Định tuyến ký tự đại diện Express-js để bao gồm mọi thứ bên dưới và bao gồm cả một đường dẫn


96

Tôi đang cố gắng có một lộ trình bao gồm tất cả mọi thứ, /foobao gồm cả /foochính nó. Tôi đã thử sử dụng /foo*công cụ nào cho mọi thứ ngoại trừ nó không khớp /foo. Quan sát:

var express = require("express"),
    app = express.createServer();

app.get("/foo*", function(req, res, next){
  res.write("Foo*\n");
  next();
});

app.get("/foo", function(req, res){
  res.end("Foo\n");
});

app.get("/foo/bar", function(req, res){
  res.end("Foo Bar\n");
});

app.listen(3000);

Kết quả đầu ra:

$ curl localhost:3000/foo
Foo
$ curl localhost:3000/foo/bar
Foo*
Foo Bar

Những lựa chọn của tôi là gì? Điều tốt nhất tôi nghĩ ra là định tuyến /fo*mà tất nhiên là không tối ưu lắm vì nó sẽ trùng khớp quá nhiều.


Nếu bạn chặn tất cả các /foo*tuyến đường như vậy, bạn không muốn biến nó thành phần mềm trung gian?
Raynos

3
Hãy cẩn thận với những gì bạn yêu cầu: /foo*phù hợp /foo/barnhưng cũng có thể trùng khớp /foolishmà bạn có thể không có ý định.
Wyck

Câu trả lời:


111

Tôi nghĩ bạn sẽ phải có 2 lộ trình. Nếu bạn nhìn vào dòng 331 của bộ định tuyến kết nối, dấu * trong đường dẫn được thay thế bằng. + Như vậy sẽ khớp với 1 hoặc nhiều ký tự.

https://github.com/senchalabs/connect/blob/master/lib/middleware/router.js

Nếu bạn có 2 tuyến đường thực hiện cùng một hành động, bạn có thể làm như sau để giữ cho nó KHÔ .

var express = require("express"),
    app = express.createServer();

function fooRoute(req, res, next) {
  res.end("Foo Route\n");
}

app.get("/foo*", fooRoute);
app.get("/foo", fooRoute);

app.listen(3000);

101
app.get(["/foo", "/foo*"], /* function */);cũng có thể được ưu đãi!
Chris Foster

9
Tôi cũng ưu tiên vượt qua một mảng chuỗi. Thật không may: đi qua một mảng để app.VERB () là lỗi thời và sẽ được loại bỏ trong 4,0
CodeWarrior

10
Việc chuyển một mảng chuỗi đã được khôi phục trong Express 4.9.1.
Pete TNT

30

Bộ định tuyến kết nối hiện đã bị loại bỏ ( https://github.com/senchalabs/connect/issues/262 ), tác giả cho biết rằng bạn nên sử dụng một khuôn khổ trên kết nối (như Express) để định tuyến.

Bày tỏ hiện xử lý app.get("/foo*") như app.get(/\/foo(.*)/), loại bỏ sự cần thiết của hai tuyến đường riêng biệt. Điều này trái ngược với câu trả lời trước đó (đề cập đến bộ định tuyến kết nối hiện đã bị loại bỏ) đã nói rằng " *trong một đường dẫn được thay thế bằng .+".

Cập nhật: Express hiện sử dụng mô-đun "path-to-regexp" (kể từ Express 4.0.0), mô-đun này duy trì hoạt động tương tự trong phiên bản hiện được tham chiếu. Tôi không rõ liệu phiên bản mới nhất của mô-đun đó có giữ được hành vi đó hay không, nhưng hiện tại câu trả lời này là đúng.


Vì vậy, chúng ta nên sử dụng. + Hoặc *?
Tyler Langan

2
Sử dụng /\/foo(.+)/nếu bạn muốn so khớp /footheo sau bởi một hoặc nhiều ký tự và /foo*hoặc /\/foo(.*)/nếu bạn muốn so khớp /footheo sau bởi không hoặc nhiều ký tự.
Johann

12

Không nhất thiết phải có hai tuyến.

Chỉ cần thêm (/*)?vào cuối pathchuỗi của bạn .

Ví dụ, app.get('/hello/world(/*)?' /* ... */)

Đây là một ví dụ hoạt động đầy đủ, hãy sao chép và dán nó vào tệp .js để chạy với nút và chơi với nó trong trình duyệt (hoặc curl):

const app = require('express')()

// will be able to match all of the following
const test1 = 'http://localhost:3000/hello/world'
const test2 = 'http://localhost:3000/hello/world/'
const test3 = 'http://localhost:3000/hello/world/with/more/stuff'

// but fail at this one
const failTest = 'http://localhost:3000/foo/world'

app.get('/hello/world(/*)?', (req, res) => res.send(`
    This will match at example endpoints: <br><br>
    <pre><a href="${test1}">${test1}</a></pre>
    <pre><a href="${test2}">${test2}</a></pre>
    <pre><a href="${test3}">${test3}</a></pre>

    <br><br> Will NOT match at: <pre><a href="${failTest}">${failTest}</a></pre>
`))

app.listen(3000, () => console.log('Check this out in a browser at http://localhost:3000/hello/world!'))

9

Trong mảng, bạn cũng có thể sử dụng các biến truyền tới req.params:

app.get(["/:foo", "/:foo/:bar"], /* function */);

3

Đối với những người đang học node / express (giống như tôi): không sử dụng định tuyến ký tự đại diện nếu có thể!

Tôi cũng muốn triển khai định tuyến cho GET / users /: id / anything bằng cách sử dụng định tuyến ký tự đại diện. Đây là cách tôi đến đây.

May mắn thay, tôi cũng đã tìm thấy bài viết này: http://www.jongleberry.com/wildcard-routing-is-an-anti-pattern.html

Chúc mừng, Robert


2
Liên kết hiện đã chết. Có lẽ đó là giống như: jonathanong.github.io/wildcard-routing-is-an-anti-pattern.html
Ron Burk

@RonBurk url của bạn dường như cũng đã chết .. Làm cách nào để có ký tự đại diện tùy chọn sau một tham số được đặt tên? "/ cái gì đó /: id (/ *)?" không hoạt động ..
Soichi Hayashi

Có thể sẽ vẫn còn trong bộ nhớ cache của Google trong một thời gian ngắn: webcache.googleusercontent.com/…
Ron Burk

có giải pháp thay thế cho định tuyến theo ký tự đại diện không nếu tôi không biết điều gì đến sau phần đầu tiên của URL?
Michael

1
Dưới đây là một trong những phẩm tái: Wildcard Routing là một Anti-Pattern
Praveen Kumar Purushothaman
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.