Search code examples
node.jsformspostcorspreflight

Cross-domain POST request in Node.JS with preflight?


I have just started with Node.

I am trying to get cross-domain form data from an HTML form to parse in a Node.js server. I have been able to do this with simple POST data, not with POST requests that require preflight.

I am running the Node code on cloud9 app servers. I am also using the Cors module to handle the requests. This module works well with simple requests (test here to see a simple request work), however with requests that require preflight I get this result from the Chrome inspector console.

XMLHttpRequest cannot load https://nms-motaheri-1.c9.io:8080/mail. 
The request was redirected to 'https://c9.io:8080/api/nc/auth?.....SHORTENED', 
which is disallowed for cross-origin requests that require preflight.

Here is my server.js code:

// Define dependencies 
var express = require('express')
  , cors = require('cors')
  , app = express()
  , parse_post = require("parse-post");

// Core module config 
var corsOptions = {
  origin: '*',
  preflightContinue: true  // <- I am assuming this is correct 
};

app.use(cors(corsOptions));

// Respond to option request with HTTP 200
// ?? Why is this not answering my OPTION requests sufficiently ??
app.options('*',function(req,res){
  res.send(200);
});

// Give a hello world response to all GET requests 
app.get('/',function(req,res){
  res.sendFile(__dirname + '/index.html');
});

// Handle all POST requests to /mail
app.post('/mail', parse_post(function(req, res) {
    console.log(req.body);
    res.json({msg: 'This is CORS-enabled for all origins!'});
  })
);

// Listen on default Cloud9 port which is 8080 in this case
app.listen(process.env.PORT, function(){
  console.log('CORS-enabled web server listening on port ' + process.env.PORT);
});

Why is this happening and how can I satisfactorily answer the OPTION request for my POST with pre-flight?

Here is the post request and response in Chrome dev tools:

enter image description here


Solution

  • Turns out that part of the problem was that the cloud9 server was set to private making these requests all redirect.

    After making the server public, the redirections stopped. However, I received an error that the Node.js server did not have any Access-Control-Allow-Origin headers to allow requests from my cross origin domain. I noticed that "simple" with-out preflight requests would go through. So instead of trying to understand why it was not accepting my allow-all-origin-configuration on the Node.js side I decided to serialized the POST data to get rid of the preflight requirement and changed the data type in my angular request to plain text.

    To get rid of preflight, first get rid of any POST header configuration (cache, etc), make sure your request Content-Type is plain text and make sure your actual content is plain text too. So if it is in JSON serialize it in jQuery before sending it with POST.

    This is what my new Angular Post request code looked like:

    sendEmail: function(email) {
        var config = {
            headers: { 
                'Content-Type': 'text/plain'
            }
        };
        var POSTDATA= JSON.stringify(POSTDATAJSON);
        return $http.post(POSTURL, POSTDATA, config)
    }
    

    And in Node.js this, I am using the cors Node.js module:

    app.post('/mail', parse_post(function(req, res) {
        var postReq = JSON.parse(Object.keys(req.body)); 
    }));