Errore POST di AngularJS: la risposta per il preflight ha un codice di stato HTTP 404 non valido

So che ci sono un sacco di domande come questa, ma nessuna di quelle che ho visto ha risolto il problema. Ho già utilizzato almeno 3 microframeworks. Tutti loro non riescono a fare un semplice POST, che dovrebbe restituire i dati:

Il client angularJS:

var app = angular.module('client', []); app.config(function ($httpProvider) { //uncommenting the following line makes GET requests fail as well //$httpProvider.defaults.headers.common['Access-Control-Allow-Headers'] = '*'; delete $httpProvider.defaults.headers.common['X-Requested-With']; }); app.controller('MainCtrl', function($scope, $http) { var baseUrl = 'http://localhost:8080/server.php' $scope.response = 'Response goes here'; $scope.sendRequest = function() { $http({ method: 'GET', url: baseUrl + '/get' }).then(function successCallback(response) { $scope.response = response.data.response; }, function errorCallback(response) { }); }; $scope.sendPost = function() { $http.post(baseUrl + '/post', {post: 'data from client', withCredentials: true }) .success(function(data, status, headers, config) { console.log(status); }) .error(function(data, status, headers, config) { console.log('FAILED'); }); } }); 

Il server SlimPHP:

 response()->headers->set('Access-Control-Allow-Headers', 'Content-Type'); $app->response()->headers->set('Content-Type', 'application/json'); $app->response()->headers->set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); $app->response()->headers->set('Access-Control-Allow-Origin', '*'); $array = ["response" => "Hello World!"]; $app->get('/get', function() use($array) { $app = \Slim\Slim::getInstance(); $app->response->setStatus(200); echo json_encode($array); }); $app->post('/post', function() { $app = \Slim\Slim::getInstance(); $allPostVars = $app->request->post(); $dataFromClient = $allPostVars['post']; $app->response->setStatus(200); echo json_encode($dataFromClient); }); $app->run(); 

Ho abilitato CORS e le richieste GET funzionano. L’html si aggiorna con il contenuto JSON inviato dal server. Comunque ottengo a

XMLHttpRequest non può caricare http: // localhost: 8080 / server.php / post . La risposta per il preflight ha un codice di stato HTTP 404 non valido

Ogni volta che provo a usare POST. Perché?

EDIT: il req / res come richiesto da Pointy intestazioni req / res

Ok, ecco come ho capito. Tutto ha a che fare con la politica CORS. Prima della richiesta POST, Chrome eseguiva una richiesta OPZIONI di preflight, che doveva essere gestita e riconosciuta dal server prima della richiesta effettiva. Ora questo non è proprio quello che volevo per un server così semplice. Quindi, la reimpostazione del lato client delle intestazioni impedisce la verifica preliminare:

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

Il browser invierà ora un POST direttamente. Spero che questo aiuti molte persone là fuori … Il mio vero problema non era capire il CORS abbastanza.

Link a una grande spiegazione: http://www.html5rocks.com/en/tutorials/cors/

Complimenti a questa risposta per avermi mostrato la via.

Hai abilitato CORS e triggersto Access-Control-Allow-Origin : * nel server. Se il metodo GET funzionare e il metodo POST non funziona, potrebbe essere a causa del problema del Content-Type di Content-Type e del problema dei data .

First AngularJS trasmette i dati utilizzando Content-Type: application/json che non è serializzato in modo nativo da alcuni server Web (in particolare PHP). Per loro dobbiamo trasmettere i dati come Content-Type: x-www-form-urlencoded

Esempio :-

  $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)); }); }; 

Nota: sto usando $.params per serializzare i dati per utilizzare Content-Type: x-www-form-urlencoded . In alternativa puoi usare la seguente funzione javascript

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

e usa params({ 'username': $scope.username, 'Password': $scope.Password }) per serializzarlo come Content-Type: x-www-form-urlencoded ricevono solo i dati POST in username=john&Password=12345 modulo.

Per un’app Node.js, nel file server.js prima di registrare tutti i miei percorsi, inserisco il codice seguente. Imposta le intestazioni per tutte le risposte. Termina anche la risposta con garbo se si tratta di una chiamata “OPTIONS” pre-volo e invia immediatamente la risposta pre-volo al client senza “nexting” (si tratta di una parola?) Attraverso le attuali rotte logiche di business. Ecco il mio file server.js. Sezioni rilevanti evidenziate per uso StackOverflow.

 // server.js // ================== // BASE SETUP // import the packages we need var 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 POST app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); // Logger app.use(morgan('dev')); // ------------------------------------------------------------- // STACKOVERFLOW -- PAY ATTENTION TO THIS NEXT SECTION !!!!! // ------------------------------------------------------------- //Set CORS header and intercept "OPTIONS" preflight call from AngularJS var 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 API var 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 SERVER var port = process.env.PORT || 8080; // set our port app.listen(port); console.log('API Active on port ' + port);