请求头信息的读取与设置
请求头信息的读取与设置
Koa2框架中处理HTTP请求时,请求头信息是客户端与服务器交互的重要组成部分。通过ctx.request对象可以方便地获取和操作这些头信息,同时也能通过ctx.response对象设置响应头。
请求头信息的读取
在Koa2中,可以通过ctx.request.header或ctx.headers访问完整的请求头对象。这些头信息以键值对的形式存在,键名会被统一转换为小写形式。
app.use(async (ctx) => {
// 获取所有请求头
const headers = ctx.headers;
console.log(headers);
// 获取特定请求头
const userAgent = ctx.get('User-Agent');
const contentType = ctx.request.get('Content-Type');
ctx.body = {
userAgent,
contentType
};
});
常用的请求头读取方法包括:
- ctx.get(field): 获取指定请求头字段
- ctx.request.get(field): 同上,两种写法等效
- ctx.header: 获取全部请求头对象
- ctx.headers: header的别名
请求头信息的设置
响应头的设置主要通过ctx.set()或ctx.response.set()方法实现。Koa2会自动设置一些默认响应头,如Content-Type默认为text/plain。
app.use(async (ctx) => {
// 设置单个响应头
ctx.set('X-Powered-By', 'Koa2');
// 设置多个响应头
ctx.set({
'Cache-Control': 'no-cache',
'Last-Modified': new Date()
});
// 等效写法
ctx.response.set('Content-Type', 'application/json');
ctx.body = { message: 'Headers set successfully' };
});
特殊头信息处理
某些头信息需要特别注意处理方式:
- Content-Type处理:
app.use(async (ctx) => {
// 获取Content-Type
const type = ctx.type;
// 设置Content-Type
ctx.type = 'application/json';
// 等效于
ctx.set('Content-Type', 'application/json');
});
- ETag和Last-Modified处理:
const fs = require('fs');
const crypto = require('crypto');
app.use(async (ctx) => {
const filePath = './static/image.jpg';
const fileBuffer = fs.readFileSync(filePath);
const hash = crypto.createHash('md5').update(fileBuffer).digest('hex');
ctx.set('ETag', hash);
ctx.set('Last-Modified', new Date(fs.statSync(filePath).mtime).toUTCString());
// 检查客户端缓存
if (ctx.fresh) {
ctx.status = 304;
return;
}
ctx.body = fileBuffer;
});
自定义中间件处理头信息
可以创建中间件统一处理特定头信息:
// 添加X-Response-Time头
app.use(async (ctx, next) => {
const start = Date.now();
await next();
const ms = Date.now() - start;
ctx.set('X-Response-Time', `${ms}ms`);
});
// CORS中间件
app.use(async (ctx, next) => {
ctx.set('Access-Control-Allow-Origin', '*');
ctx.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
ctx.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');
if (ctx.method === 'OPTIONS') {
ctx.status = 204;
return;
}
await next();
});
安全相关的头信息设置
安全头信息对于Web应用至关重要:
app.use(async (ctx, next) => {
ctx.set('X-Frame-Options', 'DENY');
ctx.set('X-Content-Type-Options', 'nosniff');
ctx.set('X-XSS-Protection', '1; mode=block');
ctx.set('Content-Security-Policy', "default-src 'self'");
await next();
});
请求头与响应头的实际应用
- 内容协商:
app.use(async (ctx) => {
// 根据Accept头返回不同格式响应
const accept = ctx.accepts('json', 'html', 'text');
switch(accept) {
case 'json':
ctx.type = 'application/json';
ctx.body = { data: 'JSON response' };
break;
case 'html':
ctx.type = 'text/html';
ctx.body = '<p>HTML response</p>';
break;
default:
ctx.type = 'text/plain';
ctx.body = 'Plain text response';
}
});
- 认证处理:
app.use(async (ctx, next) => {
const authHeader = ctx.get('Authorization');
if (!authHeader || !authHeader.startsWith('Bearer ')) {
ctx.status = 401;
ctx.set('WWW-Authenticate', 'Bearer');
ctx.body = 'Authentication required';
return;
}
const token = authHeader.split(' ')[1];
// 验证token逻辑...
await next();
});
性能优化相关的头设置
app.use(async (ctx, next) => {
await next();
if (ctx.response.is('json')) {
ctx.set('Vary', 'Accept-Encoding');
ctx.set('Cache-Control', 'public, max-age=3600');
}
// 启用HTTP/2服务器推送
if (ctx.response.is('html')) {
ctx.set('Link', '</styles.css>; rel=preload; as=style');
}
});
调试与问题排查
开发过程中可以添加调试头信息:
app.use(async (ctx, next) => {
ctx.set('X-Request-ID', Math.random().toString(36).substr(2, 9));
console.log('Incoming headers:', ctx.headers);
await next();
console.log('Outgoing headers:', ctx.response.headers);
});
头信息处理的注意事项
- 头字段名称大小写不敏感,但建议统一使用小写
- 设置重复头字段时,后者会覆盖前者
- 某些头字段有特殊格式要求,如Set-Cookie
- 头字段值只能是字符串或可以转换为字符串的类型
- 修改头信息应在发送响应体之前完成
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:浏览器引擎优化与设计模式选择
下一篇:多种内容类型的响应处理