Is this safe to use require("path").join
to concatenate URLs, for example:
require("path").join("http://example.com", "ok");
//returns 'http://example.com/ok'
require("path").join("http://example.com/", "ok");
//returns 'http://example.com/ok'
If not, what way would you suggest for doing this without writing code full of ifs?
No. path.join()
will return incorrect values when used with URLs.
It sounds like you want url.resolve
. From the Node docs:
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'
Edit:
As Andreas correctly points out in a comment, url.resolve
would only help if the problem is as simple as the example. url.parse
also applies to this question because it returns consistently and predictably formatted fields via the URL
object that reduces the need for "code full of ifs".
No, you should not use path.join()
to join URL elements.
There's a package for doing that now. So rather than reinvent the wheel, write all your own tests, find bugs, fix them, write more tests, find an edge case where it doesn't work, etc., you could use this package.
url-join
https://github.com/jfromaniello/url-join
Install
npm install url-join
Usage
var urljoin = require('url-join');
var fullUrl = urljoin('http://www.google.com', 'a', '/b/cd', '?foo=123');
console.log(fullUrl);
Prints:
No! On Windows path.join
will join with backslashes. HTTP urls are always forward slashes.
How about
> ["posts", "2013"].join("/")
'posts/2013'
When I tried PATH for concatenating url parts I run into problems.
PATH.join
stripes '//' down to '/' and this way invalidates an absolute url (eg. http://... -> http:/...).
For me a quick fix was:
baseurl.replace(/\/$/,"") + '/' + path.replace(/^\//,"") )
or with the solution posted by Colonel Panic:
[pathA.replace(/^\/|\/$/g,""),pathB.replace(/^\/|\/$/g,"")].join("/")
We do it like this:
var _ = require('lodash');
function urlJoin(a, b) {
return _.trimEnd(a, '/') + '/' + _.trimStart(b, '/');
}
Axios has a helper function that can combine URLs.
function combineURLs(baseURL, relativeURL) {
return relativeURL
? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '')
: baseURL;
}
This is what I use:
function joinUrlElements() {
var re1 = new RegExp('^\\/|\\/$','g'),
elts = Array.prototype.slice.call(arguments);
return elts.map(function(element){return element.replace(re1,""); }).join('/');
}
example:
url = joinUrlElements(config.mgmtServer, '/v1/o/', config.org, '/apps');
If you're using lodash, you can use this simple oneliner:
// returns part1/part2/part3
['part1/', '/part2', '/part3/'].map((s) => _.trim(s, '/')).join('/')
inspired by @Peter Dotchev's answer
If you use Angular, you can use Location:
import { Location } from '@angular/common';
// ...
Location.joinWithSlash('beginning', 'end');
Works only on 2 arguments though, so you have to chain calls or write a helper function to do that if needed.
Typescript custom solution:
export function pathJoin(parts: string[], sep: string) {
return parts
.map(part => {
const part2 = part.endsWith(sep) ? part.substring(0, part.length - 1) : part;
return part2.startsWith(sep) ? part2.substr(1) : part2;
})
.join(sep);
}
expect(pathJoin(['a', 'b', 'c', 'd'], '/')).toEqual('a/b/c/d');
expect(pathJoin(['a/', '/b/', 'c/', 'd'], '/')).toEqual('a/b/c/d');
expect(pathJoin(['http://abc.de', 'users/login'], '/')).toEqual('http://abc.de/users/login');
The WHATWG URL object constructor has a (input, base)
version, and the input
can be relative using /
, ./
, ../
. Combine this with path.posix.join
and you can do anything:
const {posix} = require ("path");
const withSlash = new URL("https://example.com:8443/something/");
new URL(posix.join("a", "b", "c"), withSlash).toString(); // 'https://example.com:8443/something/a/b/c'
new URL(posix.join("./a", "b", "c"), withSlash).toString(); // 'https://example.com:8443/something/a/b/c'
new URL(posix.join("/a", "b", "c"), withSlash).toString(); // 'https://example.com:8443/a/b/c'
new URL(posix.join("../a", "b", "c"), withSlash).toString(); // 'https://example.com:8443/a/b/c'
const noSlash = new URL("https://example.com:8443/something");
new URL(posix.join("./a", "b", "c"), noSlash).toString(); // 'https://example.com:8443/a/b/c'
来源:https://stackoverflow.com/questions/16301503/can-i-use-requirepath-join-to-safely-concatenate-urls