跳到主要内容

请求响应

本章节介绍 Express.js 中的请求对象和响应对象的使用方法。

请求对象 (req)

常用属性

app.get('/info', (req, res) => {
const info = {
baseUrl: req.baseUrl,
body: req.body,
cookies: req.cookies,
hostname: req.hostname,
ip: req.ip,
method: req.method,
originalUrl: req.originalUrl,
params: req.params,
path: req.path,
protocol: req.protocol,
query: req.query,
route: req.route,
secure: req.secure,
xhr: req.xhr,
headers: req.headers
};
res.json(info);
});

路径参数

app.get('/users/:userId/books/:bookId', (req, res) => {
const { userId, bookId } = req.params;
res.json({ userId, bookId });
});

查询参数

app.get('/search', (req, res) => {
const { q, page = 1, limit = 10 } = req.query;
res.json({ query: q, page, limit });
});

请求体

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

app.post('/users', (req, res) => {
const { name, email } = req.body;
res.json({ name, email });
});

请求头

app.get('/headers', (req, res) => {
const auth = req.get('Authorization');
const contentType = req.get('Content-Type');
res.json({ auth, contentType });
});

文件上传

npm install multer
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });

app.post('/upload', upload.single('file'), (req, res) => {
res.json({
file: req.file,
body: req.body
});
});

app.post('/photos', upload.array('photos', 12), (req, res) => {
res.json({ files: req.files });
});

响应对象 (res)

发送响应

app.get('/send', (req, res) => {
res.send('Hello World');
});

app.get('/json', (req, res) => {
res.json({ message: 'Hello' });
});

app.get('/status', (req, res) => {
res.status(201).json({ created: true });
});

设置状态码

app.get('/not-found', (req, res) => {
res.status(404).send('Not Found');
});

app.get('/error', (req, res) => {
res.status(500).json({ error: 'Internal Server Error' });
});

设置响应头

app.get('/headers', (req, res) => {
res.set('X-Custom-Header', 'value');
res.set({
'Content-Type': 'application/json',
'Cache-Control': 'no-cache'
});
res.json({ headers: 'set' });
});
app.get('/set-cookie', (req, res) => {
res.cookie('name', 'express', {
maxAge: 900000,
httpOnly: true
});
res.send('Cookie 已设置');
});

app.get('/clear-cookie', (req, res) => {
res.clearCookie('name');
res.send('Cookie 已清除');
});

重定向

app.get('/redirect', (req, res) => {
res.redirect('/home');
});

app.get('/redirect-external', (req, res) => {
res.redirect('https://expressjs.com');
});

app.get('/redirect-status', (req, res) => {
res.redirect(301, '/new-url');
});

文件下载

app.get('/download', (req, res) => {
res.download('/files/report.pdf');
});

app.get('/download-custom', (req, res) => {
res.download('/files/report.pdf', 'report.pdf', (err) => {
if (err) {
console.error(err);
}
});
});

发送文件

app.get('/file', (req, res) => {
res.sendFile('/files/index.html', { root: __dirname });
});

渲染模板

app.set('view engine', 'ejs');

app.get('/profile', (req, res) => {
res.render('profile', {
name: 'Express',
version: '4.x'
});
});

响应格式化

统一响应格式

const response = {
success: (res, data, message = 'Success') => {
res.json({
code: 0,
message,
data
});
},

error: (res, message = 'Error', code = 1, status = 400) => {
res.status(status).json({
code,
message,
data: null
});
}
};

app.get('/users', (req, res) => {
const users = [{ id: 1, name: 'User' }];
response.success(res, users);
});

app.get('/error', (req, res) => {
response.error(res, '资源未找到', 404, 404);
});

分页响应

app.get('/posts', async (req, res) => {
const { page = 1, limit = 10 } = req.query;
const posts = await Post.find()
.skip((page - 1) * limit)
.limit(limit);
const total = await Post.countDocuments();

res.json({
data: posts,
pagination: {
page: parseInt(page),
limit: parseInt(limit),
total,
pages: Math.ceil(total / limit)
}
});
});