Tôi có thể sử dụng request (“đường dẫn”). Join để nối các url một cách an toàn không?


128

Điều này có an toàn để sử dụng require("path").joinđể nối các URL, ví dụ:

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

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

Nếu không, bạn sẽ đề xuất cách nào để thực hiện việc này mà không cần viết mã đầy ifs?



5
Trong trường hợp bất cứ ai muốn sử dụng path.join, nhưng các vấn đề tránh trên Windows: path.posix.join('/one/two/three', 'four') // '/one/two/three/four, path.posix.join('/one/two/three/', 'four') // '/one/two/three/four,path.posix.join('/one/two/three/', '/four') // '/one/two/three/four
Timothy Zorn

5
@TimothyZorn Vấn đề là rằng nó nếu bạn làm điều gì đó như thế này path.posix.join('http://localhost:9887/one/two/three/', '/four'), join được thoát khỏi một trong những dấu gạch chéo đôi tronghttp://
Max Alexander

Ahh, vâng - điểm tốt. Trong những trường hợp đó, bạn muốn làm điều gì đó tương tự 'http://localhost:9887/one/two/three/'.replace(/^\/+|\/+$/, '') + '/' + '/four'.replace(/^\/+|\/+$/, '')và bạn có thể làm String.prototype.trimSlashes = function() { return this.replace(/^\/+|\/+$/, ''); }nếu không muốn nhập biểu thức chính quy lặp đi lặp lại. stackoverflow.com/a/22387870/2537258
Timothy Zorn

hoặc['http://localhost:9887/one/two/three/', '/four'].map((part) => part. replace(/^\/+|\/+$/, '')).join('/')
Timothy Zorn

Câu trả lời:


142

Không. path.join()Sẽ trả về giá trị không chính xác khi được sử dụng với URL.

Nghe có vẻ như bạn muốn url.resolve. Từ tài liệu Node :

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'

Chỉnh sửa: Như Andreas đã chỉ ra một cách chính xác trong một nhận xét, url.resolvesẽ chỉ hữu ích nếu vấn đề đơn giản như ví dụ. url.parsecũng áp dụng cho câu hỏi này vì nó trả về các trường được định dạng nhất quán và có thể dự đoán được thông qua URLđối tượng làm giảm nhu cầu về "mã đầy ifs".


1
Mặc dù không chính xác những gì tôi đang tìm kiếm nhưng điều này cũng giải quyết được vấn đề của tôi. Cảm ơn đã giúp đỡ!
Renato Gama

6
@AndreasHultgren nhận xét đầu tiên là đúng. Nếu ví dụ là url.resolve('/one/two/three/', 'four')thì đầu ra sẽ là 'one/two/three/four'.
tavnab

3
Trong trường hợp bất cứ ai muốn sử dụng path.join, nhưng các vấn đề tránh trên Windows: path.posix.join('/one/two/three', 'four') // '/one/two/three/four, path.posix.join('/one/two/three/', 'four') // '/one/two/three/four,path.posix.join('/one/two/three/', '/four') // '/one/two/three/four
Timothy Zorn

2
Nhận xét là không chính xác, url.resolve('/one/two/three', 'four') // '/one/two/four'trong câu trả lời là đúng
Jonathan.

2
Cũng lưu ý rằng url.resolve()chỉ lấy 2 đối số, trong đó path.join()lấy bất kỳ số nào. Vì vậy, tùy thuộc vào những gì bạn đang làm, bạn có thể cần đến các cuộc gọi tổ, ví dụ ..url.resolve(url.resolve(SERVER_URL, pagePath), queryString)
Molomby

47

Không, bạn không nên sử dụng path.join()để nối các phần tử URL.

Có một gói để làm điều đó ngay bây giờ. Vì vậy, thay vì phát minh lại bánh xe, hãy viết tất cả các bài kiểm tra của riêng bạn, tìm lỗi, sửa chúng, viết thêm bài kiểm tra, tìm một trường hợp cạnh mà nó không hoạt động, v.v., bạn có thể sử dụng gói này.

tham gia url

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

Tải về

npm install url-join

Sử dụng

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

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

console.log(fullUrl);

Bản in:

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


1
Điều này. Cái này thật tuyệt. Cảm ơn bạn.
dudewad


6

Khi tôi thử PATH để nối các phần url, tôi gặp sự cố. PATH.joinsọc '//' xuống '/' và cách này làm mất hiệu lực của một url tuyệt đối (ví dụ: http: // ... -> http: / ...). Đối với tôi, một bản sửa lỗi nhanh chóng là:

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

hoặc với giải pháp được đăng bởi Đại tá Panic:

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

Điều gì sẽ xảy ra nếu tôi đang cố gắng tạo một URL tương đối gốc như thế này /assets/foo:? Nó sẽ dẫn đến URL hiện tại-đường dẫn-tương đối assets/foo.
Andrey Mikhaylov - lolmaus

5

Không! Trên Windows path.joinsẽ kết hợp với dấu gạch chéo ngược. Các url HTTP luôn là dấu gạch chéo về phía trước.

Làm thế nào về

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

Ý tưởng hay, nhưng nếu đối số đầu tiên đã có dấu gạch chéo ở cuối thì sao? ví dụ ["posts/", "2013"].join("/"):?
Renato Gama,

1
@RenatoGama, posts//2013vẫn là một URL hợp lệ.
Goodwine,

2
^ điều đó sẽ không hoạt động trên tất cả các miền, mặc dù đó là một URI hợp lệ.
BingeBoy

2
Cụ thể, Node's Express không bỏ qua các dấu gạch chéo không liên quan để định tuyến.
Perseids

1
Trong trường hợp bất cứ ai muốn sử dụng path.join, nhưng các vấn đề tránh trên Windows: path.posix.join('/one/two/three', 'four') // '/one/two/three/four, path.posix.join('/one/two/three/', 'four') // '/one/two/three/four,path.posix.join('/one/two/three/', '/four') // '/one/two/three/four
Timothy Zorn

5

Chúng tôi làm như thế này:

var _ = require('lodash');

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

4

Nếu bạn đang sử dụng lodash , bạn có thể sử dụng oneliner đơn giản này:

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

lấy cảm hứng từ câu trả lời của @Peter Dotchev


3

Đây là những gì tôi sử dụng:

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

thí dụ:

url = joinUrlElements(config.mgmtServer, '/v1/o/', config.org, '/apps');

Điều gì sẽ xảy ra nếu tôi đang cố gắng tạo một URL tương đối gốc như thế này /assets/foo:? Nó sẽ dẫn đến URL hiện tại-đường dẫn-tương đối assets/foo.
Andrey Mikhaylov - lolmaus

1
thêm dấu gạch chéo? Ý tôi là, đó là một kiểm tra đơn giản; bạn có thể thêm nó cho mình.
Cheeso

3
Đây là cách nó bắt đầu ... điều tiếp theo bạn biết rằng bạn đã dành hơn 8 giờ tích lũy để tìm ra các trường hợp cạnh không hoạt động và sửa chúng trong suốt quá trình dự án của bạn.
stone

3

Nếu bạn sử dụng Angular, bạn có thể sử dụng Location :

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

Tuy nhiên, chỉ hoạt động trên 2 đối số, vì vậy bạn phải chuỗi các cuộc gọi hoặc viết một hàm trợ giúp để thực hiện điều đó nếu cần.


2

Các đối tượng WHATWG URL constructor có một (input, base)phiên bản, và inputcó thể là tương đối sử dụng /, ./, ../. Kết hợp điều này với path.posix.joinvà bạn có thể làm bất cứ điều gì:

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

Giải pháp tùy chỉnh stylescript:

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

Giải pháp của tôi

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

Chỉnh sửa: nếu bạn muốn hỗ trợ môi trường windows

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

Giải pháp thứ hai sẽ thay thế tất cả các dấu gạch chéo ngược, vì vậy các phần url như chuỗi truy vấn và mã băm cũng có thể bị thay đổi, nhưng chủ đề chỉ tham gia đường dẫn url, vì vậy tôi không coi đó là vấn đề.


0

Có những câu trả lời làm việc khác, nhưng tôi đã đi với những điều sau đây. Một tổ hợp nhỏ 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

Điều này có thể được thực hiện bằng cách kết hợp đường dẫnURL của Node :

  1. Yêu cầu các gói:
const nodeUrl = require('url')
const nodePath = require('path')
  1. Bắt đầu bằng cách tạo một đối tượng URL để làm việc với:
> const myUrl = new nodeUrl.URL('https://example.com')
  1. Sử dụng pathname=path.joinđể xây dựng bất kỳ kết hợp nào có thể có:
> myUrl.pathname = nodePath.join('/search', 'for', '/something/')
'/search/for/something/'

(bạn có thể thấy sự phóng khoáng như thế nào path.joinvới các lập luận)

  1. Tại thời điểm này, URL của bạn phản ánh kết quả mong muốn cuối cùng:
> myUrl.toString()
'https://example.com/search/for/something/'

Tại sao cách tiếp cận này?

Kỹ thuật này sử dụng các thư viện tích hợp sẵn. Càng ít phụ thuộc của bên thứ ba càng tốt, khi nói đến CVE, bảo trì, v.v.

Tái bút: Đừng bao giờ thao túng URL dưới dạng chuỗi!

Khi tôi xem lại mã, tôi kiên quyết về việc không bao giờ thao tác các URL dưới dạng chuỗi theo cách thủ công . Đối với một, hãy xem thông số kỹ thuật phức tạp như thế nào .

Thứ hai, sự vắng mặt / hiện diện của dấu gạch chéo sau / có tiền tố ( /) sẽ không khiến mọi thứ bị hỏng! Bạn không bao giờ nên làm:

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

và đặc biệt là không:

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

Trong đó tôi vừa gặp phải trong một cơ sở mã.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.