Node url.format is deprecated, what should we use instead?

Viewed 3167

I am getting warnings in VS Code that url.format from the NodeJS URL module is deprecated.

const nodeUrl = require('url')

const url = nodeUrl.format({
  protocol: 'https',
  host: 'example.com',
  pathname: 'somepath'
})

What shall I use instead? Is it fully safe to just replace the above by

const buildUrl = (url) => url.protocol + '://' + url.host + '/' + url.pathname

Are these two functions equivalent, that is, for any object input with that structure, it results in the same output? Doesn't url.format have any magic that I may miss? For example pathname with or without leading /.

My project is huge with a lot of calls to url.format and I want to be sure that nothing breaks.

edit: Apparently we should use WHATWG URL standard

Is then this the correct replacement?

const buildUrl = (url) => new URL(url.pathname, url.protocol + '://' + url.host)
2 Answers

Take a look at the documentation for URL, and be sure to note the differences in certain properties like host (includes port) vs hostname (doesn't). Based on the components in your question, it seems like you need to use a function like the following, which you can extend for your needs:

function urlFromComponents ({pathname = '/', protocol = 'https:', ...props} = {}) {
  const url = new URL('https://site.example');
  url.protocol = protocol;
  url.hostname = props.hostname;
  url.pathname = pathname;
  return url;
}

const protocol = 'https';
const hostname = 'example.com';
const pathname = 'somepath';

const url1 = urlFromComponents({
  hostname,
  pathname, // pathname will have "/" prepended if absent
  protocol, // protocol actually ends in ":", but this will also be fixed for you
});

const url2 = urlFromComponents({hostname, pathname});

console.log({url1, url2});

Node refers that the url.format method taking as input an urlObject is deprecated, although it is still a stable solution

enter image description here

We should now use the WHATWG URL API. Note that the url module fetched with require('url') provides two APIs for working with URLs: a legacy API that is Node.js specific, and a newer API that implements the same WHATWG URL Standard used by web browsers.

A one-liner solution that tries to emulate the legacy url.format method API with the new WHATWG URL Standard constructor may be

const urlFrom = (urlObject) => String(Object.assign(new URL("http://a.com"), urlObject))

Test it here

const urlFrom = (urlObject) => String(Object.assign(new URL("http://a.com"), urlObject))

const url1 = urlFrom({
  protocol: 'https',
  hostname: 'example.com',
  pathname: 'somepath'
})
console.log('url1:', url1) // https://example.com/somepath

const url2 = urlFrom({
  protocol: 'https:',
  host: 'example.com',
  pathname: '/somepath'
})
console.log('url2:', url2) // https://example.com/somepath

const url3 = urlFrom({
  protocol: 'https:',
  host: 'example.com:8080',
  pathname: '/somepath'
})
console.log('url3:', url3) // https://example.com:8080/somepath

const url4 = urlFrom({
    protocol: 'http:',
    hostname: 'example.com',
    port: 8080,
    pathname: '/somepath'
  })
console.log('url4:', url4) // http://example.com:8080/somepath

const url5 = urlFrom({
    protocol: 'https:',
    hostname: 'example.com',
    port: 8080,
    pathname: '/somepath',
    username: 'john',
    password: 'abc',
    search: 'item=bike'
  })
console.log('url5:', url5) // https://john:abc@example.com:8080/somepath?item=bike

Related