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请求,包含了上传的文件内容。

因此在服务器端进行处理的时候,需要判断这两次请求,不要错过了真正的上传内容。