AngularJS POST失败:针对预检的响应具有无效的HTTP状态码404
我知道有很多这样的问题,但是我没有看到任何问题已经解决了我的问题。 我已经使用了至less3个微框架。 他们都做了一个简单的POST失败,应该返回数据:
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'); }); } });
SlimPHP服务器:
<?php require 'vendor/autoload.php'; $app = new \Slim\Slim(); $app->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();
我已经启用CORS,GET请求工作。 html更新与服务器发送的JSON内容。 但是我得到了一个
XMLHttpRequest无法加载http:// localhost:8080 / server.php / post 。 预检的响应具有无效的HTTP状态码404
每次我尝试使用POST。 为什么?
编辑:要求由Pointy req / res
好吧,这是我如何解决这个问题。 这一切都与CORS政策有关。 在POST请求之前,Chrome正在执行预检OPTIONS请求,在请求之前应由服务器处理并确认。 现在这真的不是我想要的这样一个简单的服务器。 因此,重新设置头客户端防止预检:
app.config(function ($httpProvider) { $httpProvider.defaults.headers.common = {}; $httpProvider.defaults.headers.post = {}; $httpProvider.defaults.headers.put = {}; $httpProvider.defaults.headers.patch = {}; });
浏览器现在将直接发送一个POST。 希望这有助于很多人在那里…我真正的问题是不够了解CORS。
链接到一个很好的解释: http : //www.html5rocks.com/en/tutorials/cors/
荣誉这个答案给我的方式。
您已启用CORS并在服务器中启用了Access-Control-Allow-Origin : *
。如果仍然使用GET
方法并且POST
方法不起作用,则可能是因为Content-Type
和data
问题。
首先AngularJS使用Content-Type: application/json
传输数据,这些数据本身并不是由某些Web服务器(特别是PHP)序列化的。 对于他们,我们必须传输数据为Content-Type: x-www-form-urlencoded
例如: –
$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)); }); };
注意:我使用$.params
序列化数据以使用Content-Type: x-www-form-urlencoded
。 或者,您可以使用以下JavaScriptfunction
function params(obj){ var str = ""; for (var key in obj) { if (str != "") { str += "&"; } str += key + "=" + encodeURIComponent(obj[key]); } return str; }
并使用params({ 'username': $scope.username, 'Password': $scope.Password })
将其序列化为Content-Type: x-www-form-urlencoded
请求仅获取username=john&Password=12345
的POST数据username=john&Password=12345
表格。
对于一个Node.js应用程序,在注册所有我自己的路由之前,在server.js文件中,我把下面的代码。 它为所有响应设置标题。 如果它是一个飞行前的“OPTIONS”呼叫,它也会优雅地结束响应,并且立即将飞行前响应发送回客户端,而不需要通过实际的业务逻辑路由来进行“nexting”(这个单词?)。 这是我的server.js文件。 突出显示了有关使用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);