节点js服务器safari客户端连接失败

我有一个简单的html-js <-ajax-> nodejs服务器循环作为我的应用程序核心的testing基础。

它适用于带有浏览器的Windows 8:IE11,Chrome45,firefox40,opera31 ..并在Safari 5.1.7上失败

这是客户端代码

<html> <head> <meta charset="UTF-8"> <script language="javascript"> var url="http://127.0.0.1:1001"; function sendData(rawData) { var strout=""; var data=encodeURIComponent(rawData); var xhr = new XMLHttpRequest(); xhr.open('POST', url, true); xhr.onreadystatechange=function(){ if (xhr.readyState==4 && xhr.status==200){ strout=decodeURIComponent(xhr.responseText); document.getElementById("opResult").innerHTML="srv-sent "+strout } } xhr.send(data); alert("sent = "+rawData) } //+++++++++++++++++++ function send(){ var v=document.getElementById("ta").value; sendData(v); } </script> </head> <body> <input type="button" value="send" onclick="send()"> <br> <textarea id="ta" cols=40 rows=10> </textarea> <br> <div id="opResult"></div> </body> </html> 

这里是服务器代码:

 var http = require('http'); http.createServer(function(request, response){ var postData="",cmdQ=[],resout=[]; if (request.method == 'POST') { request.on('data', function (data) { postData += data; }); } console.log("SRV got data:"+postData); request.on('end', function () { console.log("got post: "+decodeURIComponent(postData)); resout="SRVRep: got "+decodeURIComponent(postData); response.writeHead(200, { 'Content-Type': 'text/html', 'Access-Control-Allow-Origin' : '*', 'Access-Control-Allow-Headers':'Origin, X-Requested-With, Content-Type, Accept' }); response.end(encodeURIComponent(resout), "utf-8"); console.log("sent "+resout); post_data=""; }); }).listen(1001,'127.0.0.1'); console.log("server initialized to port 1001"); 

为了使networking仿真完成,我正在运行(npm安装)http-server(端口8080),客户端是index.html中的链接。

模拟很简单; 在客户端键入文本框中的东西,点击发送,你应该得到的

响应显示在opResult股利。 而且,除了safari之外,它确实如此。

debugging代码显示safari发送空白消息… CORS问题?!?

Safari专家请指教。

(总结在底部)

问题

我需要一个提供应用程序的静态文件服务器(http-server:8080),以及一个应用程序文件/数据存储服务器:1001。

这是您当前的模型:客户端访问静态数据和应用程序/数据作为两个不同的来源 (wiki):

 (current model: client receives content from two origins) http-server:8080 ─┐ ┌─> node:1001 └─> client <─┘ 

选项#1:反向代理

更受欢迎的devise是“反向代理”( nginx , apache ),其中http-server提供静态数据, 作为节点应用程序的接口。 这样,您的两种内容types都来自相同的来源和端口,但仍看到性能提升:

 (reverse-proxy model: everything comes from localhost:8080) node:1001 <─────> apache or nginx:8080 <──┐ └─> client 

…但是你没有使用nginx或apache 。 别担心。 有一个NPM软件包可以在这里使用你已经使用的堆栈。 看我的pastebin的例子。

这个模型有一个额外的优点,即为你的节点应用程序提供所有的http服务器的可configuration性,为你提供高级的安全性和优化选项,比如请求caching。

… localhost!= 127.0.0.1,不能处理IO到不同的端口…

这是正式的CORS违规,但并不总是这样。 查看MDN的相同的来源政策文件 。 这个相当近期的策略必然会缓解有问​​题的跨站脚本攻击。

选项2:跨源共享标准( w3 )

这就是说,有一个官方认可的方式来跨域请求Ajax请求,但“其他”域必须知道和接受你的stream量。 有两种方法来实现这一点:

  • 通过在您的节点应用程序中添加Access-Control-Allow-Origin: *标头到您的响应,可以允许简单的GET和POST请求。
  • 具有除application/x-www-form-urlencodedmultipart/form-datatext/plain之外的内容types的POST请求需要预检请求 。

概要:

您可以通过以下两种方式避免违反浏览器的同源策略:

  1. 通过实现一个反向代理,所以你的静态和dynamic内容来自同一个地方(在你的情况下,本地主机:8080)
  2. 通过在节点中添加Access-Control-Allow-Origin: *标题到您的响应中,或者在极less数情况下,对请求进行预检。