JavaScript中XMLHttpRequest实现跨域访问
JavaScript的跨域访问方法有很多,不下十种。本文总结的是XMLHttpRequest的跨域访问。
在JavaScript中,我们可以用XMLHttpRequest访问服务端应用。但是浏览器对这类访问有一个限制,就是JavaScript所在页面与所访问的服务端应用必须属于同一个域内,也就是同一个IP和端口号内。这就是JavaScript同源策略(Access-Control-Allow-Origin),这样的限制有益于保证服务的安全性,使得本方服务不会被其他网络应用所盗用。
然而这也会给自己带来一些不便,因为即便是同一个网络应用,也有可能在不同的服务器上呀。那么我想,作为网络服务的设计者,如此严格的定义会使得网络开发变得非常丑陋。所以设计者还是留下一个活口,就是在服务器端应用定义时,允许部分网段访问,这就是跨域访问。
下面以上传文件为例子解释XMLHttpRequest的跨域访问。
如何实现跨域访问?
XMLHttpRequest的使用总是大同小异,直接上代码。
1 var form = new FormData(); 2 form.append("upload", fileObj); 3 4 var http = new XMLHttpRequest(); 5 if (http != null) { 6 http.onstatechange = stateHandler; 7 http.open("POST", "host:port/url"); 8 http.send(form); 9 } 10 11 stateHandler : function() { 12 if (this.readyState==4) { 13 if (this.status == 200) { 14 console.log("fileObj uploaded successfully!"); 15 } else { 16 console.log("Origin null is not allowed by Access-Control-Allow-Origin"); 17 } 18 } else { 19 console.log("XMLHttpRequest is not ready"); 20 } 21 }
最关键的处理在服务器部分,其实无论是否跨域,服务器都是可以获取上述请求的。问题的关键在于服务器的回应是否能够返回到浏览器。
所以在服务器发送回应的时候,需要添加一个文件头。
response.setHeader("Access-Control-Allow-Origin","http://js.host");
这个文件头的第一个参数是允许跨域,第二个参数是接受跨域的服务,上述文件头说明了服务器信任来自http://js.host的请求。
这样也就实现了XMLHttpRequest的跨域访问。
Tricks
在这里,其实与不同的XMLHttpRequest还有一个小小的不同,却很重要。同域内的XMLHttpRequest访问通常只有一次请求,而跨域的XMLHttpRequest有两次。
第一次XMLHttpRequest请求,其method是OPTIONS,并非前文定义的POST。这并不是由JS代码控制的,而是浏览器来完成的操作。其作用是判断该请求是否能够被服务器所响应。
第二次XMLHttpRequest请求才是真正的POST请求,包含了上传的文件内容。
因此在服务器端进行处理的时候,需要判断这两次请求,不要错过了真正的上传内容。