javascript - Node js服务器safari客户端连接失败

标签 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,它确实适用于所有内容。

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

Safari 高手请指教。

最佳答案

(总结在底部)

问题

I need a static file server (http-server :8080) serving up the app, and an app file/data storage server :1001.

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

(current model: client receives content from two origins)

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

选项 #1:反向代理

一种更流行的设计是“反向代理”(nginxapache),其中 http 服务器提供静态数据并且充当您的 Node 应用程序的接口(interface).这样,您的两种内容类型都来自相同的来源和端口,但仍然可以看到性能提升:

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

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

...但您没有使用 nginx 或 apache。不用担心。有一个 NPM 包可以对您已经在使用的堆栈执行此操作 here .看我的pastebin举个例子。

此模型的额外优势是为您的 Node 应用程序提供 http 服务器的所有可配置性,为您提供高级安全性和优化选项,例如请求缓存。

...localhost!=127.0.0.1 and can't handle IO to different ports...

这是正式的 CORS 违规,但并非总是如此。查看MDN's same origin policy documentation .这个相当新的政策必然会减轻有问题的跨站点脚本攻击。

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

也就是说,一种官方认可的方式来跨源发出 ajax 请求,但“其他”域必须知道并接受您的流量。有两种方法可以实现这一点:

  • 可以通过将 Access-Control-Allow-Origin: * header 添加到 Node 应用程序中的响应来允许简单的 GET 和 POST 请求。
  • POST 请求的内容类型不是 application/x-www-form-urlencodedmultipart/form-datatext/plain 需要一个 preflight request .

总结:

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

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

关于javascript - Node js服务器safari客户端连接失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32487672/

相关文章:

javascript - AngularJS 识别滑动 Action ?

node.js - npm 不工作 - "read ECONNRESET"

javascript - findOneAndRemove 和 findOneAndUpdate 未按预期工作

javascript - 首次访问 iOS9 上的 Safari 时页面显示为空白但可选择

javascript - 如何在 Safari 提交表单之前执行 JQuery

javascript - 使用 browserify shim 给 npm 模块起别名

javascript - 带有 Highcharts 的计数器

javascript - 使用 Bootstrap 固定标题和部分 anchor

javascript - 来自 Node js的多个系统调用

javascript - Safari 零高度 SVG 路径不触发鼠标事件