http触发预检请求条件

浏览器会在以下情况下自动发送预检请求(Preflight Request)

简单请求 vs 复杂请求

简单请求(不触发预检)

必须同时满足以下所有条件

1. HTTP 方法限制

只能是以下三种方法之一:

  • GET
  • HEAD
  • POST
2. 请求头限制

只能包含以下安全头部

  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type(但有值的限制)
  • Range(简单范围请求)
3. Content-Type 限制

如果使用 POST 且包含 Content-Type,只能是:

  • text/plain
  • multipart/form-data
  • application/x-www-form-urlencoded
4. 其他限制
  • 不能有自定义请求头
  • 不能使用 XMLHttpRequestUpload 对象注册事件监听器
  • 不能使用 ReadableStream 对象

触发预检请求的条件(复杂请求)

满足以下任意一个条件就会触发预检:

1. HTTP 方法

javascript 复制代码
// 这些方法会触发预检
fetch(url, { method: 'PUT' });
fetch(url, { method: 'DELETE' });
fetch(url, { method: 'PATCH' });
fetch(url, { method: 'CONNECT' });

2. 自定义请求头

javascript 复制代码
// 任何自定义头部都会触发预检
fetch(url, {
  headers: {
    'X-Custom-Header': 'value',        // 自定义头部
    'Authorization': 'Bearer token',   // 认证头部
    'X-Requested-With': 'XMLHttpRequest'
  }
});

3. Content-Type 不在简单值范围内

javascript 复制代码
// 这些 Content-Type 会触发预检
fetch(url, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'    // ❌ 触发预检
  }
});

fetch(url, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/xml'     // ❌ 触发预检
  }
});

fetch(url, {
  method: 'POST',
  headers: {
    'Content-Type': 'text/html'          // ❌ 触发预检
  }
});

4. 使用凭据

javascript 复制代码
// 设置凭据会触发预检
fetch(url, {
  credentials: 'include'  // 包含 cookies
});

实际示例对比

✅ 简单请求(不触发预检)

javascript 复制代码
// GET 请求
fetch('http://127.0.0.1:3333/list');

// 简单 POST
fetch('http://127.0.0.1:3333/list', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  body: 'name=john&age=30'
});

// 纯文本 POST
fetch('http://127.0.0.1:3333/list', {
  method: 'POST',
  headers: {
    'Content-Type': 'text/plain'
  },
  body: 'hello world'
});

❌ 复杂请求(触发预检)

javascript 复制代码
// JSON 数据
fetch('http://127.0.0.1:3333/list', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'  // 触发预检
  },
  body: JSON.stringify({name: 'john'})
});

// 自定义头部
fetch('http://127.0.0.1:3333/list', {
  headers: {
    'Authorization': 'Bearer token'     // 触发预检
  }
});

// PUT 方法
fetch('http://127.0.0.1:3333/list', {
  method: 'PUT',                        // 触发预检
  body: 'data'
});

预检请求的内容

当触发预检时,浏览器会发送:

http 复制代码
OPTIONS /list HTTP/1.1
Host: 127.0.0.1:3333
Origin: http://127.0.0.1:5500
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type

服务器需要响应:

http 复制代码
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://127.0.0.1:5500
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400

避免预检的技巧

如果想避免预检请求:

  1. 使用 GET/HEAD/POST 方法
  2. 避免自定义头部
  3. POST 时使用 application/x-www-form-urlencodedtext/plain
  4. 不使用认证相关头部

但在现代 Web 开发中,JSON API 很常见,所以预检请求是不可避免的,正确配置 CORS 才是解决方案。

相关推荐
火山上的企鹅1 小时前
Codex实战:APP远程升级服务搭建(三)后台管理页面(APK 上传、版本管理、多应用页签)
服务器·网络·数据库·oracle·qgc
caimouse2 小时前
Reactos 第 9 章 设备驱动 — 9.5 一组PnP设备驱动模块的实例
网络·windows
袁小皮皮不皮2 小时前
3.HCIP OSPF补充知识(优化版)
服务器·网络·数据库·网络协议·智能路由器
志栋智能3 小时前
超自动化巡检:知识沉淀与团队协作的新载体
大数据·运维·网络·数据库·人工智能·自动化
酣大智3 小时前
策略路由PBR--企业双出口实验
网络·智能路由器·策略路由·pbr
袁小皮皮不皮3 小时前
1.HCIP BFD 学习笔记(优化版)
服务器·网络·笔记·网络协议·学习·智能路由器·ip
梁辰兴4 小时前
计算机网络基础:数据加密模型
网络·计算机网络·计算机·数据加密·计算机网络基础·梁辰兴·数据加密模型
fofantasy4 小时前
NSK LH12AN 微型导轨技术手册
运维·网络·数据库·经验分享·规格说明书
网络系统管理4 小时前
第八届江苏技能状元大赛“信息通信网络运行管理”项目技术文件
网络
福建佰胜张工4 小时前
3HNA006643-001 BRACKET ZB/CCIB:ABB 喷涂机器人关键结构件深度解析
网络·机器人