如何使用JavaScript的fetch() API发送OPTIONS * HTTP/1.1请求?
如何用fetch()发送
OPTIONS * HTTP/1.1请求 根据RFC 9110(HTTP语义规范):
以星号("")作为请求目标的OPTIONS请求适用于整个服务器,而非特定资源。由于服务器的通信选项通常取决于资源,""请求仅用作“ping”或“无操作(no-op)”类型的方法;除了允许客户端测试服务器的功能外,它不执行任何操作。例如,可用于测试代理是否符合HTTP/1.1规范(或不符合)。
我在Node环境下用JavaScript编写了HTTP服务器,需要编写单元测试来验证它对以下请求的响应:
OPTIONS * HTTP/1.1
已知可以通过Curl实现该请求:
curl --request-target '*' -X OPTIONS https://example.com/
问题:如何使用fetch() API发送这个请求?
解决方案:借助undici的请求拦截器
标准fetch API(包括浏览器和Node原生实现)没有直接提供修改请求目标的接口,因为它的设计逻辑绑定了URL路径。但Node的原生fetch基于undici库,我们可以通过undici的拦截器在请求发送前修改目标为*。
示例代码:
import { fetch, Agent } from 'undici'; async function sendOptionsStarRequest() { // 创建带拦截器的Agent const customAgent = new Agent({ interceptors: { request: (opts, handler) => { // 将请求路径替换为*,即修改请求目标 opts.path = '*'; return handler(opts); } } }); // 发送请求,指定自定义Agent const response = await fetch('http://localhost:3000/', { // 替换为你的服务器地址 method: 'OPTIONS', dispatcher: customAgent }); // 处理响应 console.log('响应状态码:', response.status); console.log('响应头:', Object.fromEntries(response.headers.entries())); } sendOptionsStarRequest();
原理说明
当调用fetch时,默认会把URL的路径部分作为请求目标。通过undici的请求拦截器,我们可以在请求被处理前覆盖path字段为*,从而构造出符合要求的OPTIONS * HTTP/1.1请求。
替代方案:直接使用Node内置http模块
如果单元测试无需严格依赖fetch,可以直接用Node原生http模块发送请求,代码更简洁:
import http from 'node:http'; const request = http.request({ hostname: 'localhost', port: 3000, method: 'OPTIONS', path: '*' // 直接指定请求目标为* }, (res) => { console.log(`状态码: ${res.statusCode}`); console.log(`响应头: ${JSON.stringify(res.headers)}`); res.resume(); // 消费响应流,避免内存泄漏 }); request.end();
内容的提问来源于stack exchange,提问作者Géry Ogam
相关产品推荐
相关产品推荐

