require(“ path”)。joinを使用して安全にURLを連結できますか?


128

これは、require("path").joinURLを連結するために使用しても安全ですか?

require("path").join("http://example.com", "ok"); 
//returns 'http://example.com/ok'

require("path").join("http://example.com/", "ok"); 
//returns 'http://example.com/ok'

そうでない場合、ifsでいっぱいのコードを記述せずにこれを行うにはどのような方法を提案しますか?



5
場合には誰もがWindows上でpath.joinが、回避の問題を使用したい:path.posix.join('/one/two/three', 'four') // '/one/two/three/fourpath.posix.join('/one/two/three/', 'four') // '/one/two/three/fourpath.posix.join('/one/two/three/', '/four') // '/one/two/three/four
ティモシー・ソーン

5
@TimothyZorn問題は、このようなことをするpath.posix.join('http://localhost:9887/one/two/three/', '/four')と、結合がダブルスラッシュの1つを取り除くことですhttp://
Max Alexander

ああ、そう-良い点。これらのシナリオでは、次のようなことをしたいと思います。正​​規表現を何度も入力したくない場合は、そうする'http://localhost:9887/one/two/three/'.replace(/^\/+|\/+$/, '') + '/' + '/four'.replace(/^\/+|\/+$/, '')ことができますString.prototype.trimSlashes = function() { return this.replace(/^\/+|\/+$/, ''); }stackoverflow.com/a/22387870/2537258
ティモシーゾーン

または['http://localhost:9887/one/two/three/', '/four'].map((part) => part. replace(/^\/+|\/+$/, '')).join('/')
ティモシーゾーン2017

回答:


141

いいえ path.join()。URLと一緒に使用すると、誤った値が返されます。

あなたが望むように聞こえますurl.resolveノードのドキュメントから:

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'

編集: アンドレアスがコメントで正しく指摘しているのでurl.resolve、問題が例のように単純である場合にのみ役立つでしょう。 「ifsの完全なコード」の必要性を減らすオブジェクトをurl.parse介して一貫して予測可能な形式のフィールドを返すため、この質問にも適用されますURL


1
正確にこれを探していたわけではありませんが、私の問題も解決します。助けてくれてありがとう!
レナート・ガマ

6
@AndreasHultgren最初のコメントは正しいです。この例の場合、url.resolve('/one/two/three/', 'four')出力はになります'one/two/three/four'
tavnab 2016年

3
場合には誰もがWindows上でpath.joinが、回避の問題を使用したい:path.posix.join('/one/two/three', 'four') // '/one/two/three/fourpath.posix.join('/one/two/three/', 'four') // '/one/two/three/fourpath.posix.join('/one/two/three/', '/four') // '/one/two/three/four
ティモシー・ソーン

2
コメントは正しくありませんurl.resolve('/one/two/three', 'four') // '/one/two/four'

2
またurl.resolve()、as path.join()は任意の数を取る2つの引数のみを取ることに注意してください。したがって、何をしているのかによっては、呼び出しをネストする必要があるかもしれません。例えば、url.resolve(url.resolve(SERVER_URL, pagePath), queryString)
Molomby

47

いいえ、path.join()URL要素の結合には使用しないでください。

今それを行うためのパッケージがあります。したがって、ホイールを作り直すのではなく、独自のすべてのテストを記述し、バグを見つけ、修正し、さらにテストを記述し、機能しないエッジケースを見つけるなど、このパッケージを使用できます。

url-join

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 '


1
この。これは素晴らしいです。ありがとうございました。
dudewad 2016年


6

URL部分を連結するためにPATHを試したところ、問題が発生しました。 PATH.join'//'を '/'にストライプし、この方法で絶対URLを無効にします(例:http:// ...-> http:/ ...)。私にとって簡単な修正は:

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

またはパニック大佐が投稿した解決策を使用して:

[pathA.replace(/^\/|\/$/g,""),pathB.replace(/^\/|\/$/g,"")].join("/")

次のようなルート相対URLを作成しようとしている場合はどうなります/assets/fooか?結果はcurrent-path-relative URLになりますassets/foo
Andrey Mikhaylov-lolmaus

5

番号!Windowsではpath.joinバックスラッシュで結合されます。HTTP URLは常にスラッシュです。

いかがですか

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

良い考えですが、最初の引数の最後にすでにスラッシュがある場合はどうなりますか?例:["posts/", "2013"].join("/")
Renato Gama

1
@RenatoGama posts//2013は引き続き有効なURLです。
Goodwine 2013

2
^有効なURIであっても、すべてのドメインで機能するわけではありません。
BingeBoy 2015年

2
具体的には、Node's Expressはルーティングに無関係なスラッシュを無視しません。
Perseids、2016

1
場合には誰もがWindows上回避の問題はpath.joinを使用したいが、: 、、path.posix.join('/one/two/three', 'four') // '/one/two/three/fourpath.posix.join('/one/two/three/', 'four') // '/one/two/three/fourpath.posix.join('/one/two/three/', '/four') // '/one/two/three/four
ティモシー・ソーン

5

これは次のように行います。

var _ = require('lodash');

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

4

lodashを使用している場合は、次のシンプルなワンライナーを使用できます。

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

@Peter Dotchevの回答に触発された


3

これは私が使用するものです:

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

次のようなルート相対URLを作成しようとしている場合はどうなります/assets/fooか?結果はcurrent-path-relative URLになりますassets/foo
Andrey Mikhaylov-lolmaus

1
スラッシュを追加しますか?つまり、これは簡単なチェックです。自分で追加できます。
Cheeso

3
これが始まりです...次に、累積して8時間以上をかけて、機能しないエッジケースを見つけ、プロジェクトの過程でそれらを修正したことを知っています。

3

Angularを使用する場合は、Locationを使用できます。

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

ただし、2つの引数でのみ機能するため、必要に応じて、呼び出しをチェーンするか、それを行うヘルパー関数を記述する必要があります。


2

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'

0

Typescriptカスタムソリューション:

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

0

私の解決策

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

編集:Windows環境をサポートする場合

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

2番目のソリューションはすべてのバックスラッシュを置き換えるため、クエリ文字列やハッシュなどのURLの部分も変更される可能性がありますが、トピックはURLパスのみを結合するため、問題とは見なしません。


0

他にも有効な答えはありますが、私は次のように行きました。小さな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

0

これは、ノードのパスURLの組み合わせによって実現できます

  1. パッケージが必要:
const nodeUrl = require('url')
const nodePath = require('path')
  1. まず、使用するURLオブジェクトを作成します。
> const myUrl = new nodeUrl.URL('https://example.com')
  1. pathname=path.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を文字列として手動で操作することは絶対に避けません。1つは、仕様がいかに複雑かを見てください。

第二に、末尾/接頭辞付きのスラッシュ(/)が存在しないことで、すべてが壊れてはなりません。あなたは決してすべきではありません:

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

特に:

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

このうち、コードベースで遭遇したばかりです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.