node js server safari客户端连接失败

时间:2015-09-09 19:25:36

标签: javascript node.js safari cors

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

适用于带浏览器的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");

为了完成网络模拟,我正在运行(已安装npm)http-server(端口8080),客户端是index.html中的链接。

模拟很简单;在客户端上键入文本框中的内容,单击“发送”,然后您将获得

响应显示在opResult div中。除了野生动物园之外,它确实如此。

调试代码显示safari发送空白消息... CORS问题?!?

Safari专家请指教。

1 个答案:

答案 0 :(得分:1)

(摘要在底部)

问题

  

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

这是您当前的模型:客户端将静态数据和app / data作为两个不同的origins(wiki)访问:

(current model: client receives content from two origins)

http-server:8080 ─┐            ┌─> node:1001
                  └─> client <─┘

选项#1:反向代理

更受欢迎的设计是&#34;反向代理&#34; (nginxapache),其中http服务器提供静态数据充当节点应用的接口。这样,您的两种内容类型都来自相同的源和端口,但仍然可以看到性能提升:

(reverse-proxy model: everything comes from localhost:8080)

node:1001 <─────> apache or nginx:8080 <──┐
                                          └─> client

...但你不是使用nginx或apache 。别担心。有一个NPM包就可以使用你已经使用here的堆栈。有关示例,请参阅我的pastebin

此模型的另一个优势是可以将您的http服务器的所有可配置性提供给您的节点应用程序,为您提供高级安全性和优化选项,例如请求缓存。

  

... localhost!= 127.0.0.1并且无法处理IO到不同的端口...

这是正式的CORS违规行为,但并非始终如此。查看MDN's same origin policy documentation。这个最新的策略必然可以缓解有问题的跨站点脚本攻击。

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

话虽如此, 是一种官方认可的方式,可以跨越来源制作ajax请求,但是&#34;其他&#34;域必须知道并接受您的流量。有两种实现方法:

  • 通过在节点应用程序中的响应中添加Access-Control-Allow-Origin: *标头,可以允许简单的GET和POST请求。
  • 使用application/x-www-form-urlencodedmultipart/form-datatext/plain以外的内容类型的POST请求需要preflight request

要点:

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

  1. 通过实现反向代理,您的静态和动态内容都来自同一个地方(在您的情况下,localhost:8080)
  2. 通过在节点中的回复中添加Access-Control-Allow-Origin: *标头,或者在极少数情况下,预检请求。