问题简介:在我发送post请求之前,浏览器总是会多发送一个option请求,而由于我们的Nginx服务器直接屏蔽了options请求,导致options请求失败,进而导致后面的请求无法发送。
我们都知道请求分为同源请求和跨源请求,而我们常用的AJAX只能用于同源请求,要想跨域,我们可以使用JSONP,CORS, WebSocket来实现。本文主要来带大家简单了解下CORS。
CORS是跨域资源共享(Cross-origin resource sharing)的简称
CORS请求需要浏览器和服务端同时支持。
CORS的请求分为简单请求和非简单请求两类。
简单请求
被称为简单请求的条件:
(1) 请求方法是以下三种方法之一:
HEAD
GET
POST
(2)HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
对于简单请求,浏览器会在其请求头部中增加一个Origin字段,
Orgin: http://example.com:10000
来说明这个请求来自哪个源(即请求来自哪里,协议+域名+端口),当服务器收到这个请求,会查看请求的origin字段,根据源来判断是否允许该跨域请求。
若允许,则会在返回的头部信息中加上:
Access-Control-Allow-Origin: http://example.com:10000
该字段表示该跨域请求被允许。
若不允许,也会正常返回一个HTTP Response,但是Header中不包括此字段。这时浏览器收到后就会知道请求失败(即使HTTP回应的状态码是200)。
非简单请求
不符合简单请求要求的被称为非简单请求。
对于非简单请求,会在真正请求之前先发送一个options请求,称之为预请求,这就是为什么我们在开发的时候明明没有发送过什么options类型的请求却经常看到的原因。预请求的作用是用来询问后面真正的请求是否被许可,预请求很简单,有三个主要的字段:
origin: http://example.com:10000
Access-Control-Request-Method: post
Access-Control-Request-Headers: auth-token
分别表示请求的源,真正请求的方式,真正请求的额外头信息字段(多个用逗号分开),服务器端收到预请求后,会检查这三个字段,确认允许后会在头部返回如下信息:
Access-Control-Allow-Origin: http://example.com:10000
Access-Control-Allow-Methods: get, post, put, delete
Access-Control-Allow-Headers: auth-token
如没有这三个字段,则表示不允许后面真正的请求,则浏览器不会继续发送真正的请求;有则表示允许,被允许后,则会像发送简单请求那样发送真正的请求。
参考链接
同源政策及其避规方法 http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html
CORS详解 http://www.ruanyifeng.com/blog/2016/04/cors.html