Menu

Express Router וניתוב: routes, פרמטרים ו-prefixes

route ב-Express הוא method, נתיב ו-handler: app.get('/users/:id', handler). קבצו routes קשורים ב-express.Router() וחברו אותו תחת prefix עם app.use('/api', router).

בדף הזה יש עורכים שאפשר להריץ. לערוך, להריץ ולראות את הפלט מיד.

ניתוב ב-Express ממפה method של HTTP ונתיב לפונקציית handler: ‏app.get('/users', handler) עונה לבקשות GET ל-/users, ו-app.post(), app.put() ו-app.delete() עושים את אותו הדבר לשאר ה-methods. קטע שמתחיל בנקודתיים, כמו ב-/users/:id, הוא פרמטר של route, והערך שלו נכנס ל-req.params. כדי לשמור על סדר באפליקציה שגדלה, שימו routes קשורים ב-express.Router() וחברו אותו תחת prefix עם app.use('/api', router).

GET /users/2 עונה {"id":2,"name":"Linus"}. פרמטרים של route הם תמיד מחרוזות, ולכן ה-handler משווה עם Number(req.params.id). שלחו POST /users עם הגוף {"name": "Grace"} כדי לקבל 201, ואז DELETE /users/1 ו-GET /users כדי לראות את הרשימה משתנה.

express.Router() עם prefix

router הוא מיני אפליקציה עם routes ו-middleware משלו. הנתיבים שלו יחסיים: route שנכתב כ-/:id בתוך router שמחובר ב-/api/books עונה ל-/api/books/:id. בפרויקט אמיתי כל router יושב בקובץ משלו ומסתיים ב-module.exports = router.

GET /api/books/1 מחזיר {"id":1,"title":"Dune"}. ‏router.route('/:id') כותב את הנתיב פעם אחת ומשרשר handler אחד לכל method; שלחו PUT /api/books/1 ותקבלו {"updated":"1"}. שנו את נתיב החיבור ל-/v2/books ואותו router יענה שם במקום.

סדר ה-routes: ההתאמה הראשונה מנצחת

Express מנסה routes לפי הסדר שבו רשמתם אותם ועוצר בראשון ששולח תשובה. route עם פרמטר תופס כל דבר במיקום שלו, כך שנתיב קבוע שנרשם אחריו לא מגיעים אליו אף פעם:

GET /users/new עונה {"route":"/users/:id","id":"new"}: ה-route עם הפרמטר נרשם ראשון ותפס את הבקשה. העבירו את ה-route של /users/new אל מעל /users/:id והריצו שוב כדי לקבל {"route":"/users/new"}. אחר כך שלחו GET /books כדי להגיע ל-handler של ה-404 בתחתית.

ה-handler של 404

Express עונה לבקשה שלא נמצאה לה התאמה בדף HTML משלו, Cannot GET /books. ב-API בדרך כלל רוצים JSON, אז הוסיפו app.use() בלי נתיב בתור ה-route האחרון ממש, כמו בבלוק שלמעלה. הוא רץ רק כשכל route לפניו העביר את הבקשה הלאה. שגיאות שנזרקות מ-handlers הן מקרה אחר עם handler משלהן שמקבל ארבעה ארגומנטים, ומוסברות ב-טיפול בשגיאות ב-Express.

נתיבי routes ב-Express 5

Express 5 שינה את התחביר של הנתיבים, ורוב הקטעים ברשת כתובים ל-Express 4:

תבניתExpress 4Express 5
כל נתיבapp.get('*', fn)app.get('/*splat', fn)
פרמטר אופציונלי/users/:id?/users{/:id}
תבנית על פרמטר/users/:id(\\d+)לא נתמך; בדקו את הערך ב-handler

* לבד או ? אחרי פרמטר זורקים TypeError כשה-route נרשם, כך שהאפליקציה לא עולה.

טעויות נפוצות

לרשום את ה-handler של 404 ראשון. app.use() בלי נתיב תואם לכל דבר, כך שכל בקשה מקבלת 404. השאירו אותו בתחתית.

לשכוח שה-prefix מוסר. בתוך router שמחובר ב-/api, ‏req.path לא כולל את /api. השתמשו ב-req.originalUrl כשאתם צריכים את הנתיב המלא.

השוואה של פרמטר למספר. req.params.id === 1 תמיד false, כי req.params.id הוא המחרוזת '1'.

שאלות נפוצות

מה ההבדל בין app.use ל-app.get?

app.get('/users', fn) מריץ את fn רק לבקשות GET שהנתיב שלהן הוא בדיוק /users. app.use('/users', fn) רץ לכל method ולכל נתיב שמתחיל ב-/users, ולכן משתמשים בו כדי לחבר routers ו-middleware.

איך הופכים routes ב-Express לרגישים לאותיות גדולות וקטנות?

כברירת מחדל routes מתעלמים מגודל האותיות, כך ש-/Users תואם ל-/users. כבו את זה עם app.set('case sensitive routing', true), או לכל router בנפרד עם express.Router({ caseSensitive: true }).

למה req.params ריק בתוך router מקונן?

router רואה רק את הפרמטרים של הנתיבים שלו. אם הוא מחובר ב-/users/:userId/posts, צרו אותו עם express.Router({ mergeParams: true }) כדי ש-req.params.userId מהנתיב של ההורה יהיה זמין.

לשים את כל ה-routes בקובץ אחד?

לא כשיש יותר מכמה בודדים. צרו router אחד לכל משאב (routes/users.js, routes/orders.js), ייצאו אותו עם module.exports = router, וחברו כל אחד בקובץ הראשי עם app.use().

איור של שפות התכנות ב-Coddy

ללמוד תכנות עם Coddy

להתחיל