Menu

Express Router i routing: trasy, parametry, prefiksy

Trasa w Express to metoda, ścieżka i handler: app.get('/users/:id', handler). Powiązane trasy grupuj w express.Router() i podpinaj pod prefiks przez app.use('/api', router).

Na tej stronie są działające edytory: edytuj, uruchamiaj i od razu zobacz wynik.

Routing w Express przypisuje metodę HTTP i ścieżkę do funkcji handlera: app.get('/users', handler) odpowiada na żądania GET do /users, a app.post(), app.put() i app.delete() robią to samo dla innych metod. Segment zaczynający się od dwukropka, jak w /users/:id, to parametr trasy, którego wartość trafia do req.params. Żeby rosnąca aplikacja nie zamieniła się w bałagan, umieszczaj powiązane trasy w express.Router() i podpinaj go pod prefiks przez app.use('/api', router).

GET /users/2 odpowiada {"id":2,"name":"Linus"}. Parametry trasy to zawsze stringi, dlatego handler porównuje z Number(req.params.id). Wyślij POST /users z body {"name": "Grace"}, żeby dostać 201, a potem DELETE /users/1 i GET /users, żeby zobaczyć, jak zmienia się lista.

express.Router() z prefiksem

Router to mini aplikacja z własnymi trasami i middleware. Jego ścieżki są względne: trasa zapisana jako /:id w routerze podpiętym pod /api/books odpowiada na /api/books/:id. W prawdziwym projekcie każdy router siedzi w osobnym pliku i kończy się module.exports = router.

GET /api/books/1 zwraca {"id":1,"title":"Dune"}. router.route('/:id') zapisuje ścieżkę raz i łączy po jednym handlerze na metodę; wyślij PUT /api/books/1, a dostaniesz {"updated":"1"}. Zmień ścieżkę podpięcia na /v2/books, a ten sam router odpowie tam.

Kolejność tras: wygrywa pierwsze dopasowanie

Express sprawdza trasy w kolejności rejestracji i zatrzymuje się na pierwszej, która wyśle odpowiedź. Trasa z parametrem łapie wszystko na swojej pozycji, więc stała ścieżka zarejestrowana po niej nigdy nie zostanie osiągnięta:

GET /users/new odpowiada {"route":"/users/:id","id":"new"}: trasa z parametrem była zarejestrowana pierwsza i przejęła żądanie. Przenieś trasę /users/new nad /users/:id i uruchom ponownie, żeby dostać {"route":"/users/new"}. Potem wyślij GET /books, żeby trafić do handlera 404 na samym dole.

Handler 404

Na żądanie bez pasującej trasy Express odpowiada własną stroną HTML, Cannot GET /books. W API zwykle chcesz JSON, więc dodaj app.use() bez ścieżki jako ostatnią trasę, jak w bloku powyżej. Wykonuje się tylko wtedy, gdy każda wcześniejsza trasa przepuściła żądanie dalej. Błędy rzucane przez handlery to inna sprawa, z własnym handlerem z czterema argumentami, opisanym w obsłudze błędów w Express.

Ścieżki tras w Express 5

Express 5 zmienił składnię ścieżek, a większość fragmentów kodu w sieci jest napisana pod Express 4:

WzorzecExpress 4Express 5
Dowolna ścieżkaapp.get('*', fn)app.get('/*splat', fn)
Opcjonalny parametr/users/:id?/users{/:id}
Wzorzec na parametrze/users/:id(\\d+)Nieobsługiwany; sprawdź wartość w handlerze

Samo * albo ? po parametrze rzuca TypeError przy rejestracji trasy, więc aplikacja się nie uruchomi.

Częste błędy

Rejestrowanie handlera 404 jako pierwszego. app.use() bez ścieżki pasuje do wszystkiego, więc każde żądanie dostaje 404. Trzymaj go na samym dole.

Zapominanie, że prefiks jest usuwany. W routerze podpiętym pod /api req.path nie zawiera /api. Użyj req.originalUrl, gdy potrzebujesz pełnej ścieżki.

Porównywanie parametru z liczbą. req.params.id === 1 zawsze daje false, bo req.params.id to string '1'.

Najczęściej zadawane pytania

Czym różni się app.use od app.get?

app.get('/users', fn) uruchamia fn tylko dla żądań GET, których ścieżka to dokładnie /users. app.use('/users', fn) działa dla każdej metody i każdej ścieżki zaczynającej się od /users, dlatego używa się go do podpinania routerów i middleware.

Jak sprawić, żeby trasy w Express rozróżniały wielkość liter?

Domyślnie trasy ignorują wielkość liter, więc /Users pasuje do /users. Wyłączysz to przez app.set('case sensitive routing', true) albo dla jednego routera przez express.Router({ caseSensitive: true }).

Dlaczego req.params jest pusty w zagnieżdżonym routerze?

Router widzi tylko parametry swoich własnych ścieżek. Jeśli jest podpięty pod /users/:userId/posts, utwórz go przez express.Router({ mergeParams: true }), żeby req.params.userId ze ścieżki nadrzędnej był dostępny.

Czy wszystkie trasy powinny być w jednym pliku?

Nie, gdy masz ich więcej niż kilka. Utwórz jeden router na zasób (routes/users.js, routes/orders.js), wyeksportuj go przez module.exports = router i podepnij każdy w głównym pliku przez app.use().

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

Zacznij