167

这是否可以安全地用于require("path").join连接 URL,例如:

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 的代码的情况下这样做?

4

15 回答 15

204

No.path.join()与 URL 一起使用时会返回不正确的值。

这听起来像你想要new URL()的。来自WHATWG URL 标准

new URL('/one', 'http://example.com/').href    // 'http://example.com/one'
new URL('/two', 'http://example.com/one').href // 'http://example.com/two'

请注意,url.resolve现在在Node 文档中标记为已弃用。

正如 Andreas 在评论中正确指出的那样,url.resolve(也已弃用)只有在问题与示例一样简单时才会有所帮助。 url.parse也适用于这个问题,因为它通过URL对象返回一致且可预测的格式化字段,从而减少了对“充满 ifs 的代码”的需求。但是,new URL()也是url.parse.

于 2013-04-30T14:07:04.187 回答
55

不,您不应该使用path.join()来加入 URL 元素。

现在有一个包可以做到这一点。因此,与其重新发明轮子、编写所有自己的测试、查找错误、修复它们、编写更多测试、找到它不起作用的边缘情况等,不如使用这个包。

网址连接

https://github.com/jfromaniello/url-join

安装

npm install url-join

用法

var urljoin = require('url-join');

var fullUrl = urljoin('http://www.google.com', 'a', '/b/cd', '?foo=123');

console.log(fullUrl);

印刷:

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

于 2016-09-28T05:10:48.963 回答
19

Axios有一个帮助函数,可以组合 URL。

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

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

于 2018-04-22T13:59:43.793 回答
17

这可以通过 Node 的pathURL的组合来完成:

  1. 需要软件包:
const nodeUrl = require('url')
const nodePath = require('path')
  1. 首先创建一个可以使用的 URL 对象:
> const myUrl = new nodeUrl.URL('https://example.com')
  1. 使用pathname=andpath.join构造任何可能的组合:
> myUrl.pathname = nodePath.join('/search', 'for', '/something/')
'/search/for/something/'

(你可以看到path.join论点是多么的自由)

  1. 此时,您的 URL 反映了最终所需的结果:
> myUrl.toString()
'https://example.com/search/for/something/'

为什么采用这种方法?

该技术使用内置库。在 CVE、维护等方面,第三方依赖项越少越好。

没有什么比标准库更能证明或更好地测试了。

PS:永远不要将 URL 当作字符串来操作!

当我查看代码时,我坚持永远不要手动将 URL 操作为字符串。一方面,看看规范有多复杂。

其次,尾随/前缀斜杠 ( ) 的缺失/存在/不应导致一切中断!你不应该这样做:

const url = `${baseUrl}/${somePath}`

尤其不是:

uri: host + '/' + SAT_SERVICE + '/' + CONSTELLATION + '/',

其中我见过。

于 2020-07-23T06:33:27.573 回答
8

WHATWG URL 对象构造函数有一个(input, base)版本,并且input可以是相对的,使用/, ./, ../。结合它path.posix.join,你可以做任何事情:

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'
于 2019-08-02T12:00:50.363 回答
6

当我尝试使用 PATH 连接 url 部分时,我遇到了问题。 PATH.join将 '//' 删除为 '/',这样会使绝对 URL 无效(例如 http://... -> http:/...)。对我来说,一个快速的解决方法是:

baseurl.replace(/\/$/,"") + '/' + path.replace(/^\//,"") )

或使用上校恐慌发布的解决方案:

[pathA.replace(/^\/|\/$/g,""),pathB.replace(/^\/|\/$/g,"")].join("/")
于 2013-06-06T11:46:08.577 回答
5

不!在 Windowspath.join上将加入反斜杠。HTTP url 总是正斜杠。

怎么样

> ["posts", "2013"].join("/")
'posts/2013'
于 2013-04-30T13:50:55.180 回答
5

我们这样做:

var _ = require('lodash');

function urlJoin(a, b) {
  return _.trimEnd(a, '/') + '/' + _.trimStart(b, '/');
}
于 2016-02-08T14:49:31.690 回答
5

如果你使用lodash,你可以使用这个简单的 oneliner:

// returns part1/part2/part3
['part1/', '/part2', '/part3/'].map((s) => _.trim(s, '/')).join('/')

@Peter Dotchev 的回答启发

于 2017-06-08T07:17:25.970 回答
3

如果你使用 Angular,你可以使用Location

import { Location } from '@angular/common';
// ...
Location.joinWithSlash('beginning', 'end');

但仅适用于 2 个参数,因此如果需要,您必须链接调用或编写辅助函数来执行此操作。

于 2018-10-30T18:06:06.280 回答
2

这就是我使用的:

function joinUrlElements() {
  var re1 = new RegExp('^\\/|\\/$','g'),
      elts = Array.prototype.slice.call(arguments);
  return elts.map(function(element){return element.replace(re1,""); }).join('/');
}

例子:

url = joinUrlElements(config.mgmtServer, '/v1/o/', config.org, '/apps');
于 2015-02-18T19:46:06.467 回答
1

还有其他可行的答案,但我选择了以下内容。一个小 path.join/URL 组合。

const path = require('path');
//
const baseUrl = 'http://ejemplo.mx';
// making odd shaped path pieces to see how they're handled.
const pieces = ['way//', '//over/', 'there/'];
//
console.log(new URL(path.join(...pieces), baseUrl).href);
// http://ejemplo.mx/way/over/there/

// path.join expects strings. Just an example how to ensure your pieces are Strings.
const allString = ['down', 'yonder', 20000].map(String);
console.log(new URL(path.join(...allString), baseUrl).href);
// http://ejemplo.mx/down/yonder/20000
于 2020-04-20T19:57:39.003 回答
1

到发布此答案时url.resolve(),已弃用;

我做了以下加入Nodejs中的路径:

const path = require('path');
const url = require('url');


let myUrl = new URL('http://ignore.com');
myUrl.pathname=path.join(firstpath, secondpath);
console.log(myUrl.pathname)

这种方法记录正确的 url 路径,它适用于我的情况。

您对这种方法有何看法?

谢谢

于 2020-10-23T19:46:42.393 回答
0

我的解决方案

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

编辑:如果你想支持 Windows 环境

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

第二种解决方案将替换所有反斜杠,因此查询字符串和哈希之类的 url 部分也可能会更改,但主题只是加入 url 路径,所以我不认为这是一个问题。

于 2020-02-13T09:29:24.887 回答
0

打字稿自定义解决方案:

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');
于 2019-05-24T10:55:32.950 回答