경로를 포함한 모든 것을 포함하는 Express-js 와일드 카드 라우팅


96

나는 자신 을 /foo포함하여 모든 것을 포함하는 하나의 경로를 갖도록 노력하고 있습니다 /foo. 일치하지 않는 /foo*것을 제외하고 모든 작업에 대해 어떤 작업을 사용해 보았습니다 /foo. 관찰 :

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

출력 :

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

내 옵션은 무엇입니까? 내가 생각해 낸 최선의 /fo*방법은 너무 많이 일치하기 때문에 물론 최적이 아닌 경로 를 지정하는 것입니다.


/foo*이와 같은 모든 경로를 가로채는 대신 미들웨어로 만들고 싶지 않습니까?
Raynos

3
당신이 요구하는 것에주의하십시오 : /foo*성냥 /foo/bar뿐만 아니라 /foolish아마 당신이 의도하지 않았던 성냥 .
Wyck

답변:


111

2 개의 루트가 필요하다고 생각합니다. 연결 라우터의 331 행을 보면 경로의 *가. +로 바뀌므로 1 개 이상의 문자와 일치합니다.

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

동일한 작업을 수행하는 2 개의 경로가있는 경우 다음을 수행하여 건조 상태를 유지할 수 있습니다.

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 */);또한 우대 할 수 있습니다!
Chris Foster

9
문자열 배열을 전달하는 것도 나에게 우선적입니다. 불행하게도 : app.VERB ()에 배열을 전달하는 것은 더 이상 사용되지 않으며 4.0에서 제거 될 예정입니다
CodeWarrior를

10
Express 4.9.1에서는 문자열 배열 전달이 복원되었습니다.
Pete TNT

30

이제 연결 라우터가 제거되었습니다 ( https://github.com/senchalabs/connect/issues/262 ). 작성자는 라우팅을 위해 연결 위에 프레임 워크 (예 : Express)를 사용해야한다고 언급했습니다.

Express는 현재로 처리 app.get("/foo*") 되므로 app.get(/\/foo(.*)/)두 개의 별도 경로가 필요하지 않습니다. 이것은 " *in a path is replace with .+"라고 언급 한 이전 답변 (지금 제거 된 연결 라우터 참조)과는 대조적 입니다.

업데이트 : 이제 Express는 현재 참조 된 버전에서 동일한 동작 을 유지 하는 "regexp에 대한 경로"모듈 (Express 4.0.0 이후)을 사용합니다 . 해당 모듈의 최신 버전이 동작을 유지하는지 여부는 확실하지 않지만 현재로서는이 답변이 유효합니다.


그렇다면. + 또는 *를 사용해야합니까?
Tyler Langan 2015-08-22

2
다음에 하나 이상의 문자 를 일치 시키거나 0 개 이상의 문자 를 일치 시키 /\/foo(.+)/려면 사용하십시오 . /foo/foo*/\/foo(.*)//foo
Johann

12

두 개의 경로가 필요하지 않습니다.

문자열 (/*)?끝에 추가하기 만하면 path됩니다.

예를 들면 app.get('/hello/world(/*)?' /* ... */)

다음은 완전히 작동하는 예제입니다. 이것을 .js 파일에 복사하여 붙여 넣어 노드와 함께 실행하고 브라우저 (또는 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

배열에서 req.params에 전달되는 변수를 사용할 수도 있습니다.

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

3

노드 / 익스프레스 (나처럼)를 배우는 사람들을 위해 : 가능하면 와일드 카드 라우팅을 사용하지 마십시오!

또한 와일드 카드 라우팅을 사용하여 GET / users / : id / whatever에 대한 라우팅을 구현하고 싶었습니다. 이것이 내가 여기에 온 방법입니다.

다행히도 다음 문서도 찾았습니다. http://www.jongleberry.com/wildcard-routing-is-an-anti-pattern.html

건배, 로버트


2
현재 링크가 끊어졌습니다. 아마이었다 동일 : jonathanong.github.io/wildcard-routing-is-an-anti-pattern.html
론 버크

@RonBurk 귀하의 URL도 죽은 것 같습니다. 명명 된 매개 변수 뒤에 선택적 와일드 카드를 어떻게 가질 수 있습니까? "/ something / : id (/ *)?" 작동하지 않음 ..
쇼이치 하야시

아마 아직 잠시 동안 구글 캐시에있을 것입니다 : webcache.googleusercontent.com/...
론 버크

URL의 처음 부분 뒤에 오는 내용을 모르는 경우 와일드 카드 라우팅에 대한 대안이 있습니까?
Michael

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