AngularJS POST Fails: Response for preflight has invalid HTTP status code 404 AngularJS POST Fails: Response for preflight has invalid HTTP status code 404 ajax ajax

AngularJS POST Fails: Response for preflight has invalid HTTP status code 404


EDIT:

It's been years, but I feel obliged to comment on this further. Now I actually am a developer. Requests to your back-end are usually authenticated with a token which your frameworks will pick up and handle; and this is what was missing. I'm actually not sure how this solution worked at all.

ORIGINAL:

Ok so here's how I figured this out.It all has to do with CORS policy. Before the POST request, Chrome was doing a preflight OPTIONS request, which should be handled and acknowledged by the server prior to the actual request. Now this is really not what I wanted for such a simple server. Hence, resetting the headers client side prevents the preflight:

app.config(function ($httpProvider) {  $httpProvider.defaults.headers.common = {};  $httpProvider.defaults.headers.post = {};  $httpProvider.defaults.headers.put = {};  $httpProvider.defaults.headers.patch = {};});

The browser will now send a POST directly. Hope this helps a lot of folks out there... My real problem was not understanding CORS enough.

Link to a great explanation: http://www.html5rocks.com/en/tutorials/cors/

Kudos to this answer for showing me the way.


You have enabled CORS and enabled Access-Control-Allow-Origin : * in the server.If still you get GET method working and POST method is not working then it might be because of the problem of Content-Type and data problem.

First AngularJS transmits data using Content-Type: application/json which is not serialized natively by some of the web servers (notably PHP). For them we have to transmit the data as Content-Type: x-www-form-urlencoded

Example :-

        $scope.formLoginPost = function () {            $http({                url: url,                method: "POST",                data: $.param({ 'username': $scope.username, 'Password': $scope.Password }),                headers: { 'Content-Type': 'application/x-www-form-urlencoded' }            }).then(function (response) {                // success                console.log('success');                console.log("then : " + JSON.stringify(response));            }, function (response) { // optional                // failed                console.log('failed');                console.log(JSON.stringify(response));            });        };

Note : I am using $.params to serialize the data to use Content-Type: x-www-form-urlencoded. Alternatively you can use the following javascript function

function params(obj){    var str = "";    for (var key in obj) {        if (str != "") {            str += "&";        }        str += key + "=" + encodeURIComponent(obj[key]);    }    return str;}

and use params({ 'username': $scope.username, 'Password': $scope.Password }) to serialize it as the Content-Type: x-www-form-urlencoded requests only gets the POST data in username=john&Password=12345 form.


For a Node.js app, in the server.js file before registering all of my own routes, I put the code below. It sets the headers for all responses. It also ends the response gracefully if it is a pre-flight "OPTIONS" call and immediately sends the pre-flight response back to the client without "nexting" (is that a word?) down through the actual business logic routes. Here is my server.js file. Relevant sections highlighted for Stackoverflow use.

// server.js// ==================// BASE SETUP// import the packages we needvar express    = require('express');var app        = express();var bodyParser = require('body-parser');var morgan     = require('morgan');var jwt        = require('jsonwebtoken'); // used to create, sign, and verify tokens// ====================================================// configure app to use bodyParser()// this will let us get the data from a POSTapp.use(bodyParser.urlencoded({ extended: true }));app.use(bodyParser.json());// Loggerapp.use(morgan('dev'));// -------------------------------------------------------------// STACKOVERFLOW -- PAY ATTENTION TO THIS NEXT SECTION !!!!!// -------------------------------------------------------------//Set CORS header and intercept "OPTIONS" preflight call from AngularJSvar allowCrossDomain = function(req, res, next) {    res.header('Access-Control-Allow-Origin', '*');    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');    res.header('Access-Control-Allow-Headers', 'Content-Type');    if (req.method === "OPTIONS")         res.send(200);    else         next();}// -------------------------------------------------------------// STACKOVERFLOW -- END OF THIS SECTION, ONE MORE SECTION BELOW// -------------------------------------------------------------// =================================================// ROUTES FOR OUR APIvar route1 = require("./routes/route1");var route2 = require("./routes/route2");var error404 = require("./routes/error404");// ======================================================// REGISTER OUR ROUTES with app// -------------------------------------------------------------// STACKOVERFLOW -- PAY ATTENTION TO THIS NEXT SECTION !!!!!// -------------------------------------------------------------app.use(allowCrossDomain);// -------------------------------------------------------------//  STACKOVERFLOW -- OK THAT IS THE LAST THING.// -------------------------------------------------------------app.use("/api/v1/route1/", route1);app.use("/api/v1/route2/", route2);app.use('/', error404);// =================// START THE SERVERvar port = process.env.PORT || 8080;        // set our portapp.listen(port);console.log('API Active on port ' + port);