-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor: tighten up cloudflare detection #3170
Conversation
Deploying node-postgres with Cloudflare Pages
|
db7d830
to
079a259
Compare
I haven’t taken a good look at pg-cloudflare yet, but I think it’s always nicer to detect the APIs that are actually needed than to detect a particular runtime, when possible. |
That was my original approach way back, where I "knew" that Cloudflare did not support The approach of trying to import from |
Trying to detect a specific platform based on API presence isn’t an example of that; trying to import |
I kicked off a discussion at Cloudflare about possibly taking a different approach by beefing up our I do think that this PR improves the situation and should be merged, otherwise we'll most likely break pg-cloudflare as we improve our node compatibility which will result in misdetection in the current version of pg-cloudflare. But ideally, we should transition completely away from a need to provide a custom socket within |
726c9cb
to
2a1cd64
Compare
The previous approach to detecting whether to use Cloudflare's sockets was to check for missing polyfills. But as we improve the polyfills that Wrangler can provide these checks are no longer valid. Now we just try to use the Cloudflare API first and fallback to Node.js if those are not available.
2a1cd64
to
74714b0
Compare
Thanks to everyone who has looked at this PR over the weeks it has been evolving. I think it is now in a good enough place to land. Could you take a last look? @brianc , @IgorMinar , @sehrope and @charmander ? |
Having multiple parts of the code handle the caching is odd. Also, that structure makes it more difficult to add other non-native stream implementations. How about something like this: function getNodejsStreamFuncs() {
function getStream(ssl) {
const net = require('net')
return new net.Socket()
}
function getSecureStream(options) {
var tls = require('tls')
return tls.connect(options)
}
return {
getStream,
getSecureStream,
}
}
function getCloudflareStreamFuncs() {
function getStream(ssl) {
const { CloudflareSocket } = require('pg-cloudflare')
return new CloudflareSocket(ssl)
}
function getSecureStream(options) {
options.socket.startTls(options)
return options.socket
}
return {
getStream,
getSecureStream,
}
}
/**
* Are we running in a Cloudflare Worker?
*
* @returns true if the code is currently running inside a Cloudflare Worker.
*/
function isCloudflareRuntime() {
// Since 2022-03-21 the `global_navigator` compatibility flag is on for Cloudflare Workers
// which means that `navigator.userAgent` will be defined.
if (typeof navigator === 'object' && navigator !== null && typeof navigator.userAgent === 'string') {
return navigator.userAgent === 'Cloudflare-Workers'
}
// In case `navigator` or `navigator.userAgent` is not defined then try a more sneaky approach
if (typeof Response === 'function') {
const resp = new Response(null, { cf: { thing: true } })
if (typeof resp.cf === 'object' && resp.cf !== null && resp.cf.thing) {
return true
}
}
return false
}
function getStreamFuncs() {
if (isCloudflareRuntime()) {
return getCloudflareStreamFuncs()
}
return getNodejsStreamFuncs()
}
module.exports = getStreamFuncs() When (if?) we ever change this repo to embed types, that lends itself to a better structure as as each of the I haven't tested the above so if you do go with that approach, obviously test it out and make sure it makes sense. Regarding the check in |
Thanks for the input @sehrope.
This is because the I did consider a solution similar to the one you propose above. The only downside is that the check for Cloudflare will not happen lazily. But I guess that it is so fundamental to get hold of such a socket that there are very few (if any) scenarios where the library will be used and not ask for a socket. So there is not much value in doing this check lazily. |
Hey I just got back from out of town - will take a look at this tomorrow! thanks! |
Code looks good to me! I'll get this merged up - thanks. @petebacondarwin are there other things y'all are blocked on wrt cf workers & pg integration? I was talking with @jrf0110 and he said there were some other issues...I'm happy to look at them. |
Hi @brianc - can we run a release of pg to get this change out there? It is needed for the new Cloudflare nodejs compatibility to work properly with this library. |
The previous approach to detecting whether to use Cloudflare's sockets was to check for missing polyfills.
But as we improve the polyfills that Wrangler can provide these checks are no longer valid.
Now we check if the
navigator.userAgent
is'Cloudflare-Workers'
and fallback to Node.js if not.This is a refactoring - there is already a test in place to check that this works.