Perutean karakter pengganti Express-js untuk mencakup semua yang ada di bawah dan termasuk jalur

96

Saya mencoba untuk memiliki satu rute yang mencakup semuanya /footermasuk /foodirinya sendiri. Saya sudah mencoba menggunakan /foo*yang berfungsi untuk semuanya kecuali tidak cocok /foo. Mengamati:

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

Keluaran:

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

Apa saja pilihan saya? Yang terbaik yang pernah saya temukan adalah rute /fo*yang tentu saja tidak terlalu optimal karena akan terlalu cocok.

Kit Sunde
sumber
Jika Anda mencegat semua /foo*rute seperti itu, tidakkah Anda ingin menjadikannya middleware?
Raynos
3
Berhati-hatilah dengan apa yang Anda minta: /foo*kecocokan /foo/bartetapi juga kecocokan /foolishyang mungkin tidak Anda inginkan.
Wyck

Jawaban:

112

Saya pikir Anda harus memiliki 2 rute. Jika Anda melihat baris 331 dari koneksi router, * di jalur diganti dengan. + Jadi akan cocok dengan 1 atau lebih karakter.

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

Jika Anda memiliki 2 rute yang melakukan tindakan yang sama, Anda dapat melakukan hal berikut agar tetap KERING .

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);
serby
sumber
103
app.get(["/foo", "/foo*"], /* function */);mungkin preferensial juga!
Chris Foster
9
Meneruskan serangkaian string juga penting bagi saya. Sayangnya: meneruskan array ke app.VERB () tidak digunakan lagi dan akan dihapus di 4.0
CodeWarrior
10
Meneruskan array string telah dipulihkan di Express 4.9.1.
Pete TNT
30

Router penghubung sekarang telah dihapus ( https://github.com/senchalabs/connect/issues/262 ), penulis menyatakan bahwa Anda harus menggunakan kerangka kerja di atas koneksi (seperti Express) untuk perutean.

Express saat ini diperlakukan app.get("/foo*") sebagai app.get(/\/foo(.*)/), menghilangkan kebutuhan untuk dua rute terpisah. Ini berbeda dengan jawaban sebelumnya (mengacu pada koneksi router yang sekarang dihapus) yang menyatakan bahwa " *dalam jalur diganti dengan .+".

Update: Express saat ini menggunakan "jalan-to-regexp" modul (karena Ekspres 4.0.0) yang mempertahankan perilaku yang sama dalam versi saat ini direferensikan. Tidak jelas bagi saya apakah versi terbaru modul itu mempertahankan perilakunya, tetapi untuk saat ini jawaban ini berlaku.

Johann
sumber
Jadi, haruskah kita menggunakan. + Atau *?
Tyler Langan
2
Gunakan /\/foo(.+)/jika Anda ingin mencocokkan /foodiikuti dengan satu atau lebih karakter, dan /foo*atau /\/foo(.*)/jika Anda ingin mencocokkan /foodiikuti dengan nol atau lebih karakter.
Johann
12

Tidak perlu memiliki dua rute.

Cukup tambahkan (/*)?di akhir pathstring Anda .

Sebagai contoh, app.get('/hello/world(/*)?' /* ... */)

Berikut adalah contoh yang berfungsi sepenuhnya, silakan salin dan tempel ini ke dalam file .js untuk dijalankan dengan node, dan mainkan di browser (atau 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!'))
Somo S.
sumber
9

Dalam array Anda juga dapat menggunakan variabel yang meneruskan ke req.params:

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

Bagi mereka yang sedang mempelajari node / express (seperti saya): jangan gunakan perutean wildcard jika memungkinkan!

Saya juga ingin menerapkan perutean untuk GET / users /: id / apa pun yang menggunakan perutean wildcard. Beginilah cara saya sampai di sini.

Info lebih lanjut: https://blog.praveen.science/wildcard-routing-is-an-anti-pattern/

throbi
sumber
3
Link saat ini mati. Mungkin itu sama dengan: jonathanong.github.io/wildcard-routing-is-an-anti-pattern.html
Ron Burk
@RonBurk url Anda tampaknya juga mati .. Bagaimana saya bisa memiliki wildcard opsional setelah parameter bernama? "/ sesuatu /: id (/ *)?" tidak bekerja ..
Soichi Hayashi
Mungkin masih akan ada di cache Google untuk sementara waktu: webcache.googleusercontent.com/…
Ron Burk
apakah ada alternatif untuk perutean karakter pengganti jika saya tidak tahu apa yang muncul setelah bagian awal URL?
Michael
2
Ini yang diterbitkan ulang: Perutean Karakter Pengganti adalah Anti-Pola
Praveen Kumar Purushothaman