diff --git a/src/workerd/api/node/node.h b/src/workerd/api/node/node.h index ece0e756b14..180f7abefb0 100644 --- a/src/workerd/api/node/node.h +++ b/src/workerd/api/node/node.h @@ -67,7 +67,15 @@ bool isNodeJsCompatEnabled(auto featureFlags) { return featureFlags.getNodeJsCompat() || featureFlags.getNodeJsCompatV2(); } -bool isExperimentalNodeJsCompatModule(kj::StringPtr name); +constexpr bool isExperimentalNodeJsCompatModule(kj::StringPtr name) { + return name == "node:fs"_kj; +} + +constexpr bool isNodeHttpModule(kj::StringPtr name) { + return name == "node:http"_kj || name == "node:_http_common"_kj || + name == "node:_http_outgoing"_kj || name == "node:_http_client"_kj || + name == "node:_http_incoming"_kj || name == "node:_http_agent"_kj || name == "node:https"_kj; +} template void registerNodeJsCompatModules(Registry& registry, auto featureFlags) { @@ -85,7 +93,7 @@ void registerNodeJsCompatModules(Registry& registry, auto featureFlags) { bool nodeJsCompatEnabled = isNodeJsCompatEnabled(featureFlags); registry.addBuiltinBundleFiltered(NODE_BUNDLE, [&](jsg::Module::Reader module) { - // node:fs and node:http will be considered experimental until they are completed, + // node:fs will be considered experimental until it's completed, // so unless the experimental flag is enabled, don't register them. if (isExperimentalNodeJsCompatModule(module.getName())) { return featureFlags.getWorkerdExperimental(); @@ -97,6 +105,12 @@ void registerNodeJsCompatModules(Registry& registry, auto featureFlags) { return module.getType() == jsg::ModuleType::INTERNAL; } + // We put node:http and node:https modules behind a compat flag + // for securing backward compatibility. + if (isNodeHttpModule(module.getName())) { + return featureFlags.getEnableNodejsHttpModules(); + } + return true; }); diff --git a/src/workerd/api/node/tests/http-agent-nodejs-test.wd-test b/src/workerd/api/node/tests/http-agent-nodejs-test.wd-test index ffc238f050b..30442173493 100644 --- a/src/workerd/api/node/tests/http-agent-nodejs-test.wd-test +++ b/src/workerd/api/node/tests/http-agent-nodejs-test.wd-test @@ -8,7 +8,7 @@ const unitTests :Workerd.Config = ( (name = "worker", esModule = embed "http-agent-nodejs-test.js") ], compatibilityDate = "2025-01-15", - compatibilityFlags = ["nodejs_compat", "experimental"], + compatibilityFlags = ["nodejs_compat", "experimental", "enable_nodejs_http_modules"], bindings = [ (name = "PONG_SERVER_PORT", fromEnvironment = "PONG_SERVER_PORT"), ], diff --git a/src/workerd/api/node/tests/http-client-nodejs-test.wd-test b/src/workerd/api/node/tests/http-client-nodejs-test.wd-test index b4c2d57b28a..cfaa8e5b05d 100644 --- a/src/workerd/api/node/tests/http-client-nodejs-test.wd-test +++ b/src/workerd/api/node/tests/http-client-nodejs-test.wd-test @@ -8,7 +8,7 @@ const unitTests :Workerd.Config = ( (name = "worker", esModule = embed "http-client-nodejs-test.js") ], compatibilityDate = "2025-01-15", - compatibilityFlags = ["nodejs_compat", "experimental"], + compatibilityFlags = ["nodejs_compat", "experimental", "enable_nodejs_http_modules"], bindings = [ (name = "PONG_SERVER_PORT", fromEnvironment = "PONG_SERVER_PORT"), (name = "ASD_SERVER_PORT", fromEnvironment = "ASD_SERVER_PORT"), diff --git a/src/workerd/api/node/tests/http-nodejs-test.wd-test b/src/workerd/api/node/tests/http-nodejs-test.wd-test index 89aededf944..3c1fe50cf6b 100644 --- a/src/workerd/api/node/tests/http-nodejs-test.wd-test +++ b/src/workerd/api/node/tests/http-nodejs-test.wd-test @@ -8,7 +8,7 @@ const unitTests :Workerd.Config = ( (name = "worker", esModule = embed "http-nodejs-test.js") ], compatibilityDate = "2025-01-15", - compatibilityFlags = ["nodejs_compat", "experimental"], + compatibilityFlags = ["nodejs_compat", "experimental", "enable_nodejs_http_modules"], bindings = [ (name = "PONG_SERVER_PORT", fromEnvironment = "PONG_SERVER_PORT"), (name = "ASD_SERVER_PORT", fromEnvironment = "ASD_SERVER_PORT"), diff --git a/src/workerd/api/node/tests/http-outgoing-nodejs-test.wd-test b/src/workerd/api/node/tests/http-outgoing-nodejs-test.wd-test index 8139d0ebffe..6c0d4ec19c8 100644 --- a/src/workerd/api/node/tests/http-outgoing-nodejs-test.wd-test +++ b/src/workerd/api/node/tests/http-outgoing-nodejs-test.wd-test @@ -8,7 +8,7 @@ const unitTests :Workerd.Config = ( (name = "worker", esModule = embed "http-outgoing-nodejs-test.js") ], compatibilityDate = "2025-01-15", - compatibilityFlags = ["nodejs_compat", "experimental"], + compatibilityFlags = ["nodejs_compat", "experimental", "enable_nodejs_http_modules"], bindings = [ (name = "FINISH_WRITABLE_PORT", fromEnvironment = "FINISH_WRITABLE_PORT"), (name = "WRITABLE_FINISHED_PORT", fromEnvironment = "WRITABLE_FINISHED_PORT"), diff --git a/src/workerd/api/node/util.c++ b/src/workerd/api/node/util.c++ index 153b25f9412..3a258313341 100644 --- a/src/workerd/api/node/util.c++ +++ b/src/workerd/api/node/util.c++ @@ -12,12 +12,6 @@ namespace workerd::api::node { -bool isExperimentalNodeJsCompatModule(kj::StringPtr name) { - return name == "node:fs"_kj || name == "node:http"_kj || name == "node:_http_common"_kj || - name == "node:_http_outgoing"_kj || name == "node:_http_client"_kj || - name == "node:_http_incoming"_kj || name == "node:_http_agent"_kj; -} - MIMEParams::MIMEParams(kj::Maybe mimeType): mimeType(mimeType) {} // Oddly, Node.js allows creating MIMEParams directly but it's not actually diff --git a/src/workerd/io/compatibility-date.capnp b/src/workerd/io/compatibility-date.capnp index dd21903b789..8fe49f179d9 100644 --- a/src/workerd/io/compatibility-date.capnp +++ b/src/workerd/io/compatibility-date.capnp @@ -870,4 +870,10 @@ struct CompatibilityFlags @0x8f8c1b68151b6cef { # The original version of the headers sent to edgeworker were truncated to a single # value for specific header names, such as To and Cc. With this compat flag we will send # the full header values to the worker script. + + enableNodejsHttpModules @100 :Bool + $compatEnableFlag("enable_nodejs_http_modules") + $compatDisableFlag("disable_nodejs_http_modules") + $impliedByAfterDate(name = "nodeJsCompat", date = "2025-08-15"); + # Enables Node.js http related modules such as node:http and node:https }