שרת HTTP בלי ספריות
לפני שעוברים ל-Express, כדאי לראות מה קורה מתחת למכסה: Node.js יודע לבנות שרת ווב בעצמו, עם המודול המובנה http. זה עוזר להבין מה Express עושה בשבילכם.
השרת הראשון
import http from 'node:http';
const server = http.createServer((request, response) => {
response.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
response.end('שלום מהשרת!');
});
server.listen(3000, () => {
console.log('השרת רץ בכתובת http://localhost:3000');
});
שמרו כ-server.js, הריצו node server.js ופתחו את הכתובת בדפדפן. הפונקציה שמועברת ל-createServer רצה על כל בקשה, ומקבלת שני אובייקטים:
- request - מה הדפדפן שלח:
method,url,headers. - response - מה שחוזר: קוד סטטוס, headers ותוכן. חובה לסיים ב-
response.end(), אחרת הדפדפן מחכה לנצח.
עצרו את השרת עם Ctrl+C. כדי שיעלה מחדש בכל שמירה: node --watch server.js.
ניתוב ידני
אין כאן app.get. כל ההחלטות הן if על הכתובת והשיטה:
import http from 'node:http';
const users = [{ id: 1, name: 'דנה' }, { id: 2, name: 'יוסי' }];
function sendJson(response, status, data) {
response.writeHead(status, { 'Content-Type': 'application/json; charset=utf-8' });
response.end(JSON.stringify(data));
}
const server = http.createServer((request, response) => {
// URL מפרק את הכתובת לחלקים (pathname, searchParams)
const url = new URL(request.url, `http://${request.headers.host}`);
if (request.method === 'GET' && url.pathname === '/api/users') {
return sendJson(response, 200, users);
}
const match = url.pathname.match(/^\/api\/users\/(\d+)$/);
if (request.method === 'GET' && match) {
const user = users.find((item) => item.id === Number(match[1]));
return user ? sendJson(response, 200, user) : sendJson(response, 404, { error: 'לא נמצא' });
}
sendJson(response, 404, { error: 'אין נתיב כזה' });
});
server.listen(3000);
קריאת גוף הבקשה (POST)
הגוף מגיע בחתיכות (stream), וצריך לאסוף אותו לבד. זה בדיוק מה ש-express.json() עושה בשורה אחת:
async function readJsonBody(request) {
const chunks = [];
for await (const chunk of request) {
chunks.push(chunk);
}
const text = Buffer.concat(chunks).toString('utf8');
return text ? JSON.parse(text) : {};
}
const server = http.createServer(async (request, response) => {
if (request.method === 'POST' && request.url === '/api/users') {
try {
const body = await readJsonBody(request);
const user = { id: users.length + 1, name: body.name };
users.push(user);
return sendJson(response, 201, user);
} catch (error) {
return sendJson(response, 400, { error: 'JSON לא תקין' });
}
}
sendJson(response, 404, { error: 'אין נתיב כזה' });
});
קודי סטטוס שכדאי להכיר
| קוד | משמעות |
|---|---|
200 | הצליח |
201 | נוצר (אחרי POST) |
204 | הצליח, בלי תוכן (אחרי DELETE) |
400 | בקשה לא תקינה |
401 / 403 | לא מחובר / אין הרשאה |
404 | לא נמצא |
500 | שגיאה בשרת |
גם לקוח: fetch מתוך Node.js
Node.js כולל fetch מובנה, בדיוק כמו בדפדפן, כך שאפשר גם לפנות לשרתים אחרים:
const response = await fetch('https://api.github.com/repos/nodejs/node');
const repo = await response.json();
console.log(`ל-Node.js יש ${repo.stargazers_count} כוכבים`);
אז למה Express?
ראיתם שאפשר לבנות הכול לבד, וגם כמה זה מתארך: ניתוב עם ביטויים רגולריים, איסוף גוף הבקשה, טיפול בשגיאות, קבצים סטטיים. Express עוטף בדיוק את המודול הזה, ונותן לכל אחד מהדברים האלה שורה אחת.
דוגמאות מלאות להרצה
simple-server.js- שרת שמחזיר דף HTMLrouting.js- ניתוב ידני לכמה דפים ו-API
בדקו את עצמכם
נסו לענות לבד לפני שאתם פותחים את התשובה.
-
מה חובה לקרוא בסוף כל תשובה בשרת http?
הצגת התשובה
תשובה ג. בלי end() הדפדפן ממשיך לחכות לתשובה.
-
למה Express קיים אם אפשר לבנות שרת עם http לבד?
הצגת התשובה
תשובה ב. Express עוטף את מודול http ונותן לכל צורך שורה אחת.