Сообщение AngularJS завершается неудачно: Ответ на предполетный запрос содержит недопустимый код состояния HTTP 404


Я знаю, что есть много подобных вопросов, но ни один из них, которые я видел, не исправил мою проблему. Я уже использовал по крайней мере 3 микрокадра. Все они терпят неудачу при выполнении простого сообщения, которое должно возвращать данные обратно:

Клиент 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, и запросы работают. html обновляется с помощью содержимого JSON, отправленного сервером. Однако я получаю

Не удается загрузить XMLHttpRequest http://localhost:8080/server.php/post . Ответ для предполетной подготовки содержит недопустимый код состояния HTTP 404

Каждый раз, когда я пытаюсь использовать POST. Почему?

ИЗМЕНИТЬ: Запрос/разрешение в соответствии с просьбой Pointy req/res headers

Author: Deegriz, 2015-11-12

3 answers

Хорошо, итак, вот как я это понял. Все это связано с политикой CORS. Перед запросом POST Chrome выполнял предварительный запрос ПАРАМЕТРОВ, который должен быть обработан и подтвержден сервером до фактического запроса. Теперь это действительно не то, что я хотел для такого простого сервера. Следовательно, сброс заголовков на стороне клиента предотвращает предварительный запуск:

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

Теперь браузер будет отправлять СООБЩЕНИЕ напрямую. Надеюсь, это поможет многим людям там... Моей настоящей проблемой было не понимания КОРСА достаточно.

Ссылка на отличное объяснение: http://www.html5rocks.com/en/tutorials/cors/

Слава этому ответу за то, что он показал мне путь.

 84
Author: Deegriz, 2017-05-23 11:55:07

Вы включили CORS и включили Access-Control-Allow-Origin : * на сервере.Если вы все еще получаете GET работающий метод и POST метод не работает, то это может быть связано с проблемой Content-Type и data.

Сначала 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.

 8
Author: jafarbtech, 2017-06-03 11:37:14

Для 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);
 3
Author: hoekma, 2017-05-25 22:37:22