使用CORS与OpenShift上的节点应用程序一起使用POST的空请求正文

时间:2015-05-19 03:21:19

标签: node.js post express cors openshift

我正在使用express在OpenShift上创建一个简单的Node应用程序(我只是修改了OpenShift的默认示例Node应用程序)。我希望得到CORS的支持:

var cors = require('cors');
...

/**
 *  Initialize the server (express) and create the routes and register
 *  the handlers.
 */
self.initializeServer = function() {
    self.createRoutes();
    self.app = express();

    self.app.use(cors());
    self.app.use(express.json());

    //  Add handlers for the app (from the routes).
    for (var r in self.routes) {
        self.app.get(r, self.routes[r]);
    }

    self.app.post('/vote/', function (req, res) {
        // just echo back the request body
        res.json(req.body);
    });
};

如果我从本地机器发送请求,使用curl它可以正常工作:

C:\Users\Chin\Desktop>curl -H "Content-Type: application/json" -X POST -d "{\"username\":\"xyz\"}" https://bloodbrothers-chinhodado.rhcloud.com/vote/
{"username":"xyz"}

但是,如果我使用jQuery从另一个具有不同域的站点发送请求,则返回的正文为空:

$.ajax({
    url: "https://bloodbrothers-chinhodado.rhcloud.com/vote/",
    type: "POST",
    crossDomain: true,
    data: JSON.stringify({"username": "xyz"}),
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function (response) {
        alert(response);
    },
    error: function (xhr, status) {
        alert("error");
    }
});

=>服务器返回{}

我在console.log()函数中放了一个self.app.post()调用,实际上当请求来自跨域时,请求的主体是空的。

我在这里做错了什么?该应用程序是现场的,所以你可以尝试自己卷曲和ajax调用。

编辑:在这种情况下,如果我发出了CORS请求,它会进入self.app.post('/vote/', function (req, res) {}函数(通过在console.log()调用验证)。这是否意味着CORS运行良好而问题不在于CORS?

1 个答案:

答案 0 :(得分:3)

我明白了。事实证明,像我一样启用CORS不起作用,因为content-type是JSON,这使得该请求成为“复杂”请求。来自docs

  

一个简单的跨站点请求是:

     
      
  • 仅使用GET,HEAD或POST。如果使用POST将数据发送到服务器,则使用HTTP POST请求发送到服务器的数据的Content-Type是application / x-www-form-urlencoded,multipart / form-data或text / plain之一

  •   
  • 不使用HTTP请求设置自定义标头(例如X-Modified等)

  •   

来自npm cors package doc

  

启用CORS Pre-Flight

     

某些CORS请求被视为“复杂”,需要初始OPTIONS请求(称为“飞行前请求”)。 “复杂”CORS请求的示例是使用除GET / HEAD / POST之外的HTTP动词(例如DELETE)或使用自定义标头的请求。要启用预先飞行,您必须为要支持的路由添加新的OPTIONS处理程序:

var express = require('express')
  , cors = require('cors')
  , app = express();

app.options('/products/:id', cors()); // enable pre-flight request for DELETE request 
app.del('/products/:id', cors(), function(req, res, next){
  res.json({msg: 'This is CORS-enabled for all origins!'});
});

所以我做了改动,现在工作得很好。