Express-js wildcard การกำหนดเส้นทางเพื่อครอบคลุมทุกสิ่งที่อยู่ภายใต้และรวมถึงเส้นทาง


97

ฉันพยายามมีเส้นทางเดียวที่ครอบคลุมทุกอย่างภายใต้/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

คำตอบ:


114

ฉันคิดว่าคุณจะต้องมี 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);

105
app.get(["/foo", "/foo*"], /* function */);อาจจะมีสิทธิพิเศษเช่นกัน!
Chris Foster

9
การส่งผ่านในอาร์เรย์ของสตริงเป็นสิ่งพิเศษสำหรับฉันเช่นกัน ขออภัย: การส่งอาร์เรย์ไปยังแอป 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(.*)/)ขจัดความจำเป็นในการใช้เส้นทางแยกกัน สิ่งนี้ตรงกันข้ามกับคำตอบก่อนหน้านี้ (หมายถึงเราเตอร์เชื่อมต่อที่ถูกลบออกในขณะนี้) ซึ่งระบุว่า " *ในเส้นทางถูกแทนที่ด้วย.+"

อัปเดต:ขณะนี้ Express ใช้โมดูล "path-to-regexp" (ตั้งแต่ Express 4.0.0) ซึ่งยังคงลักษณะการทำงานเดียวกันในเวอร์ชันที่อ้างถึงในปัจจุบัน ไม่ชัดเจนสำหรับฉันว่าเวอร์ชันล่าสุดของโมดูลนั้นมีพฤติกรรมหรือไม่ แต่สำหรับตอนนี้คำตอบนี้มีผล


เราควรใช้. + หรือ *?
Tyler Langan

2
ใช้/\/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 */);

4

สำหรับผู้ที่เรียนรู้ node / express (เช่นเดียวกับฉัน): อย่าใช้ wildcard routeing ถ้าเป็นไปได้!

ฉันต้องการใช้การกำหนดเส้นทางสำหรับ GET / ผู้ใช้ /: id / อะไรก็ตามที่ใช้การกำหนดเส้นทางสัญลักษณ์แทน นี่คือวิธีที่ฉันมาที่นี่

ข้อมูลเพิ่มเติม: https://blog.praveen.science/wildcard-routing-is-an-anti-pattern/


3
ลิงก์เสียในขณะนี้ บางทีอาจจะเหมือนกับ: jonathanong.github.io/wildcard-routing-is-an-anti-pattern.html
Ron Burk

@RonBurk url ของคุณดูเหมือนจะตายแล้วด้วย .. ฉันจะมีสัญลักษณ์แทนหลังจากพารามิเตอร์ที่ตั้งชื่อได้อย่างไร "/ บางสิ่ง /: id (/ *)?" ไม่ทำงาน ..
Soichi Hayashi

อาจจะยังอยู่ใน Google cache อีกสักพัก: webcache.googleusercontent.com/…
Ron Burk

มีทางเลือกอื่นในการกำหนดเส้นทางโดยใช้สัญลักษณ์แทนหรือไม่หากฉันไม่รู้ว่าเกิดอะไรขึ้นหลังจากส่วนเริ่มต้นของ URL
Michael

2
นี่คือรายการที่เผยแพร่ซ้ำ: Wildcard Routing is an Anti-Pattern
Praveen Kumar Purushothaman
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.