关于http请求的一些理解:
CORS是一个w3c标准,全称为Cross-origin resoursce sharing(跨域资源共享),它允许浏览器向不用源的服务器发起XMLHttpRequest请求,从而可以略过ajax同源策略的限制。
简单请求:
只要满足请求方法是HEAD、GET、POST;HTTP头信息不超出以下字段Accept Accept-Language Content-Language Last-Event-ID Content-Type: application/x-www-form-urlencode multipart-data text/plain 就属于简单请求。
对于简单请求,基本就是在请求中自动在头信息中添加一个origin字段,例如Origin: http://localhost:8000,这表示同意locahost:8000的请求。如果origin指定的源不在许可范围内,服务器会返回一个正常的HTTP回应,如果浏览器没有发现Resonse Headers响应头信息没有包含Access-Control-Allow-Origin就会抛出错误,但这种错误无法通过status code来识别,因为返回的状态码可能是200.
如果你使用的域名是origin允许的,Response Headers里会多出几个基本头信息字段:
Access-Control-Allow-Credential: true,
Access-Control-Allow-Headers:origin, content-type, accept, x-request-with,
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS,
Access-Control-Allow-Origin: http:localhost:8000
Access-Control-Allow-Credential: 表示是否允许发送cookies。默认情况下,Cookies不包括在CORS请求中;设为true表示cookies可以包含在请求中一起发给服务器,如果不需要发送cookies给服务器,需删除字段。需要注意的是:除了设置Access-Control-Allow-Credential:true外,在ajax请求中也必须打开withCredentials,方法如下:
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
否则就算服务器同意发送或设置cookie,浏览器也不会发送或处理。如果不想发送cookie,最保险的方法就是:
xhr.withCredentials = false;
Access-Control-origin: 必填项,要么是origin指定的被允许的值,要么是*,表示接受任意域名的请求。
非简单请求:
非简单请求是那种对服务器有特殊要求的请求,比如PUT DELETE,或者Content-Type:application/json等。非简单请求会在正式通信前增加一次HTTP查询请求,成为flight(预检)。浏览器先询问服务器,当前请求域是否在服务器许可名单中,以及可以使用哪些HTTP动词头信息字段,如果返回true浏览器会发出XMLHTTPRequest请求否则会报错。下面是一个例子:
var url = 'http://localhost:8000';
var xhr = new XMLHttpRequest();
xhr.open('DELETE', url, true);
xhr.setRequestHeader('x-request-with', 'value');
xhr.send();
这里,HTTP请求中,方法是DELETE,并发送了一个头信息为x-request-with,浏览器发现,这是一个非简单请求,就会自动预检,要求服务器预检这个HTTP头信息。
预检请求用的方法是OPTIONS,表示这个请求是用来询问的。头信息里面,关键字段是origin,表示来源于哪个源。除了origin,预检还包括Method Headers,分别为:
Access-control-request-origin: *,
Access-Control-Request-Method: DELETE,
Access-Control-request-Headers: x-request-with,
浏览器收到flight预检以后检查了origin Access-Control-Request-Method 和 Access-Control-Request-Headers字段后确认允许跨域请求,就可以作出回应。如果flight预检没有通过,也会返回一个正常的HTTP回应。但如果没有任何CORS相关的Response Headers,flight预检就不会通过,控制台会打印出关键信息:
...http://localhost:8000 is not allowed by Access-Allow-Origin
服务器回应的其他CORS相关字段如下。
Access-Control-Allow-credentials: true
Access-Control-Allow-Methods:GET, POST, DELETE,OPTIONS
Access-Control-Allow-Headers:origin, content-type, accept, x-request-with, Authorization
Access-Control-Allow-Max-Age:1728000
Access-Control-Allow-Methods 必要字段 表示服务器支持的所有跨域请求方法,只要浏览器使用的请求方法包含在内即可通过。
Access-Control-Allow-Headers 必要字段 表明服务器支持的所有头信息字段,也是为了避免多次预检请求。
Access-Control-Allow-Max-Age 可选字段 单位是s,用来指定本次预检的有效期,即在给定时间内允许该条缓存回应,不会发出一条预检请求。
如果服务器通过了预检请求,以后浏览器正常的跨域请求就和简单请求一样,会有一个origin有信息段,副武器的回应也都会有一个Access-Control-Allow-Origin 的头信息段,返回请求如下:
Access-Control-Allow-Origin:http:localhost:8000
Content-Type: text/html; charset=utf-8
其中origin信息是必然会出现的。
Cors与JSONP的比较
CORS比JSONP更强大,JSONP只支持GET请求,CORS支持所有类型的HTTP请求,但JSONP对于老浏览器支持较好。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。