我们知道借助Access-Control-Allow-Origin响应头字段可以允许跨域 AJAX, 对于非简单请求,CORS 机制跨域会首先进行 preflight(一个 OPTIONS 请求), 该请求成功后才会发送真正的请求。 这一设计旨在确保服务器对 CORS 标准知情,以保护不支持 CORS 的旧服务器。

简单请求

简单请求具体是指请求方法是简单方法且请求头是简单头的 HTTP 请求。具体地,

简单方法包括GET, HEAD, POST

简单头包括:Accept, Accept-LanguageContent-Language,以及值为application/x-www-form-urlencoded, multipart/form-data, text/plain 其中之一的 Content-Type 头。

对于非简单请求浏览器会首先发送 OPTIONS 请求(成为 preflight), 例如添加一个自定义头部x-foo的 HTTP 请求:

var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.setRequestHeader('x-foo', 'bar');
xhr.send();

服务器需要成功响应(2xx)并在Access-Control-Alow-Headers中包含x-foo (因为它不是简单头部):

OPTIONS /origin-redirect-with-preflight 200
Access-Control-Allow-Headers: x-foo
Access-Control-Allow-Origin: http://index.com:4001
Connection:keep-alive
Content-Length: 0
Access-Control-Request-Headers

Access-Control-Request-Headerspreflight 请求中用来标识真正请求将会包含哪些头部字段, preflight 请求本身不会发送这些头字段。 例如上述请求中Access-Control-Request-Headers字段的值应该是x-foo。 服务器应当在对应的Access-Control-Allow-Headers响应头中包含这些字段。 否则即使返回 200 preflight 也会失败:

XMLHttpRequest cannot load http://mid.com:4001/access-control-allow-origin-wildcard.

Request header field x-foo is not allowed by Access-Control-Allow-Headers in preflight response.

关于 DNT 请求头

有些浏览器(如 Safari 隐身模式)会在请求中添加DNT头, 但浏览器不会(也不应)因此而发起 preflight。 因为这一请求头是浏览器添加的,也应当对此知情。 所以响应头中也不需要包含Access-Control-Allow-Headers, 参照 W3C Recommendation,满足以下条件即可跳过 preflight:

For request method there either is a method cache match or it is a simple method and the force preflight flag is unset. For every header of author request headers there either is a header cache match for the field name or it is a simple header.

注意只要所有Author Header是简单头即可跳过,这里的DNT虽然不是简单头但它属于 User-Agent Header。 注意在 CORS 被重定向之后这一状况会变得复杂,在重定向 CORS 跨域请求一文有较详细的讨论。

CORS 跨域中的 preflight 请求的更多相关文章

  1. CORS跨域带来的preflight request

    CORS跨域带来的preflight request https://blog.csdn.net/baidu_35407267/article/details/79043515 HTTPS://blo ...

  2. CORS跨域限制以及预请求验证

    之前我们可以通过“Access-Control-Allow-Origin”,实现跨域请求,那是不是所有跨域请求都可以通过设置Access-Control-Allow-Origin实现跨域请求呢?显然不 ...

  3. ajax跨域通过 Cors跨域资源共享 进行GetPost请求

    using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Ne ...

  4. JSONP跨域和CORS跨域

    什么是跨域? 跨域:指的是浏览器不能执行其它网站的脚本,它是由浏览器的同源策略造成的,是浏览器的安全限制! 同源策略 同源策略:域名.协议.端口均相同. 浏览器执行JavaScript脚本时,会检查这 ...

  5. CORS跨域请求规则以及在Spring中的实现

    CORS: 通常情况下浏览器禁止AJAX从外部获取资源,因此就衍生了CORS这一标准体系,来实现跨域请求. CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origi ...

  6. CORS——跨域请求那些事儿

    在日常的项目开发时会不可避免的需要进行跨域操作,而在实际进行跨域请求时,经常会遇到类似 No 'Access-Control-Allow-Origin' header is present on th ...

  7. CORS跨域请求

    一.问题: 服务器端代码 from flask import Flask from flask import make_response from flask import jsonify app = ...

  8. [转] 重定向 CORS 跨域请求

    非简单请求不可重定向,包括第一个preflight请求和第二个真正的请求都不行. 简单请求可以重定向任意多次,但如需兼容多数浏览器,只可进行一次重定向. 中间服务器应当同样配置相关 CORS 响应头. ...

  9. CORS跨域请求总结

    CORS跨域请求分为简单请求和复杂请求. 1. 简单请求: 满足一下两个条件的请求. (1) 请求方法是以下三种方法之一: HEAD GET POST (2)HTTP的头信息不超出以下几种字段: Ac ...

随机推荐

  1. 吴裕雄--天生自然 python语言数据分析:开普勒系外行星搜索结果分析

    import pandas as pd pd.DataFrame({'Yes': [50, 21], 'No': [131, 2]}) pd.DataFrame({'Bob': ['I liked i ...

  2. js中判断为false的情况

     document.write((new Boolean())+"<br />");        document.write((new Boolean(" ...

  3. Python---9高级特性

    一.切片 取一个list或tuple的部分元素是非常常见的操作.比如,一个list如下: >>> L = ['Michael', 'Sarah', 'Tracy', 'Bob', ' ...

  4. 编程语言十万个为什么之java web的基础概念

    1.什么是JAVA Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由SunMicrosystems公司于1995年5月推出的Java程序设计语言和Java平台(即JavaSE, Ja ...

  5. 详解 Filter 过滤器

    1.简介 Filter也称之为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 ...

  6. Jmeter连接mysql成功

    1 下载,mysql-connector-odbc-5.3.4-winx64.msi 进行安装  <转载> 2 安装后, copy "C:\ProgramFiles (x86)\ ...

  7. PyGame学习笔记之壹

    新建窗口 代码 '''PyGame学习笔记之壹''' import pygame # 引入 PyGame 库 pygame.init() # PyGame 库初始化 screen = pygame.d ...

  8. SpringCloud - 全家桶

    先导篇:SpringCloud介绍篇 第一篇:注册中心Eureka 第二篇:服务提供与Rest+Ribbon调用 第三篇:服务提供与Feign调用 第四篇:熔断器Hystrix(断路器) 第五篇:熔断 ...

  9. 【Amaple教程】6. 路由配置

    在 第1节<启动路由> 章节中为了能让单页应用顺利跑起来,我们提前介绍了简单的路由配置方法.我们已了解路由配置的目的是指定不同的url下对应的 模块节点(也叫做模块容器)内应该显示哪个模块 ...

  10. UIButton左边图片右边文字的做法

    UIImage *yuyinImage = [UIImage imageNamed:@"yuyin.png"]; [soundButton setImage:yuyinImage ...