Skip to content

Commit

Permalink
feat(node/url): add url.urlToHttpOptions(url) (#1426)
Browse files Browse the repository at this point in the history
  • Loading branch information
Hirotaka Tagawa / wafuwafu13 authored Oct 19, 2021
1 parent a3257fa commit 6024dd3
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 1 deletion.
4 changes: 3 additions & 1 deletion node/_tools/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
"test-net-server-call-listen-multiple-times.js",
"test-net-server-try-ports.js",
"test-net-write-arguments.js",
"test-url-format-whatwg.js"
"test-url-format-whatwg.js",
"test-url-urltooptions.js"
],
"pummel": [
"test-net-write-callbacks.js"
Expand Down Expand Up @@ -147,6 +148,7 @@
"test-url-fileurltopath.js",
"test-url-format-whatwg.js",
"test-url-pathtofileurl.js",
"test-url-urltooptions.js",
"test-util-inherits.js"
],
"pummel": [
Expand Down
45 changes: 45 additions & 0 deletions node/_tools/suites/parallel/test-url-urltooptions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// deno-fmt-ignore-file
// deno-lint-ignore-file

// Copyright Joyent and Node contributors. All rights reserved. MIT license.
// Taken from Node 16.11.1
// This file is automatically generated by "node/_tools/setup.ts". Do not modify this file manually

'use strict';
require('../common');
const assert = require('assert');
const { urlToHttpOptions } = require('url');

// Test urlToHttpOptions
const urlObj = new URL('http://user:[email protected]:21/aaa/zzz?l=24#test');
const opts = urlToHttpOptions(urlObj);
assert.strictEqual(opts instanceof URL, false);
assert.strictEqual(opts.protocol, 'http:');
assert.strictEqual(opts.auth, 'user:pass');
assert.strictEqual(opts.hostname, 'foo.bar.com');
assert.strictEqual(opts.port, 21);
assert.strictEqual(opts.path, '/aaa/zzz?l=24');
assert.strictEqual(opts.pathname, '/aaa/zzz');
assert.strictEqual(opts.search, '?l=24');
assert.strictEqual(opts.hash, '#test');

const { hostname } = urlToHttpOptions(new URL('http://[::1]:21'));
assert.strictEqual(hostname, '::1');

// If a WHATWG URL object is copied, it is possible that the resulting copy
// contains the Symbols that Node uses for brand checking, but not the data
// properties, which are getters. Verify that urlToHttpOptions() can handle
// such a case.
const copiedUrlObj = { ...urlObj };
const copiedOpts = urlToHttpOptions(copiedUrlObj);
assert.strictEqual(copiedOpts instanceof URL, false);
assert.strictEqual(copiedOpts.protocol, undefined);
assert.strictEqual(copiedOpts.auth, undefined);
assert.strictEqual(copiedOpts.hostname, undefined);
// TODO(wafuwafu13): Fix `AssertionError: Values have the same structure but are not reference-equal`
// assert.strictEqual(copiedOpts.port, NaN);
assert.strictEqual(copiedOpts.path, '');
assert.strictEqual(copiedOpts.pathname, undefined);
assert.strictEqual(copiedOpts.search, undefined);
assert.strictEqual(copiedOpts.hash, undefined);
assert.strictEqual(copiedOpts.href, undefined);
51 changes: 51 additions & 0 deletions node/url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,9 +265,60 @@ export function pathToFileURL(filepath: string): URL {
return outURL;
}

interface HttpOptions {
protocol: string;
hostname: string;
hash: string;
search: string;
pathname: string;
path: string;
href: string;
port?: number;
auth?: string;
}

/**
* This utility function converts a URL object into an ordinary options object as expected by the `http.request()` and `https.request()` APIs.
* @param url The `WHATWG URL` object to convert to an options object.
* @returns HttpOptions
* @returns HttpOptions.protocol Protocol to use.
* @returns HttpOptions.hostname A domain name or IP address of the server to issue the request to.
* @returns HttpOptions.hash The fragment portion of the URL.
* @returns HttpOptions.search The serialized query portion of the URL.
* @returns HttpOptions.pathname The path portion of the URL.
* @returns HttpOptions.path Request path. Should include query string if any. E.G. `'/index.html?page=12'`. An exception is thrown when the request path contains illegal characters. Currently, only spaces are rejected but that may change in the future.
* @returns HttpOptions.href The serialized URL.
* @returns HttpOptions.port Port of remote server.
* @returns HttpOptions.auth Basic authentication i.e. `'user:password'` to compute an Authorization header.
*/
function urlToHttpOptions(url: URL): HttpOptions {
const options: HttpOptions = {
protocol: url.protocol,
hostname: typeof url.hostname === "string" &&
url.hostname.startsWith("[")
? url.hostname.slice(1, -1)
: url.hostname,
hash: url.hash,
search: url.search,
pathname: url.pathname,
path: `${url.pathname || ""}${url.search || ""}`,
href: url.href,
};
if (url.port !== "") {
options.port = Number(url.port);
}
if (url.username || url.password) {
options.auth = `${decodeURIComponent(url.username)}:${
decodeURIComponent(url.password)
}`;
}
return options;
}

export default {
format,
fileURLToPath,
pathToFileURL,
urlToHttpOptions,
URL,
};

0 comments on commit 6024dd3

Please sign in to comment.