Маршрутизація Express.js: необов’язковий параметр splat?


82

У мене є маршрут, який виглядає так:

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

однак це не працює - якщо я зателефоную, path/foo/barце потрапить на маршрут, але якщо я зателефоную path/foo, це не буде.

Чи можна мати необов'язковий параметр splat, чи мені потрібно використовувати регулярний вираз для виявлення цього?

Редагувати :

щоб бути зрозумілішим, ось вимоги, яких я намагаюся досягти:

  • перший і другий PARAMS які потрібні
  • перший параметр - статичний, другий - іменований параметр.
  • можна додати будь-яку кількість додаткових додаткових параметрів, які все одно потрапляють у маршрут.

1
що ти намагаєшся зробити? якщо вам не потрібно знати splat, просто знайте '/path/:firstParam/*'. Якщо вам це потрібно, зробіть '/path/:firstParam/:secondParam?/*'.
Джонатан Онг,

1
Я прагну, щоб знак не був необов’язковим - перший приклад, який ви навели, не збігався б /path/foo(так виглядав мій маршрут, перш ніж я хотів необов’язковий знак). Крім того, у вашому другому прикладі додавання символу фактично заперечує необов’язковий другий параметр - /path/fooне буде відповідати вашому другому шаблону (як і не буде /path/foo/barз цього приводу ...) - одній з найбільш дратівливих частин експрес-маршрутизатора.
Джессі,

1
особисто я б просто вибрав /path/:firstParamі /path/:firstParam/:secondParam/як два окремі маршрутизатори зі спільним контролером. не потрібно робити ваші URL-адреси заплутаними
Джонатан Онг

Наявність nкінцевих точок необхідно для розробки програми - я не просто маршрутую до 1-3 параметрів, це може бути будь-яке число, тому обмеження кількості парам не є варіантом (звичайно, я міг би створити 10 кінцевих точок, але експрес-виконання цієї роботи не є нічим кращим, ніж виконання цього за маршрутом). Я можу використати маршрут регулярного виразу, щоб вирішити свою проблему (те, що я роблю зараз), але я сподівався мати можливість читання.
Джессі,

дивно, що розробники не думали просто використовувати дужки для названих додаткових параметрів. тобто/path/:param(/:otherOptionalParam)
r3wt

Відповіді:


111

Це працює для / path та / path / foo на express 4, зверніть увагу на *попереднє ?.

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

43
Зверніть увагу, що, хоча це дійсно працює, якщо ви завітаєте /path/foo/bar/bazzle, req.params.idбуде рівним fooі req.params[0]буде рівним /bar/bazzle, що може зіткнути деяких людей. Очищувач розчин може бути , щоб визначити шлях, /path/*?, який в експрес 4 буде встановлений req.params[0]в foo/bar/bazzle, який, ймовірно , ближче до того , що ви шукаєте.
Джессі

тобі краще використовувати url-код, який кодує необов’язковий параметр - дозволяючи будь-що з косими рисками, це означає, що у вас виникнуть конфлікти в дорозі, якщо ви хочете додати такий шлях, як app.get ('path /: required1 /: required2 /: optional? *' , обробник)
Йорданія

@Jesse Будь-який спосіб зробити останню частину потрібною? Наприклад, я хочу відповідати, /path/foo/barале ні /path/foo . Я спробував, '/path/:id/*але, *схоже, також відповідає порожньому рядку.
Франклін Ю

73

Я просто мав ту саму проблему і вирішив її. Це те, що я використав:

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

Це повинно працювати path/meow, path/meow/voof, path/meow/voof/moo/etc...

Здається, знижуючи /між ?і *, останній /стає факультативним теж поки :optional?залишається необов'язковим.


Класно! Я щойно перевірив це (у Express 3.0.0, не тестував у 2.x), і воно працює. Це, безумовно, чистіше, ніж мій злом RegEx.
Джессі

5
Чи знаєте ви, де я можу прочитати більше про ці заздалегідь визначені ключові слова?
Янос

8
У Express 4.0x це, здається, вже не працює
regretoverflow

2
@chris відповів на це для express 4 - оскільки це останнє, я переніс прийняту відповідь на його.
Джессі,

Використовуючи це, натрапила на дивну помилку, для чисел із нулем в ній експрес виразить її. Наприклад /: id де id = 904, req.params.id = 9 та req.params.0 = 04 (висловити це решту сюди з якихось причин). Відповідь Кріса це виправляє
emiidee

17

Чи буде це робити те, що вам потрібно?

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

Докладніше про маршрутизацію Express тут, якщо ви ще не переглядали: http://expressjs.com/guide/routing.html


2
Це рішення відповідало б /path/foo/bar, але ні /path/foo/bar/baz- *splat match , .+який необхідний для того, що я роблю, - я, безумовно, rtfm, схоже, не згадує про це, тому, можливо, це неможливо ...
Джессі

3

Ось нинішній спосіб вирішення цієї проблеми, схоже, експрес підтримує будь-яку кількість параметрів splat з необов’язковим іменованим param:

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

Я хотів би, щоб це використання було названо params для читабельності та послідовності - якщо повернеться інша відповідь, яка дозволяє це, я прийму це.


2

Припустимо, у вас є така URL-адреса: /api/readFile/c:/a/a.txt

Якщо ви хочете req.params.pathбути c::

'/api/readFile/:path*

Якщо ви хочете req.params.pathбути c:/a/a.txt:

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

0

Наведені вище рішення з використанням необов’язкового не працюють у Express 4. І я спробував кілька способів, використовуючи шаблони пошуку, але також не працюючи. І тоді я знайшов цей метод і, здається, звільнений за необмежений вкладений шлях, 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();
});

Це збіг усіх / bar, / bar / z, / bar / a / b / c і т.д. І після цього ви можете прочитати req.originalUrl, оскільки параметри не заповнюються, напр. Ви можете спробувати порівняти baseUrl та originalUrl, щоб отримати залишковий шлях.


0

Я вирішив цю проблему за допомогою комбінації проміжного програмного забезпечення, яке додає кінцеві косі риси до url і router.get('/bar/*?', ..., які забирають все після /bar/і повертають, undefinedякщо це справедливо /bar/. Якщо відвідувач просив про це /bar, express-slashпроміжне програмне забезпечення додасть у запит косу риску і перетворює запит на /bar/.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.