web-dev-qa-db-ja.com

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

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でいっぱいのコードを記述せずにこれを行うにはどのような方法をお勧めしますか?

93
Renato Gama

いいえ。path.join()は、URLと共に使用すると、誤った値を返します。

url.resolveNode 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'

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

109

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

今それを行うためのパッケージがあります。したがって、車輪を再発明し、独自のテストをすべて作成し、バグを見つけ、それらを修正し、さらにテストを作成し、機能しないEdgeケースを見つけるなどするのではなく、このパッケージを使用できます。

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=12 '

36
stone

URLパーツを連結するためにPATHを試したときに、問題が発生しました。 PATH.joinストライプ '//'を '/'にすると、絶対URLが無効になります(例:http:// ...-> http:/ ...)。私にとって簡単な修正は:

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

または、Colonel Panicが投稿したソリューションを使用:

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

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

どう?

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

このようにします:

var _ = require('lodash');

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

Axiosには、URLを結合できるヘルパー関数があります。

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

ソース: https://github.com/axios/axios/blob/fe7d09bb08fa1c0e414956b7fc760c80459b0a43/lib/helpers/combineURLs.js

4
Ikbel

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

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

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

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

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

2
Mic

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

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

@ Peter Dotchev's answer

2
M K

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
Coderer

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
Patrick Wozniak