Thứ tự rất quan trọng
Thuộc phần Kiến thức cơ bản về Express trong hành trình Node.js của Coddy. Bài học 14 trên 23.
Express chạy middleware và các route theo thứ tự bạn thêm chúng vào code, và một route trả lời sẽ kết thúc yêu cầu tại đó.
app.get('/bikes', (req, res) => {
res.json(bikes);
});
app.use((req, res, next) => {
res.set('Cache-Control', 'no-store');
next();
});res.set(name, value) thêm một tiêu đề vào phản hồi, và phải chạy hàm này trước khi gửi phản hồi. Ở đây, GET /bikes trả lời trước khi middleware được chạy, nên phản hồi của nó không bao giờ có tiêu đề này: middleware chỉ nhận được những yêu cầu mà không có route nào phía trên trả lời. Middleware cần tác động đến mọi phản hồi phải nằm phía trên các route và phía trên express.static.
Thử thách
DễMỗi phản hồi đều có một mã id, để khi khách truy cập báo sự cố, bạn có thể tìm yêu cầu của họ trong nhật ký. Mọi phản hồi đều cần có mã này: trang, dữ liệu API và tệp do public gửi.
- Trong
server.js, nhậprandomUUIDtừnode:crypto. Mỗi lần gọi hàm này sẽ trả về một mã id ngẫu nhiên mới, chẳng hạn3b241101-e2bb-4255-8caf-4136c566a962. - Thêm một middleware để đặt tiêu đề phản hồi có tên
X-Request-Id, chứa mộtrandomUUID()mới cho mỗi yêu cầu, rồi gọinext(). - Đặt middleware này sao cho mọi yêu cầu đều đi qua nó, kể cả các tệp mà
express.staticgửi. Phản hồi chỉ có tiêu đề này nếu middleware chạy trước khi có thứ gì đó gửi phản hồi.
Thử ngay: Nhấn Chạy rồi gửi /api/recipes hai lần. Trong thẻ Headers, X-Request-Id có giá trị khác nhau mỗi lần. Gửi /style.css và /: mỗi phản hồi cũng có X-Request-Id.
Tự làm thử
import { escapeHtml } from './html.js';
import express from 'express';
import { recipes } from './data.js';
const app = express();
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`);
next();
});
app.use(express.static('public'));
app.get('/', (req, res) => {
const items = recipes.map((r) => `<li><a href="/recipes/${r.id}">${escapeHtml(r.title)}</a></li>`);
res.send(`<link rel="stylesheet" href="/style.css"><h1>Recipe Box</h1><ul>${items.join('')}</ul>`);
});
// type('text') gửi văn bản thuần túy, nên mỗi tiêu đề hiển thị trên một dòng riêng.
app.get('/recipes', (req, res) => {
const { tag } = req.query;
const list = tag ? recipes.filter((recipe) => recipe.tags.includes(tag)) : recipes;
res.type('text').send(list.map((recipe) => recipe.title).join('\n'));
});
app.get('/recipes/:id', (req, res) => {
const recipe = recipes.find((r) => r.id === Number(req.params.id));
if (!recipe) {
res.status(404).send('No such recipe');
return;
}
res.send(recipe.title);
});
app.get('/api/recipes', (req, res) => {
res.json(recipes);
});
app.get('/api/recipes/:id', (req, res) => {
const recipe = recipes.find((r) => r.id === Number(req.params.id));
if (!recipe) {
res.status(404).json({ error: 'No such recipe' });
return;
}
res.json(recipe);
});
app.get('/about', (req, res) => {
res.send('Recipe Box collects family recipes.');
});
app.get('/menu', (req, res) => {
res.redirect(301, '/recipes');
});
app.get('/menu/:id', (req, res) => {
res.redirect(301, `/recipes/${req.params.id}`);
});
app.listen(3000, () => {
console.log('Recipe Box is running on port 3000');
});
Tất cả bài học trong Kiến thức cơ bản về Express
1Máy chủ đầu tiên của bạn
Xin chào, ExpressModule httpThêm tuyến đườngTham số tuyến đường3Middleware
Middleware đầu tiên của bạnTự luyện tập: Playground Express