什么是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/dataNot 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)。
