Định tuyến Express.js: tham số biểu tượng tùy chọn?


82

Tôi có một tuyến đường giống như sau:

app.all('/path/:namedParam/*splat?',function(req,res,next){
  if(!req.params.length){
    // do something when there is no splat
  } else {
    // do something with splat
  }
});

tuy nhiên, điều này không hoạt động - nếu tôi gọi path/foo/barthì nó trúng tuyến, nhưng nếu tôi gọi path/foothì không.

Có thể có một tham số biểu tượng tùy chọn hay tôi phải sử dụng regex để phát hiện điều này?

Chỉnh sửa :

để rõ ràng hơn, đây là những yêu cầu tôi đang cố gắng đạt được:

  • thông số đầu tiên và thông số thứ hai là bắt buộc
  • tham số đầu tiên là tĩnh, tham số thứ hai là tham số được đặt tên.
  • bất kỳ số lượng tham số bổ sung tùy chọn nào có thể được thêm vào và vẫn đạt được lộ trình.

1
bạn đang cố làm gì vậy? nếu bạn không cần biết splat, chỉ cần làm '/path/:firstParam/*'. Nếu bạn cần, hãy làm '/path/:firstParam/:secondParam?/*'.
Jonathan Ong

1
Tôi đang tìm cách để biểu tượng là tùy chọn - ví dụ đầu tiên bạn đưa ra sẽ không khớp /path/foo, (đó là những gì tuyến đường của tôi ban đầu trông giống như trước khi tôi muốn có biểu tượng tùy chọn). Ngoài ra, trong ví dụ thứ hai của bạn, việc thêm biểu tượng thực sự phủ định thông số thứ hai tùy chọn - /path/foosẽ không phù hợp với mẫu thứ hai của bạn (cũng không phù hợp với /path/foo/barvấn đề đó ...) - một trong những phần khó chịu hơn của bộ định tuyến express '.
Jesse

1
cá nhân tôi sẽ chỉ đi /path/:firstParam/path/:firstParam/:secondParam/như hai bộ định tuyến riêng biệt với một bộ điều khiển được chia sẻ. không cần phải làm cho các url của bạn khó hiểu
Jonathan Ong

nđiểm cuối là cần thiết cho thiết kế của ứng dụng - tôi không chỉ định tuyến đến 1-3 tham số, nó có thể là bất kỳ số nào, vì vậy giới hạn về số lượng tham số không phải là một lựa chọn (chắc chắn, tôi có thể tạo 10 điểm cuối, nhưng có express làm công việc đó không phải là tốt hơn làm nó trong một lộ trình). Tôi có thể sử dụng một tuyến đường regex để giải quyết vấn đề của mình (những gì tôi đang làm bây giờ), nhưng tôi đã hy vọng có một tùy chọn có thể đọc được.
Jesse

thật tuyệt vời khi các nhà phát triển không nghĩ chỉ sử dụng dấu ngoặc đơn cho các tham số tùy chọn được đặt tên. tức là/path/:param(/:otherOptionalParam)
r3wt

Câu trả lời:


111

Điều này hoạt động cho / path và / path / foo trên express 4, hãy lưu ý phần *trước ?.

router.get('/path/:id*?', function(req, res, next) {
    res.render('page', { title: req.params.id });
});

43
Lưu ý rằng trong khi điều này hoạt động, nếu bạn truy cập /path/foo/bar/bazzle, req.params.idsẽ bằng nhau fooreq.params[0]sẽ bằng nhau /bar/bazzle, điều này có thể khiến một số người tăng lên. Một giải pháp rõ ràng hơn có thể là xác định đường dẫn /path/*?, mà trong express 4 sẽ được đặt req.params[0]thành foo/bar/bazzle, có lẽ gần với những gì bạn đang tìm kiếm.
Jesse

bạn nên mã hóa url thông số tùy chọn của mình - cho phép bất kỳ thứ gì có dấu gạch chéo có nghĩa là bạn sẽ gặp xung đột nếu bạn muốn thêm một đường dẫn như app.get ('path /: Requi1 /: Requi2 /: tùy chọn? *' , xử lý)
Jordan

@Jesse Có cách nào để thực hiện phần cuối cùng được yêu cầu không? Ví dụ tôi muốn khớp /path/foo/barnhưng không được /path/foo . Tôi đã thử '/path/:id/*nhưng *dường như cũng khớp với chuỗi trống.
Franklin Yu

73

Tôi chỉ có cùng một vấn đề và đã giải quyết nó. Đây là những gì tôi đã sử dụng:

app.get('path/:required/:optional?*', ...)

Điều này sẽ làm việc cho path/meow, path/meow/voof, path/meow/voof/moo/etc...

Có vẻ như bằng cách bỏ /giữa ?*, cuối cùng cũng /trở thành tùy chọn trong khi :optional?vẫn là tùy chọn.


Mát mẻ! Tôi vừa thử nghiệm điều này (trong 3.0.0 express, chưa thử nghiệm trong 2.x) và nó hoạt động. Điều này chắc chắn rõ ràng hơn bản hack RegEx của tôi.
Jesse

5
Bạn có biết nơi tôi có thể đọc thêm về những từ khóa được xác định trước này không?
János

8
Trong nhanh 4.0x này không xuất hiện để làm việc nữa
regretoverflow

2
@chris đã trả lời câu này cho express 4 - vì đó là câu trả lời mới nhất, tôi đã chuyển câu trả lời được chấp nhận sang câu trả lời của anh ấy.
Jesse

Gặp lỗi kỳ lạ khi sử dụng điều này, đối với các số không có trong đó, express sẽ cắt nó đi. Ví dụ /: id trong đó id = 904, req.params.id = 9 và req.params.0 = 04 (express đổ phần còn lại này ở đây vì một số lý do). Chris sửa câu trả lời này
emiidee

17

Điều này sẽ làm những gì bạn đang theo đuổi?

app.all('/path/:namedParam/:optionalParam?',function(req,res,next){
  if(!req.params.optionalParam){
    // do something when there is no optionalParam
  } else {
    // do something with optionalParam
  }
});

Thông tin thêm về định tuyến Express 'tại đây, nếu bạn chưa xem: http://expressjs.com/guide/routing.html


2
Giải pháp này sẽ phù hợp /path/foo/bar, nhưng không /path/foo/bar/baz- các *trận đấu splat .+, đó là cần thiết cho những gì tôi đang làm - Tôi đã chắc chắn RTFM, dường như không đề cập đến nó, vì vậy có lẽ nó không thể ...
Jesse

3

Đây là cách hiện tại tôi đang giải quyết vấn đề này, có vẻ như express không hỗ trợ bất kỳ số lượng tham số biểu tượng nào với tham số có tên tùy chọn:

app.all(/\/path\/([^\/]+)\/?(.+)?/,function(req,res,next){
  // Note: this is all hacked together because express does not appear to support optional splats.
  var params = req.params[1] ? [req.params[1]] : [],
      name = req.params[0];
  if(!params.length){
    // do something when there is no splat
  } else {
    // do something with splat
  }
});

Tôi muốn sử dụng các tham số được đặt tên này để dễ đọc và nhất quán - nếu câu trả lời khác xuất hiện cho phép điều này, tôi sẽ chấp nhận nó.


2

Giả sử bạn có url này: /api/readFile/c:/a/a.txt

Nếu bạn muốn req.params.pathtrở thành c::

'/api/readFile/:path*

Nếu bạn muốn req.params.pathtrở thành c:/a/a.txt:

'/api/readFile/:path([^/]*)'

0

Các giải pháp trên bằng cách sử dụng tùy chọn không hoạt động trong Express 4. Và tôi đã thử một số cách bằng cách sử dụng các mẫu tìm kiếm, nhưng cũng không hoạt động. Và sau đó tôi tìm thấy phương pháp này và dường như được kích hoạt cho đường dẫn lồng nhau không giới hạn, http://expressjs.com/api.html#router

// this will only be invoked if the path starts with /bar from the mount point
router.use('/bar', function(req, res, next) {
  // ... maybe some additional /bar logging ...

  // to get the url after bar, you can try
  var filepath = req.originalUrl.replace(req.baseUrl, "");

  next();
});

Nó khớp với tất cả / bar, / bar / z, / bar / a / b / c, v.v. Và sau đó, bạn có thể đọc req.originalUrl, vì các tham số không được điền, ví dụ: bạn có thể thử so sánh baseUrl và originalUrl để lấy đường dẫn còn lại.


0

Tôi đã giải quyết vấn đề này bằng cách sử dụng sự kết hợp của một phần mềm trung gian thêm dấu gạch chéo vào url và router.get('/bar/*?', ...sẽ nhận mọi thứ sau đó /bar/và trả lại undefinednếu đúng như vậy /bar/. Nếu khách truy cập yêu cầu /bar, express-slashphần mềm trung gian sẽ thêm dấu gạch chéo vào yêu cầu và biến yêu cầu thành /bar/.

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.