从 ExtJS 向 node.js 请求时出现 CORS 问题。请求或响应标头不正确?

Posted

技术标签:

【中文标题】从 ExtJS 向 node.js 请求时出现 CORS 问题。请求或响应标头不正确?【英文标题】:CORS Issue When Requesting from ExtJS to node.js. Request or Response Header Incorrect? 【发布时间】:2015-07-06 06:01:11 【问题描述】:

我在向我们网络中两个不同域之间的 Nodejs 服务器发出 ExtJS AJAX 请求时遇到问题,希望能提供任何帮助。当尝试从 ExtJS 客户端的 http 和 https 时响应失败,但是来自我的本地通过 http 的 Curl 返回正确数据的 200 OK。我们正在处理内容类型application/json

ExtJS onReady 函数已启用 CORS:

Ext.onReady(function () 
   Ext.Ajax.cors = true;
   Ext.Ajax.useDefaultXhrHeader = false;
   ... (code removed) 
)

我的 ExtJS 客户端在一个已知的工作 URL 上进行测试,该 URL 将正确创建 ExtJS 数据存储(返回 200 OK):

Ext.create('Ext.data.Store', 
    id         : 'countryStore',
    model      : 'country',
    autoLoad   : true,
    autoDestroy: true,
    proxy: 
        type: 'rest',
        url : 'https://restcountries.eu/rest/v1/all',
        ,
        reader: 
            type           : 'json',
            headers: 'Accept': 'application/json',
            totalProperty  : 'total',
            successProperty: 'success',
            messageProperty: 'message'
        
);

但是,当尝试通过

向我们的 Nodejs 服务器发出请求时

http:

Ext.create('Ext.data.Store', 
    id         : 'circuits',
    model      : 'circuit',
    autoLoad   : true,
    autoDestroy: true,
    proxy: 
        type: 'rest',
        url : 'http://ourNodeJsServerDomain:5500/v3/circuits',
        ,
        reader: 
            type           : 'json',
            headers: 'Accept': 'application/json',
            totalProperty  : 'total',
            successProperty: 'success',
            messageProperty: 'message'
        
);

在 Chrome 的控制台中返回以下内容:

Mixed Content: The page at 'https://ourExtJsDevClientSide' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://ourNodeJsServerDomain:5500/v3/circuits?_dc=1430149427032&page=1&start=0&limit=50'. This request has been blocked; the content must be served over HTTPS.

现在,当尝试超过 https:

火狐显示:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://ourNodeJsServerDomain:5500/v3/circuits?_dc=1430151516741&page=1&start=0&limit=50. This can be fixed by moving the resource to the same domain or enabling CORS.

并且请求标头没有显示“application/json”,这是一个问题吗?:

Accept  
text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding 
gzip, deflate
Accept-Language 
en-US,en;q=0.5
Host    
ourNodeJsServerDomain:5500
Origin  
https://ourExtJsDevClientSide
Referer 
https://ourExtJsDevClientSide
User-Agent  
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:37.0) Gecko/20100101 Firefox/37.0

然后我尝试使用 Curl 来查看有助于调试的响应

http 给出 200 OK 响应,但即使我们将其定义为 "*",Access-Control-Allow-Origin 也未定义:

curl http://ourNodeJsServerDomain:5500/v3circuits?_limit=1 -v
> GET /v3/circuits?_limit=1 HTTP/1.1
> User-Agent: curl/7.37.1
> Host: ourNodeJsServerDomain:5500
> Accept: */*
> 
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Access-Control-Allow-Origin: undefined
< Access-Control-Allow-Methods: GET
< Access-Control-Allow-Headers: Content-Type
< Content-Type: application/json; charset=utf-8
< Content-Length: 1126
< ETag: W/"MlbRIlFPCV6w7+PmPoVYiA=="
< Date: Mon, 27 Apr 2015 16:24:18 GMT
< Connection: keep-alive
< 
[
   *good json data returned here*  ]

然后当我尝试通过httpsCurl 时

curl https://ourNodeJsServerDomain:5500/v3/circuits?_limit=1 -v
* Server aborted the SSL handshake
* Closing connection 0
curl: (35) Server aborted the SSL handshake

我们已经在我们的 Nodejs 服务器上启用了 CORS:

router
    .all('*', function(req, res, next)
        res.setHeader('Content-Type', 'application/json');
        // res.setHeader("Access-Control-Allow-Origin", req.headers.origin);
        // console.log('\n\nreq.headers.origin ===================== ' + req.headers.origin);
        //I have tried allowing all * via res.SetHeader and res.header and neither is defining the Access-Control-Allow-Origin properly when curling
        //res.setHeader("Access-Control-Allow-Origin", "*");
        res.header("Access-Control-Allow-Origin", "*");
        // res.header("Access-Control-Allow-Headers", "X-Requested-With");
        res.header('Access-Control-Allow-Methods', 'GET');
        res.header('Access-Control-Allow-Headers', 'Content-Type');

我试图详细说明我的思考过程,我愿意尝试新的方法来确定如何理解和解决这个问题。

* 解决方案 *

问题是来自浏览器的混合内容。我们的客户端 UI 在 https(安全)上,而我们从 nodejs 服务器请求 http(不安全)内容。我们需要允许我们的 nodejs 服务器在 https 上运行

我们generated SSL certifications 并将它们实现到我们的 nodejs 服务器上。

在 nodejs 代码中,我们使用 CORS 模块启用了 CORS,并同时运行 http 和 https 服务器:

// enable CORS for all requests
var cors = require('cors');
app.use(cors());

// for certifications
var credentials = 
  key: fs.readFileSync('our.key'),
  cert: fs.readFileSync('our.crt')
;

var httpServer = http.createServer(app);
var httpsServer = https.createServer(credentials, app);

httpServer.listen(port, function() 
console.log('HTTP server listening on port ' + port);
);

httpsServer.listen(httpsPort, function() 
    console.log('HTTPS server listening on port ' + httpsPort);
);

【问题讨论】:

你看过这个***.com/questions/27682785/… @AbdulRehmanYawarKhan 我有 Ext.Ajax.useDefaultXhrHeader = false;在 Ext.onReady 函数中。上面的示例代码的第一块。谢谢。 取得了任何进展?我认为您应该首先尝试确保在节点中正确配置所有内容。 我的同事测试了从 Advanced Rest Client(Chrome 扩展)对 nodejs 的调用,由于某种原因,他通过 http 接收 Access-Control-Allow-Origin: * 而我正在接收 Access-Control-Allow -来源:未定义。还是很神秘的。无论如何,从我们的 ExtJs UI 来看,这两种方式都不起作用。 @Richard - 尝试在请求标头中添加 Accept : application/json? 【参考方案1】:

您的服务器中的 CORS 和 HTTPS 似乎都存在问题...您应该尝试 this middleware 作为 CORS 部分,并在首先以原始 HTTP 访问页面时使其工作。据我所知,对于 HTTP 和 HTTPS,您必须 use different ports。您可能还需要启用CORS credentials。正如我所说,我认为你最好先让它在 HTTP 中工作;)

然后,在 Ext 部分,正如 cmets 中已经提到的,您可能应该禁用默认标头(或者您必须让所有这些标头都被您的服务器接受;请参阅this answer 的第一条评论)。但您需要在代理上执行此操作,因为apparently it replaces the global setting 在Ext.Ajax 中。

所以,是这样的:

Ext.create('Ext.data.Store', 
    id         : 'countryStore',
    model      : 'country',
    autoLoad   : true,
    autoDestroy: true,
    proxy: 
        type: 'rest',
        url : 'https://restcountries.eu/rest/v1/all',
        useDefaultXhrHeader: false, // <= HERE
        reader: 
            type           : 'json',
            headers: 'Accept': 'application/json',
            totalProperty  : 'total',
            successProperty: 'success',
            messageProperty: 'message'
        
     // <= and notice this change
);

可能不相关,但请注意您的缩进不正确,并隐藏了 reader 选项应用于商店本身而不是代理的事实(因此被忽略)。

【讨论】:

感谢您提供帮助。我做了一些小改动并实现了 CORS 模块,“未定义”现在返回“*”。您是否知道一种允许“混合”内容的方法,因为我们当前的页面是 https 而我们更希望我们的 nodejs 服务器通过 http 运行? 另外,我注意到我们用于测试的国家休息电话 restcountries.eu/rest/v1/all 是通过 https 服务的。您知道他们是如何在我们客户端没有任何类型的身份验证或密钥的情况下做到这一点的吗? 你指引我朝着正确的方向前进。这只是 http 与 https 的问题。我会更新解决方案。

以上是关于从 ExtJS 向 node.js 请求时出现 CORS 问题。请求或响应标头不正确?的主要内容,如果未能解决你的问题,请参考以下文章

尝试发布到 Limesurvey RC API 时出现 Node.js 错误,ECONNREFUSED

使用 db.query 方法 node.js 时出现 Heroku H12“请求超时”错误

从 React 向 Django 发送 post 请求时出现 400(错误请求)

从子域向域发送 POST 请求时出现错误 419

从 Angular 向 Asp.net 发送 post 请求时出现错误 405

部署 Node.js 应用程序时出现 Heroku 错误