Я знаю, что таких вопросов очень много, но ни один из них не видел исправления моей проблемы. Я уже использовал по крайней мере 3 микрокарта. Все они не могут выполнить простой 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. Зачем?
EDIT: req / res по просьбе Pointy
Хорошо, вот так я понял это. Все это связано с политикой КОРС. Перед запросом 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
.
First AngularJS передает данные с использованием Content-Type: application/json
который не сериализуется изначально некоторыми веб-серверами (в частности, 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
. В качестве альтернативы вы можете использовать следующую функцию javascript
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
получает только данные POST в username=john&Password=12345
.
Для приложения Node.js, в файле server.js, прежде чем регистрировать все мои собственные маршруты, я помещаю код ниже. Он устанавливает заголовки для всех ответов. Он также отлично завершает ответ, если он является предполетным вызовом «ОПЦИИ» и сразу же отправляет ответ перед полетом обратно клиенту без «следующего» (это слово?) Вниз по фактическим маршрутам бизнес-логики. Вот мой файл 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);