Legacy URL API
History
The legacy urlObject (require('node:url').Url or
import { Url } from 'node:url') is
created and returned by the url.parse() function.
The auth property is the username and password portion of the URL, also
referred to as userinfo. This string subset follows the protocol and
double slashes (if present) and precedes the host component, delimited by @.
The string is either the username, or it is the username and password separated
by :.
For example: 'user:pass'.
The hash property is the fragment identifier portion of the URL including the
leading # character.
For example: '#hash'.
The host property is the full lower-cased host portion of the URL, including
the port if specified.
For example: 'sub.example.com:8080'.
The hostname property is the lower-cased host name portion of the host
component without the port included.
For example: 'sub.example.com'.
The href property is the full URL string that was parsed with both the
protocol and host components converted to lower-case.
For example: 'http://user:pass@sub.example.com:8080/p/a/t/h?query=string#hash'.
The path property is a concatenation of the pathname and search
components.
For example: '/p/a/t/h?query=string'.
No decoding of the path is performed.
The pathname property consists of the entire path section of the URL. This
is everything following the host (including the port) and before the start
of the query or hash components, delimited by either the ASCII question
mark (?) or hash (#) characters.
For example: '/p/a/t/h'.
No decoding of the path string is performed.
The port property is the numeric port portion of the host component.
For example: '8080'.
The protocol property identifies the URL's lower-cased protocol scheme.
For example: 'http:'.
The query property is either the query string without the leading ASCII
question mark (?), or an object returned by the querystring module's
parse() method. Whether the query property is a string or object is
determined by the parseQueryString argument passed to url.parse().
For example: 'query=string' or {'query': 'string'}.
If returned as a string, no decoding of the query string is performed. If returned as an object, both keys and values are decoded.
The search property consists of the entire "query string" portion of the
URL, including the leading ASCII question mark (?) character.
For example: '?query=string'.
No decoding of the query string is performed.
The slashes property is a boolean with a value of true if two ASCII
forward-slash characters (/) are required following the colon in the
protocol.
url.format
History
ERR_INVALID_URL exception when Punycode conversion of a hostname introduces changes that could cause the URL to be re-parsed differently.file: scheme will now always use the correct number of slashes regardless of slashes option. A falsy slashes option with no protocol is now also respected at all times.url.format(urlObject): string
The url.format() method returns a formatted URL string derived from
urlObject.
const url = require('node:url'); url.format({ protocol: 'https', hostname: 'example.com', pathname: '/some/path', query: { page: 1, format: 'json', }, }); // => 'https://example.com/some/path?page=1&format=json'
If urlObject is not an object or a string, url.format() will throw a
TypeError.
The formatting process operates as follows:
- A new empty string
resultis created. - If
urlObject.protocolis a string, it is appended as-is toresult. - Otherwise, if
urlObject.protocolis notundefinedand is not a string, anErroris thrown. - For all string values of
urlObject.protocolthat do not end with an ASCII colon (:) character, the literal string:will be appended toresult. - If either of the following conditions is true, then the literal string
//will be appended toresult:urlObject.slashesproperty is true;urlObject.protocolbegins withhttp,https,ftp,gopher, orfile;
- If the value of the
urlObject.authproperty is truthy, and eitherurlObject.hostorurlObject.hostnameare notundefined, the value ofurlObject.authwill be coerced into a string and appended toresultfollowed by the literal string@. - If the
urlObject.hostproperty isundefinedthen:- If the
urlObject.hostnameis a string, it is appended toresult. - Otherwise, if
urlObject.hostnameis notundefinedand is not a string, anErroris thrown. - If the
urlObject.portproperty value is truthy, andurlObject.hostnameis notundefined:- The literal string
:is appended toresult, and - The value of
urlObject.portis coerced to a string and appended toresult.
- The literal string
- If the
- Otherwise, if the
urlObject.hostproperty value is truthy, the value ofurlObject.hostis coerced to a string and appended toresult. - If the
urlObject.pathnameproperty is a string that is not an empty string:- If the
urlObject.pathnamedoes not start with an ASCII forward slash (/), then the literal string'/'is appended toresult. - The value of
urlObject.pathnameis appended toresult.
- If the
- Otherwise, if
urlObject.pathnameis notundefinedand is not a string, anErroris thrown. - If the
urlObject.searchproperty isundefinedand if theurlObject.queryproperty is anObject, the literal string?is appended toresultfollowed by the output of calling thequerystringmodule'sstringify()method passing the value ofurlObject.query. - Otherwise, if
urlObject.searchis a string:- If the value of
urlObject.searchdoes not start with the ASCII question mark (?) character, the literal string?is appended toresult. - The value of
urlObject.searchis appended toresult.
- If the value of
- Otherwise, if
urlObject.searchis notundefinedand is not a string, anErroris thrown. - If the
urlObject.hashproperty is a string:- If the value of
urlObject.hashdoes not start with the ASCII hash (#) character, the literal string#is appended toresult. - The value of
urlObject.hashis appended toresult.
- If the value of
- Otherwise, if the
urlObject.hashproperty is notundefinedand is not a string, anErroris thrown. resultis returned.
An automated migration is available (source).
npx codemod@latest @nodejs/node-url-to-whatwg-url
url.format(urlString): string
url.format(urlString) is shorthand for url.format(url.parse(urlString)).
Because it invokes the deprecated url.parse() internally, passing a string argument
to url.format() is itself deprecated.
Canonicalizing a URL string can be performed using the WHATWG URL API, by
constructing a new URL object and calling url.toString().
import { URL } from 'node:url'; const unformatted = 'http://[fe80:0:0:0:0:0:0:1]:/a/b?a=b#abc'; const formatted = new URL(unformatted).toString(); console.log(formatted); // Prints: http://[fe80::1]/a/b?a=b#abc
const { URL } = require('node:url'); const unformatted = 'http://[fe80:0:0:0:0:0:0:1]:/a/b?a=b#abc'; const formatted = new URL(unformatted).toString(); console.log(formatted); // Prints: http://[fe80::1]/a/b?a=b#abc
url.parse
History
--pending-deprecation.pathname property on the returned URL object is now / when there is no path and the protocol scheme is ws: or wss:.search property on the returned URL object is now null when no query string is present.url.parse(urlString, parseQueryString?, slashesDenoteHost?): void
stringbooleantrue, the query property will always
be set to an object returned by the querystring module's parse()
method. If false, the query property on the returned URL object will be an
unparsed, undecoded string. Default: false.booleantrue, the first token after the literal
string // and preceding the next / will be interpreted as the host.
For instance, given //foo/bar, the result would be
{host: 'foo', pathname: '/bar'} rather than {pathname: '//foo/bar'}.
Default: false.The url.parse() method takes a URL string, parses it, and returns a URL
object.
A TypeError is thrown if urlString is not a string.
A URIError is thrown if the auth property is present but cannot be decoded.
url.parse() uses a lenient, non-standard algorithm for parsing URL
strings. It is prone to security issues such as host name spoofing
and incorrect handling of usernames and passwords. Do not use with untrusted
input. CVEs are not issued for url.parse() vulnerabilities. Use the
WHATWG URL API instead, for example:
function getURL(req) { const proto = req.headers['x-forwarded-proto'] || 'https'; const host = req.headers['x-forwarded-host'] || req.headers.host || 'example.com'; return new URL(`${proto}://${host}${req.url || '/'}`); }
The example above assumes well-formed headers are forwarded from a reverse proxy to your Node.js server. If you are not using a reverse proxy, you should use the example below:
function getURL(req) { return new URL(`https://example.com${req.url || '/'}`); }
An automated migration is available (source).
npx codemod@latest @nodejs/node-url-to-whatwg-url
url.resolve
History
auth fields are now kept intact when from and to refer to the same host.port field is copied correctly now.auth fields is cleared now the to parameter contains a hostname.url.resolve(from, to): void
The url.resolve() method resolves a target URL relative to a base URL in a
manner similar to that of a web browser resolving an anchor tag.
const url = require('node:url'); url.resolve('/one/two/three', 'four'); // '/one/two/four' url.resolve('http://example.com/', '/one'); // 'http://example.com/one' url.resolve('http://example.com/one', '/two'); // 'http://example.com/two'
Because it invokes the deprecated url.parse() internally, url.resolve() is itself deprecated.
To achieve the same result using the WHATWG URL API:
function resolve(from, to) { const resolvedUrl = new URL(to, new URL(from, 'resolve://')); if (resolvedUrl.protocol === 'resolve:') { // `from` is a relative URL. const { pathname, search, hash } = resolvedUrl; return pathname + search + hash; } return resolvedUrl.toString(); } resolve('/one/two/three', 'four'); // '/one/two/four' resolve('http://example.com/', '/one'); // 'http://example.com/one' resolve('http://example.com/one', '/two'); // 'http://example.com/two'