Can I use require(“path”).join to safely concatena

2019-02-01 03:17发布

问题:

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.

回答1:

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".



回答2:

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:

'http://www.google.com/a/b/cd?foo=123'



回答3:

No! On Windows path.join will join with backslashes. HTTP urls are always forward slashes.

How about

> ["posts", "2013"].join("/")
'posts/2013'


回答4:

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("/")


回答5:

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');


回答6:

We do it like this:

var _ = require('lodash');

function urlJoin(a, b) {
  return _.trimEnd(a, '/') + '/' + _.trimStart(b, '/');
}


回答7:

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



回答8:

Axios has a helper function that can combine URLs.

function combineURLs(baseURL, relativeURL) {
  return relativeURL
    ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '')
    : baseURL;
}

Source: https://github.com/axios/axios/blob/fe7d09bb08fa1c0e414956b7fc760c80459b0a43/lib/helpers/combineURLs.js



回答9:

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.