以前笔者也写过关于跨域的文章(链接在文末放出),但从未停止过对【跨域】的探索。近日又偶然得到了关于跨域的一些见解和知识,觉得将其总结一下。
众所周知,对于【跨域】,最简单、最便捷的方法莫过于CORS——这是一种后端设置跨域的方式。
为了支持cors,设置Access-Control-Allow-Origin
头为*
,如下所示:
const http=require('http');
var server=http.createServer(function(req,res){
res.setHeader('Access-Control-Allow-Origin','*');
res.writeHead(200);
res.end('Hello cors-mxc');
});
server.listen(8081);
前面,我还说过关于Ajax的四种常用请求方式:post、get、put、delete
现在有一个问题:用put请求来标记一次更新,而不是用get或post进行跨域ajax请求。怎么办?浏览器貌似不喜欢这种动作。。。
要知道:要使用get、post、head之外的一个方法,必须对你的请求进行【预绘】——它的修改也是服务器端的。
具体来说,我们要设置Access-Control-Allow-Methods
头部,以反映出你所需支持的http动词:
res.setHeader('Access-Control-Allow-Methods','GET,PUT,POST,DELETE,OPTIONS');
我们顺便发现了“options”:这是我们感兴趣的动词之一。
当使用一个put做出ajax请求,XMLHTTPRequest对象首先会发送options请求,以搞清楚服务器上是否支持put请求。在服务器上,代码通过返回一个204状态码来响应options请求。然后,浏览器发送put请求处理数据。
前面我们还说了通过ajax发送二进制数据并加载到图像中
要想通过ajax,以二进制数据的形式获取一个服务器端的图像。只需将responseType
设置为blob
,然后当数据返回的时候操作它。
如下,我们转换了数据并且将其加载到一个img元素中:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>CORS blob</title>
</head>
<body>
<img id="result" />
<script>
var request=new XMLHttpRequest();
request.open('GET','mxcdwx.png',true);
request.responseType="blob";
var img=document.getElementById("result");
request.onload=function(event){
var blob=request.response;
img.src=URL.createObjectURL(blob);
};
request.send();
</script>
</body>
</html>
CORS的另一优点就是,它支持Ajax请求中的二进制数据(也被称为类型数组),一个二进制请求的关键要求是,将reponseType设置为如下值之一:
arraybuffer——固定长度的原始二进制数据缓存
blob——类似文件的不可变原始数据
在上述代码中,笔者使用URL.createObjectURL()
方法把blob转换为一个DOMString(通常映射为JavaScript字符串),带有传递的对象的URL,该URL赋值给img元素的src属性——一旦图像加载了,代码调用URL.revokeObjectURL()
(自带API)来释放URL。
哦今天的重点是这个:跨域共享http-cookies
这个必须在客户端和服务器端都做出修改,才能支持可信任的请求。
在客户端,必须在XMLHttpRequest
对象上设置withCredentials
属性:
var request=new XMLHttpRequest();
request.onreadystatechange=function(){
if(this.readyState===4){
console.log(this.status);
if(this.status===200){
document.getElementById("result").innerHTML=this.responseText;
}
}
};
request.open('GET','http://burningbird.net:8081/');
request.withCredentials=true;
request.send(null);
而在服务端,必需将Access-Control-Allow-Credentials
头部设置为true
:
const http=require('http');
var server=http.createServer(function(req,res){
res.setHeader('Content-type','text/plain');
res.setHeader('Access-Control-Allow-Origin','http://somedomain.com');
res.setHeader('Access-Control-Allow-Credentials',true);
var cookies=new Cookies(req,res);
cookies.set('apple',"red");
res.writeHead(200);
res.end('Hello cors-mxc');
});
server.listen(8081);
能够跨域发送http-cookie或认证,这就是另一项cors扩展了。
这里为什么Access-Control-Allow-Origin
要设置为确定值?
因为通配符*可能会被某些浏览器阻拦,从而使发送失败!
笔者相关博文: