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 매개 변수를 가질 수 있습니까, 아니면 이것을 감지하기 위해 정규식을 사용해야합니까?

편집 :

더 명확하게하기 위해 내가 달성하려는 요구 사항은 다음과 같습니다.

  • 첫 번째 및 두 번째 매개 변수가 필요합니다.
  • 첫 번째 매개 변수는 정적이고 두 번째 매개 변수는 명명 된 매개 변수입니다.
  • 임의의 수의 선택적 추가 매개 변수를 추가 할 수 있으며 여전히 경로에 도달 할 수 있습니다.

1
당신은 무엇을하려고합니까? splat을 알 필요가 없다면 그냥하세요 '/path/:firstParam/*'. 필요한 경우 '/path/:firstParam/:secondParam?/*'.
Jonathan Ong 2012

1
나는 표시가 선택 사항 이길 원합니다-당신이 준 첫 번째 예는 일치하지 않을 것입니다 /path/foo(선택 사항 표시를 원하기 전에 내 경로가 원래 모습이었습니다). 또한 두 번째 예에서 표시를 추가하면 실제로 선택적인 두 번째 매개 변수가 무효화 /path/foo됩니다. 두 번째 패턴과 일치하지 않습니다 (두 번째 패턴도 마찬가지입니다 /path/foo/bar...). Express 라우터의 더 성가신 부분 중 하나입니다.
제시

1
개인적으로 난 그냥 갈 것입니다 /path/:firstParam/path/:firstParam/:secondParam/공유 컨트롤러와 두 개의 라우터로. 필요 URL이 혼동하지 않습니다합니다
조나단 옹

n, 난 그냥 그렇게 PARAMS의 수에 제한을 가지고, 그것은 모든 숫자가 될 수 있으며, 1-3 PARAMS 라우팅 아니에요 물론, 10 엔드 포인트를 만들 수있는 옵션 (하지 않습니다 - 엔드 포인트 것은 응용 프로그램의 설계에 필요한 그러나 그 작업을 명시 적으로 수행하는 것은 경로에서 수행하는 것보다 낫지 않습니다.) 정규식 경로를 사용하여 문제를 해결할 수 있지만 (지금하고있는 작업) 읽을 수있는 옵션이 있기를 바랐습니다.
Jesse

개발자가 명명 된 선택적 매개 변수에 단순히 괄호를 사용한다고 생각하지 않았다는 것이 놀랍습니다. 즉,/path/:param(/:otherOptionalParam)
r3wt

답변:


111

특급 4에 대한 / 경로 / 경로 / foo는이 작품은주의 *전에 ?.

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

43
이 작업을 수행하는 동안, 당신이 방문하는 경우주의 /path/foo/bar/bazzle, req.params.id동일합니다 fooreq.params[0]동일합니다 /bar/bazzle어떤 사람들을 여행 할 수있는. 더 깨끗한 해결책은 경로를으로 정의하는 것입니다.이 경로 /path/*?는 Express 4에서로 설정 req.params[0]되며 foo/bar/bazzle아마도 찾고있는 것에 더 가깝습니다.
Jesse

선택적 매개 변수를 URL 인코딩하는 것이 좋습니다. 슬래시가있는 항목을 허용하면 app.get ( 'path / : required1 / : required2 / : optional? *'과 같은 경로를 추가하려는 경우 길을 따라 충돌이 발생하게됩니다. , handler)
Jordan

@Jesse 마지막 부분을 요구하는 방법은 없습니까? 예를 들어 나는 일치 할 /path/foo/bar하지 /path/foo . 시도 '/path/:id/*했지만 *빈 문자열도 일치하는 것 같습니다.
Franklin Yu

73

나는 방금 똑같은 문제가 있었고 그것을 해결했습니다. 이것이 내가 사용한 것입니다.

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

이것은 작동한다 path/meow, path/meow/voof, path/meow/voof/moo/etc...

/사이 를 삭제하는 것으로 보이며 마지막 도 선택 사항이되고 선택 사항으로 유지됩니다.?*/:optional?


멋있는! 방금 테스트했는데 (익스프레스 3.0.0에서는 2.x에서는 테스트하지 않음) 작동합니다. 이것은 내 RegEx 해킹보다 확실히 깨끗합니다.
Jesse

5
이러한 사전 정의 된 키워드에 대한 자세한 내용을 어디에서 읽을 수 있는지 알고 있습니까?
János

8
익스프레스 4.0 년이 더 이상 작동에 표시되지 않습니다
regretoverflow

2
@chris는 Express 4에 대해 이것을 대답했습니다. 최신이기 때문에 수락 된 대답을 그의 대답으로 옮겼습니다.
Jesse

이것을 사용하여 이상한 오류가 발생했습니다. 0이있는 숫자의 경우 express가이를 차단합니다. 예를 들어 / : 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 일치 .+-나는 확실히 rtfm, 그것을 언급하지 않는 것 같아서 가능하지 않을 수도 있습니다 ...
Jesse

3

이 문제를 해결하는 현재 방법은 다음과 같습니다. express는 선택 사항 인 param이라는 선택적 매개 변수를 사용하여 여러 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 등과 일치합니다. 그 후에 params가 채워지지 않았기 때문에 req.originalUrl을 읽을 수 있습니다. baseUrl과 originalUrl을 비교하여 나머지 경로를 얻을 수 있습니다.


0

나는 URL에 후행 슬래시를 추가 미들웨어와의 조합을 사용하여이 문제를 주변에있어 router.get('/bar/*?', ...후 모든 데리러, /bar/그리고 수익을 undefined그냥 경우를 /bar/. 방문자가 요청 /bar하면 express-slash미들웨어는 요청에 슬래시를 추가하고 요청을 /bar/.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.