问题
I'm creating a simple Node app on OpenShift, using express (I'm just modifying the default example Node app of OpenShift). I want to have CORS support with it:
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);
    });
};
If I send a request from my local machine, using curl it works fine:
C:\Users\Chin\Desktop>curl -H "Content-Type: application/json" -X POST -d "{\"username\":\"xyz\"}" https://bloodbrothers-chinhodado.rhcloud.com/vote/
{"username":"xyz"}
However, if I send the request from another site with a different domain using jQuery, the returned body is empty:
$.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");
    }
});
=> the server returns {}
I put a console.log() call inside the self.app.post() function and indeed when the request is coming from cross-domain, the body of the request is empty.
What did I do wrong here? The app is live so you can try the curl and ajax call yourself if you want to.
EDIT: In this case, if I make a CORS request, it does go into the self.app.post('/vote/', function (req, res) {} function (verified by putting in console.log() calls there). Does it mean that CORS is working well and the problem is not because of CORS?
回答1:
I figured it out. It turns out that enabling CORS like I did didn't work since the content-type is JSON, which makes this request a "complex" request. From the docs:
A simple cross-site request is one that:
Only uses GET, HEAD or POST. If POST is used to send data to the server, the Content-Type of the data sent to the server with the HTTP POST request is one of application/x-www-form-urlencoded, multipart/form-data, or text/plain.
Does not set custom headers with the HTTP Request (such as X-Modified, etc.)
and from the npm cors package doc:
Enabling CORS Pre-Flight
Certain CORS requests are considered 'complex' and require an initial OPTIONS request (called the "pre-flight request"). An example of a 'complex' CORS request is one that uses an HTTP verb other than GET/HEAD/POST (such as DELETE) or that uses custom headers. To enable pre-flighting, you must add a new OPTIONS handler for the route you want to support:
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!'});
});
So I made the changes and it's working well now.
来源:https://stackoverflow.com/questions/30316180/empty-request-body-with-post-using-cors-with-a-node-app-on-openshift