Appearance
Express请求与响应
在Express中,请求(req)和响应(res)对象是处理HTTP请求的核心。理解这两个对象的属性和方法对于开发Express应用至关重要。
请求对象(req)
请求对象(req)代表HTTP请求,包含请求的查询字符串、参数、body、HTTP头等信息。
请求路径信息
javascript
app.get('/users/:id', (req, res) => {
console.log(req.path); // 请求路径,如 '/users/123'
console.log(req.url); // 完整URL,包括查询参数
console.log(req.baseUrl); // 路由匹配的URL路径
console.log(req.originalUrl); // 原始请求URL
console.log(req.method); // HTTP方法,如 'GET', 'POST'
});
请求参数
路由参数(req.params)
javascript
// GET /users/123/books/456
app.get('/users/:userId/books/:bookId', (req, res) => {
console.log(req.params.userId); // '123'
console.log(req.params.bookId); // '456'
res.send(req.params);
});
查询参数(req.query)
javascript
// GET /search?q=express&sort=asc&category=nodejs
app.get('/search', (req, res) => {
console.log(req.query.q); // 'express'
console.log(req.query.sort); // 'asc'
console.log(req.query.category); // 'nodejs'
// 处理可选参数
const page = req.query.page || 1;
const limit = req.query.limit || 10;
res.json({
query: req.query,
pagination: { page: parseInt(page), limit: parseInt(limit) }
});
});
请求体参数(req.body)
javascript
// 需要中间件解析请求体
app.use(express.json()); // 解析JSON
app.use(express.urlencoded({ extended: true })); // 解析URL编码
app.post('/users', (req, res) => {
console.log(req.body.name); // 从请求体获取数据
console.log(req.body.email); // 从请求体获取数据
res.json({ message: 'User created', user: req.body });
});
请求头信息
javascript
app.get('/headers', (req, res) => {
console.log(req.headers); // 所有请求头
console.log(req.headers['content-type']); // 特定请求头
console.log(req.headers['user-agent']); // 用户代理
console.log(req.headers['authorization']); // 认证信息
// 获取IP地址
console.log(req.ip); // 客户端IP
console.log(req.ips); // 信任代理时的IP数组
// 获取主机信息
console.log(req.hostname); // 主机名
console.log(req.protocol); // 协议 (http/https)
console.log(req.secure); // 是否HTTPS
res.json({
ip: req.ip,
hostname: req.hostname,
protocol: req.protocol,
headers: req.headers
});
});
请求方法和状态
javascript
app.all('/all-methods', (req, res) => {
console.log(req.method); // HTTP方法
console.log(req.accepts('json')); // 检查是否接受JSON
console.log(req.accepts(['json', 'text'])); // 检查接受的格式
console.log(req.get('Content-Type')); // 获取特定头信息
// 检查内容类型
if (req.is('json')) {
console.log('Request is JSON');
} else if (req.is('urlencoded')) {
console.log('Request is URL encoded');
}
res.send(`Method: ${req.method}`);
});
响应对象(res)
响应对象(res)表示HTTP响应,Express应用在处理请求时发送给客户端。
基本响应方法
res.send() - 发送响应
javascript
app.get('/send', (req, res) => {
// 发送字符串
res.send('Hello World');
// 发送对象
res.send({ message: 'Hello', status: 'success' });
// 发送数组
res.send([1, 2, 3]);
// 发送状态码
res.status(404).send('Not Found');
});
res.json() - 发送JSON响应
javascript
app.get('/json', (req, res) => {
// 自动设置Content-Type为application/json
res.json({
message: 'Hello JSON',
timestamp: new Date().toISOString(),
data: [1, 2, 3]
});
// 发送数组
res.json([1, 2, 3, 4]);
// 发送null或undefined
res.json(null);
});
res.jsonp() - 发送JSONP响应
javascript
app.get('/jsonp', (req, res) => {
// 支持JSONP回调
res.jsonp({
message: 'Hello JSONP',
data: { id: 1, name: 'Example' }
});
});
响应状态码
javascript
app.get('/status', (req, res) => {
// 设置状态码
res.status(201).send('Created'); // 201 Created
res.status(400).json({ error: 'Bad Request' }); // 400 Bad Request
res.status(404).send('Not Found'); // 404 Not Found
res.status(500).send('Server Error'); // 500 Server Error
// 使用状态码方法
res.sendStatus(200); // 发送状态码文本
});
响应头设置
javascript
app.get('/headers', (req, res) => {
// 设置响应头
res.set('Content-Type', 'text/html');
res.set({
'X-API-Key': 'foobar',
'Content-Type': 'application/json'
});
// 链式调用
res
.set('X-Custom-Header', 'value')
.status(200)
.json({ message: 'With custom headers' });
// 重定向头
res.location('/new-path').send('Redirecting...');
});
重定向响应
javascript
app.get('/redirect', (req, res) => {
// 临时重定向 (302)
res.redirect('/new-location');
// 指定状态码的重定向
res.redirect(301, '/permanently-moved'); // 永久重定向
// 重定向到外部URL
res.redirect('https://example.com');
// 相对路径重定向
res.redirect('back'); // 重定向到Referer或Referrer头
});
视图渲染
javascript
// 设置模板引擎
app.set('view engine', 'ejs');
app.set('views', './views');
app.get('/render', (req, res) => {
// 渲染视图模板
res.render('index', {
title: 'My Page',
message: 'Hello from template',
users: [{ name: 'John' }, { name: 'Jane' }]
});
});
文件响应
javascript
app.get('/download', (req, res) => {
// 下载文件
res.download('./files/report.pdf', 'report.pdf');
});
app.get('/file', (req, res) => {
// 发送文件
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});
app.get('/attachment', (req, res) => {
// 作为附件发送
res.attachment('filename.txt');
res.send('File content');
});
高级请求处理
Cookie处理
javascript
// 需要cookie-parser中间件
const cookieParser = require('cookie-parser');
app.use(cookieParser());
app.get('/cookies', (req, res) => {
console.log(req.cookies); // 所有cookies
console.log(req.cookies.username); // 特定cookie
// 设置cookie
res.cookie('username', 'john', {
maxAge: 900000, // 15分钟
httpOnly: true,
secure: true // 仅HTTPS
});
res.send('Cookie set');
});
// 清除cookie
app.get('/clear-cookie', (req, res) => {
res.clearCookie('username');
res.send('Cookie cleared');
});
会话处理
javascript
// 需要express-session中间件
const session = require('express-session');
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
cookie: { secure: false } // 在生产环境中设为true
}));
app.get('/session', (req, res) => {
if (req.session.views) {
req.session.views++;
res.send(`Views: ${req.session.views}`);
} else {
req.session.views = 1;
res.send('Welcome to the session demo. Refresh page!');
}
});
高级响应模式
流式响应
javascript
const fs = require('fs');
app.get('/stream', (req, res) => {
const stream = fs.createReadStream('./large-file.txt');
stream.pipe(res);
});
条件响应
javascript
app.get('/conditional', (req, res) => {
// 检查请求是否可以接受JSON
if (req.accepts('json')) {
res.json({ message: 'JSON response' });
} else if (req.accepts('html')) {
res.send('<h1>HTML response</h1>');
} else {
res.type('txt').send('Plain text response');
}
});
响应格式化
javascript
app.get('/format', (req, res) => {
res.format({
'text/plain': () => {
res.send('Hello World');
},
'text/html': () => {
res.send('<p>Hello World</p>');
},
'application/json': () => {
res.json({ message: 'Hello World' });
},
'default': () => {
res.status(406).send('Not Acceptable');
}
});
});
请求和响应最佳实践
1. 错误处理
javascript
app.get('/error-handling', (req, res, next) => {
try {
// 可能出错的代码
const result = riskyOperation();
res.json({ result });
} catch (error) {
next(error); // 传递给错误处理中间件
}
});
2. 数据验证
javascript
const validateUser = (req, res, next) => {
const { name, email } = req.body;
if (!name || !email) {
return res.status(400).json({
error: 'Name and email are required'
});
}
next(); // 验证通过,继续执行
};
app.post('/users', validateUser, (req, res) => {
res.json({ message: 'User created successfully' });
});
3. 响应缓存
javascript
app.get('/cached', (req, res) => {
// 设置缓存头
res.set({
'Cache-Control': 'public, max-age=3600', // 缓存1小时
'ETag': 'unique-identifier'
});
res.json({ data: 'cached data', timestamp: Date.now() });
});
通过掌握请求和响应对象的各种属性和方法,可以构建功能强大且灵活的Express应用,有效处理各种HTTP请求和响应场景。