diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index bbdd6e03c9f641..6d0b6a1b72d377 100644 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -45,7 +45,7 @@ const EventEmitter = require('events'); const fs = require('fs'); const http = require('http'); const { readUInt16BE, readUInt32BE } = require('internal/buffer'); -const { URL } = require('internal/url'); +const { URL, getURLOrigin } = require('internal/url'); const net = require('net'); const { Duplex } = require('stream'); const tls = require('tls'); @@ -636,7 +636,7 @@ function initOriginSet(session) { // We have to ensure that it is a properly serialized // ASCII origin string. The socket.servername might not // be properly ASCII encoded. - originSet.add((new URL(originString)).origin); + originSet.add(getURLOrigin(originString)); } } return originSet; @@ -1641,7 +1641,7 @@ class ServerHttp2Session extends Http2Session { let origin; if (typeof originOrStream === 'string') { - origin = (new URL(originOrStream)).origin; + origin = getURLOrigin(originOrStream); if (origin === 'null') throw new ERR_HTTP2_ALTSVC_INVALID_ORIGIN(); } else if (typeof originOrStream === 'number') { @@ -1693,7 +1693,7 @@ class ServerHttp2Session extends Http2Session { for (let i = 0; i < count; i++) { let origin = origins[i]; if (typeof origin === 'string') { - origin = (new URL(origin)).origin; + origin = getURLOrigin(origin); } else if (origin != null && typeof origin === 'object') { origin = origin.origin; } diff --git a/lib/internal/url.js b/lib/internal/url.js index ccd89830f91ded..7227aac12a7762 100644 --- a/lib/internal/url.js +++ b/lib/internal/url.js @@ -1436,6 +1436,16 @@ function toPathIfFileURL(fileURLOrPath) { return fileURLToPath(fileURLOrPath); } +/** + * This util takes a string containing a URL and return the URL origin, + * its meant to avoid calls to `new URL` constructor. + * @param {string} url + * @returns {URL['origin']} + */ +function getURLOrigin(url) { + return bindingUrl.getOrigin(url); +} + module.exports = { toUSVString, fileURLToPath, @@ -1451,4 +1461,5 @@ module.exports = { isURL, urlUpdateActions: updateActions, + getURLOrigin, }; diff --git a/src/node_errors.h b/src/node_errors.h index ddb87df20ef4af..b3060e7b41c396 100644 --- a/src/node_errors.h +++ b/src/node_errors.h @@ -73,6 +73,7 @@ void AppendExceptionLine(Environment* env, V(ERR_INVALID_STATE, Error) \ V(ERR_INVALID_THIS, TypeError) \ V(ERR_INVALID_TRANSFER_OBJECT, TypeError) \ + V(ERR_INVALID_URL, TypeError) \ V(ERR_MEMORY_ALLOCATION_FAILED, Error) \ V(ERR_MESSAGE_TARGET_CONTEXT_UNAVAILABLE, Error) \ V(ERR_MISSING_ARGS, TypeError) \ diff --git a/src/node_url.cc b/src/node_url.cc index ef845c612ef464..d1ae2e9b502755 100644 --- a/src/node_url.cc +++ b/src/node_url.cc @@ -117,6 +117,30 @@ void BindingData::DomainToUnicode(const FunctionCallbackInfo& args) { .ToLocalChecked()); } +void BindingData::GetOrigin(const v8::FunctionCallbackInfo& args) { + CHECK_GE(args.Length(), 1); + CHECK(args[0]->IsString()); // input + + Environment* env = Environment::GetCurrent(args); + HandleScope handle_scope(env->isolate()); + + Utf8Value input(env->isolate(), args[0]); + std::string_view input_view = input.ToStringView(); + auto out = ada::parse(input_view); + + if (!out) { + THROW_ERR_INVALID_URL(env, "Invalid URL"); + return; + } + + std::string origin = out->get_origin(); + args.GetReturnValue().Set(String::NewFromUtf8(env->isolate(), + origin.data(), + NewStringType::kNormal, + origin.length()) + .ToLocalChecked()); +} + void BindingData::CanParse(const FunctionCallbackInfo& args) { CHECK_GE(args.Length(), 1); CHECK(args[0]->IsString()); // input @@ -322,6 +346,7 @@ void BindingData::CreatePerIsolateProperties(IsolateData* isolate_data, SetMethodNoSideEffect(isolate, target, "domainToASCII", DomainToASCII); SetMethodNoSideEffect(isolate, target, "domainToUnicode", DomainToUnicode); SetMethodNoSideEffect(isolate, target, "format", Format); + SetMethodNoSideEffect(isolate, target, "getOrigin", GetOrigin); SetMethod(isolate, target, "parse", Parse); SetMethod(isolate, target, "update", Update); SetFastMethodNoSideEffect( @@ -341,6 +366,7 @@ void BindingData::RegisterExternalReferences( registry->Register(DomainToASCII); registry->Register(DomainToUnicode); registry->Register(Format); + registry->Register(GetOrigin); registry->Register(Parse); registry->Register(Update); registry->Register(CanParse); diff --git a/src/node_url.h b/src/node_url.h index dffe4b63ef11ad..8849e59be1f79a 100644 --- a/src/node_url.h +++ b/src/node_url.h @@ -53,6 +53,7 @@ class BindingData : public SnapshotableObject { const v8::FastOneByteString& input); static void Format(const v8::FunctionCallbackInfo& args); + static void GetOrigin(const v8::FunctionCallbackInfo& args); static void Parse(const v8::FunctionCallbackInfo& args); static void Update(const v8::FunctionCallbackInfo& args);