什么是negotiator
?
negotiator
是一个轻量级的Node.js库,用于处理HTTP请求中的内容协商(Content Negotiation)。内容协商是客户端(如浏览器或React前端)和服务器之间的一种机制,通过HTTP头信息(如Accept
、Accept-Language
、Accept-Encoding
等)来协商服务器应该返回的数据格式、语言或编码方式。
简单来说,negotiator
帮你解析客户端发送的这些头信息,并根据服务器支持的选项,决定最佳的响应内容。它常用于Web开发中,尤其是API服务器,确保客户端收到它“最想要”的数据格式。
主要用途
- 解析
Accept
头:确定客户端接受的媒体类型(如application/json
、text/html
等)。 - 解析
Accept-Language
头:确定客户端首选的语言(如en-US
、zh-CN
)。 - 解析
Accept-Encoding
头:确定客户端支持的编码方式(如gzip
、deflate
)。 - 提高API兼容性:让服务器动态适应不同客户端的需求。
这个库特别适合用在Express.js这样的Web框架中,或者任何需要处理HTTP请求的Node.js应用。
安装
你可以通过npm安装:
npm install negotiator
小例子
下面是一个简单的Express应用,使用negotiator
来处理Accept
头,根据客户端请求返回不同格式的数据。
const express = require('express');
const Negotiator = require('negotiator');
const app = express();
app.get('/data', (req, res) => {
// 创建Negotiator实例,传入HTTP请求对象
const negotiator = new Negotiator(req);
// 服务器支持的媒体类型
const availableTypes = ['application/json', 'text/plain', 'text/html'];
// 根据客户端的Accept头,协商出最佳媒体类型
const bestType = negotiator.mediaType(availableTypes);
// 根据协商结果返回响应
switch (bestType) {
case 'application/json':
res.json({ message: 'Hello in JSON!' });
break;
case 'text/plain':
res.send('Hello in plain text!');
break;
case 'text/html':
res.send('<h1>Hello in HTML!</h1>');
break;
default:
// 如果没有匹配的类型,返回406状态码(Not Acceptable)
res.status(406).send('Not Acceptable');
}
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
运行和测试
- 保存代码为
server.js
,然后运行:node server.js
- 用
curl
或浏览器测试:- 请求JSON格式:
输出:curl -H "Accept: application/json" http://localhost:3000/data
{"message":"Hello in JSON!"}
- 请求HTML格式:
输出:curl -H "Accept: text/html" http://localhost:3000/data
<h1>Hello in HTML!</h1>
- 请求不支持的格式:
输出:curl -H "Accept: image/png" http://localhost:3000/data
Not Acceptable
- 请求JSON格式:
工作原理
- 客户端在HTTP请求中通过
Accept
头告诉服务器它想要的格式(比如Accept: application/json, text/html;q=0.9
)。 negotiator
解析这个头,并根据服务器提供的availableTypes
列表,挑出优先级最高的匹配类型。- 如果没有匹配,服务器可以返回错误(如406)。
实际应用场景
- 多格式API:你的API需要支持JSON、XML等多种格式时,
negotiator
能帮你动态选择。 - 国际化:结合
Accept-Language
,返回用户首选语言的内容。 - 性能优化:通过
Accept-Encoding
决定是否压缩响应(如用gzip
)。