ב-Express, req.params מחזיק את הערכים של הקטעים עם השם בנתיב של ה-route (/users/:id נותן req.params.id), req.query מחזיק את ה-query string שאחרי ה-? (/search?q=node נותן req.query.q), ו-req.body מחזיק את הנתונים שנשלחו בגוף הבקשה. req.params ו-req.query מתמלאים בכל בקשה, אבל req.body נשאר undefined עד ש-body parser כמו app.use(express.json()) קורא אותו. ערכים ב-params וב-query הם תמיד מחרוזות.
הבקשה הראשונה עונה {"params":{"userId":"7"},"query":{"sort":"new","limit":"2"}}. שימו לב למרכאות: 7 ו-2 הם מחרוזות, אז המירו אותם עם Number() לפני שאתם עושים חשבון או משווים למספרים. עכשיו החליפו את ה-method ל-POST, השאירו את הנתיב /users/7/posts ושלחו את הגוף {"title": "Hello", "draft": true}: התשובה היא 201 עם "body":{"title":"Hello","draft":true}, ושם true הוא בוליאני אמיתי, כי הוא הגיע מ-JSON.
req.params מול req.query מול req.body
req.params | req.query | req.body | |
|---|---|---|---|
| מגיע מ | הנתיב, /users/:id | ה-query string, ?sort=new | גוף הבקשה |
| דוגמה ל-URL או לגוף | /users/7 | /users?sort=new | {"name": "Ada"} |
| ערך | { id: '7' } | { sort: 'new' } | { name: 'Ada' } |
| טיפוסים | מחרוזות | מחרוזות ומערכים של מחרוזות | מה שה-JSON מחזיק |
| צריך הגדרה | :name ב-route | כלום | app.use(express.json()) |
| שימוש טיפוסי | איזה משאב | סינון, מיון, עמוד | נתונים ליצירה או לעדכון |
ל-route יכולים להיות כמה פרמטרים, וכל שם הופך למפתח של req.params: /teams/:teamId/members/:memberId נותן את שני ה-ids. גם מקף או נקודה מפרידים ביניהם, כך ש-/flights/:from-:to הופך את /flights/LAX-SFO ל-{ from: 'LAX', to: 'SFO' }.
req.query עם מפתחות חוזרים וחסרים
מפתח שמופיע פעמיים הופך למערך, ומפתח שחסר הוא undefined, אז תנו לאפשרויות ברירת מחדל:
התשובה היא {"page":1,"tags":["red","sale"],"raw":{"tag":["red","sale"]}}. שלחו GET /products?tag=red&page=3 ו-tags עדיין מערך, ["red"], כי [].concat() הופך מחרוזת בודדת או מערך למערך. Express 5 מפענח query strings עם הפענוח הפשוט של Node, כך ש-?filter[size]=m נותן את המפתח "filter[size]" ולא אובייקט מקונן; Express 4 קינן אותו.
req.body צריך את express.json()
Node מעביר את הגוף כ-stream של בייטים. express.json() קורא אותו, מפענח אותו ומגדיר את req.body, אבל רק כשלבקשה יש Content-Type: application/json. טפסי HTML שולחים application/x-www-form-urlencoded, ושם צריך את express.urlencoded() במקום.
שלחו POST /signup עם הגוף {"email": "ada@example.com"} ותקבלו 201 עם {"email":"ada@example.com","name":"anonymous"}. שלחו גוף ריק ותקבלו 400. ה-?? {} חשוב: בלעדיו, destructuring של undefined זורק TypeError בכל בקשה שאין לה גוף JSON. לבדיקה אמיתית של המבנה והטיפוסים, השתמשו בספריית schemas כמו zod.
req.headers ו-req.get()
req.headers הוא אובייקט של כל ה-headers של הבקשה, עם שמות באותיות קטנות. req.get(name) קורא header אחד ומתעלם מגודל האותיות, כך ש-req.get('Content-Type') ו-req.get('content-type') מחזירים את אותו ערך. עוד כמה מאפיינים שתשתמשו בהם:
path הוא /whoami ו-originalUrl הוא /whoami?debug=1. הוסיפו בשורת הבקשה את ה-header Authorization: Bearer abc ושלחו שוב: token הופך ל-"Bearer abc". בתוך router שמחובר עם app.use('/api', router), req.path מאבד את ה-prefix /api ואילו req.originalUrl שומר אותו (ניתוב ב-Express מסביר את החיבור).
טעויות נפוצות
קריאת req.body בבקשת GET. דפדפנים ורוב הלקוחות לא שולחים גוף עם GET. שימו את האפשרויות של GET ב-query string.
בדיקה של דגל ב-query לפי truthiness. ?admin=false נותן את המחרוזת 'false', שהיא truthy, ולכן if (req.query.admin) עובר. השוו מחרוזות: req.query.admin === 'true'.
שליחת JSON בלי ה-header. לקוח ששולח JSON כ-text/plain מקבל req.body === undefined. הגדירו Content-Type: application/json בצד הלקוח.
שאלות נפוצות
איך מקבלים את כתובת ה-IP של הלקוח ב-Express?
קוראים את req.ip. מאחורי proxy או load balancer זו הכתובת של ה-proxy, עד שמגדירים app.set('trust proxy', 1), ואז Express קורא במקום את ה-header X-Forwarded-For.
איך מקבלים את ה-URL המלא של בקשה ב-Express?
req.originalUrl הוא הנתיב ועוד ה-query string כפי שהלקוח שלח אותם. בנו את ה-URL המוחלט עם `${req.protocol}://${req.get('host')}${req.originalUrl}`.
איך מטפלים בהעלאת קבצים ב-Express?
העלאות קבצים מגיעות כ-multipart/form-data, ש-express.json() ו-express.urlencoded() לא מפענחים. השתמשו בחבילה כמו multer, ששמה את הקבצים ב-req.file או ב-req.files ואת שאר השדות ב-req.body.
איך קוראים cookie מהבקשה?
ה-header הגולמי נמצא ב-req.get('cookie'). כדי לקבל אובייקט ב-req.cookies, התקינו את החבילה cookie-parser והוסיפו app.use(cookieParser()).