Node: Feature request: url.join(baseUrl, ...others)

Created on 22 Jan 2018  路  16Comments  路  Source: nodejs/node

  • Version: v9.4.0
  • Platform: Darwin
  • Subsystem: url

I want to join url href just like path.join, examples

url.join('http://nodejs.org', 'dist', 'download') === 'http://nodejs.org/dist/download'
url.join('http://nodejs.org/dist', 'download') === 'http://nodejs.org/dist/download'
url.resolve('http://nodejs.org/dist', 'download') === 'http://nodejs.org/download'
url.join('http://nodejs.org/dist/', '/download') === 'http://nodejs.org/dist/download'
url.join('http://nodejs.org/dist', 'http://mirror.nodejs.org/dist') === 'http://mirror.nodejs.org/dist'

// without protocol prefix, just like path.join
url.join('nodejs.org', 'dist', 'download') === path.join('nodejs.org', 'dist', 'download') === 'nodejs.org/dist/download'

What do you think about this?

question url

Most helpful comment

So, we can't have a function that everybody needs all the time because of semantical correctness?

All 16 comments

How does this differ from [baseUrl, ...others].join('/')?

In any case, we are trying to move away from legacy URL APIs like url.resolve() in favor of the WHATWG standard-compliant API. We probably will not consider this addition.

In some case, others maybe ['/foo', 'bar/', '/baz/']. I want path.join('http://nodejs.org', ...others) to return http://nodejs.org/foo/bar/baz/. In your code, ['http://nodejs.org', ...others].join('/') would get http://nodejs.org//foo/bar//baz/.

BTW, like path.join. You cannot use [...paths].join(path.sep) to replace it.

http://nodejs.org//foo/bar//baz/ is a valid URL that may have a different meaning from http://nodejs.org/foo/bar/baz/. It would be semantically incorrect to disallow this distinction.

There doesn't seem to be anything actionable here as such I'm going to close this.

Use it:

function joinAbsoluteUrlPath(...args: string[]) {
    return "/" + args.map( pathPart => pathPart.replace(/(^\/|\/$)/g, "") ).join("/");
}

joinAbsoluteUrlPath("a/b", "/c/d/", "/e", "f/g", "h")  // "/a/b/c/d/e/f/g/h"

So, we can't have a function that everybody needs all the time because of semantical correctness?

@waynebloss create RFC for this and refer to it and then it is possible that it will be part of Node built-in function in next few months.

@TimothyGu fyi. here you have use case:

  • developer is taking url path fragments (eg. host with path prefix and target path suffix) from config files and service discovery service. Developer cannot be sure wether path provided by someone responsible for config file (or source that dynamically provides path) starts and ends with or without "/". This is the case I met all the time.

For those that come across this later, consider a combination of url.format({protocol, hostname, port}) and path.posix.join. If you don't pass a pathname to format then you will get exactly the origin of the absolute URL, no trailing slash. Then, you just have to make sure the first token you pass to path.posix.join has a leading slash. From there, all your arguments to join can have leading or trailing slashes, no problem.

Been stuck today with this simple issue. Kind of obvious to have resolve, which "resolves" url using all the semantic, but join should be there too, providing different semantic, meaning different function.

Falling back to use urljoin package from the npm.

Our usecase: use base url for CDN and append path to the asset. CDN url can come with or w/o the ending slash.

Have you tried url.format combined with path.posix.join as in my previous comment?

@thw0rted we didn't, but I'm sure it works. The problem I have with such a method is, it is too low-levelly to use posix-specific function to calculate URL paths...

Coming from the very different tech stacks and languages, it feels so weird that no one treats node as BE tech, which has a need to provide common library, close or similar to other stacks, so entry-level will be lower, approaches will be same and code review will be easier.

I see that Node tries to provide same API between browser and server, so if browser does not have a function, Node should not have it too. Which is wise. For SSR, SPA.

But Node is not just a platform for SSR.

My solution
path.join(SERVER_URL, imageAbsolutePath).replace(':/','://');
Edit: if you want to support windows enviroments
path.join(SERVER_URL, imageAbsolutePath).replace(/\\/g,'/').replace(':/','://');
The second solution will replace all the backslashes, so url parts like querystring and hash may be altered too, but if you need to join just the url path that's not an issue.

My solution

path.join(SERVER_URL, imageAbsolutePath).replace(':/','://');

Please be careful it does not work on Windows, since path.join converted / to \.

That's why I suggested path.posix.join in my posts last year -- you're guaranteed the correct behavior regardless of platform.

My 2 cents - it's incredibly ridiculous and overly pedantic if nodejs libraries cannot provide a proper URL path-joining helper. Yes, technically // can be in a URL, but 99.99999999% of the time when we construct URLs we do not desire this. Just make a helper that explicitly calls out in its documentation that it doesn't leave in duplicate //. There, problem solved, you can do anything without violating semantics as long as you document it and are explicit.

Also, for what it's worth, other major languages provide this, e.g. the UriBuilder#path helper in Java since Java7 has this semantics and leaves out duplicate slashes, and adds slashes if needed - https://docs.oracle.com/javaee/7/api/javax/ws/rs/core/UriBuilder.html (it's not 100% clear from the description, but I have used it much in the past and I know it works that way).

Resorting to file-system helpers is not a good idea... because we are not building file paths! Also, this helper should automatically URL-escape any added path segments.

Url-join npm package: Weekly Downloads - 1,994,766

Was this page helpful?
0 / 5 - 0 ratings

Related issues

cong88 picture cong88  路  3Comments

Brekmister picture Brekmister  路  3Comments

addaleax picture addaleax  路  3Comments

fanjunzhi picture fanjunzhi  路  3Comments

stevenvachon picture stevenvachon  路  3Comments