Backbone & Slim PHP — Access-Control-Allow-Headers — Может ПОЛУЧИТЬ информацию, не может ПОСТАВИТЬ?

Я использую Backbone и фреймворк Slim PHP. Я пытаюсь опубликовать информацию в своем API, однако Access-Control-Allow-Headers продолжает вызывать у меня проблемы...

В моей консоли написано:

    OPTIONS http://api.barholla.com/user/auth 405 (Method Not Allowed) zepto.min.js:2
XMLHttpRequest cannot load http://api.barholla.com/user/auth. Request header field Content-Type is not allowed by Access-Control-Allow-Headers.

Мои заголовки гласят:

Request URL:http://api.barholla.com/user/auth
Request Method:OPTIONS
Status Code:405 Method Not Allowed
Request Headersview source
Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:origin, content-type, accept
Access-Control-Request-Method:POST
Connection:keep-alive
Host:api.barholla.com
Origin:http://localhost
Referer:http://localhost/barholla/app/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4
Response Headersview source
Access-Control-Allow-Origin:*
Allow:POST
Connection:close
Content-Type:application/json
Date:Thu, 08 Nov 2012 16:12:32 GMT
Server:Apache
Transfer-Encoding:chunked
X-Powered-By:Slim
X-Powered-By:PleskLin

Мои заголовки в моем тонком файле index.php:

$res = $app->response();
$res->header('Access-Control-Allow-Origin', '*');
$res->header("Access-Control-Allow-Methods: PUT, GET, POST, DELETE, OPTIONS");

Чтобы обработать данные поста:

$app->post('/user/auth', function () use ($app) {
//code here
});

В моем javascript (я использую основу) мой код:

 App.userAuth = new App.UserAuthModel({
  username: $('#username').val(),
  password: hex_md5($('#password').val())
});

App.userAuth.save({}, {
  success: function(model, resp) {
    console.log(resp);
  },
  error: function(model, response) {
    console.log(response);
  }
});

Любая помощь будет высоко оценена, я застрял на этом целую вечность!


person Danny    schedule 08.11.2012    source источник


Ответы (4)


У меня была аналогичная междоменная проблема POST (фактически со всеми заголовками, кроме GET). Следующее решило это:

if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']) && (   
       $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] == 'POST' || 
       $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] == 'DELETE' || 
       $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] == 'PUT' )) {
             header('Access-Control-Allow-Origin: *');
             header("Access-Control-Allow-Credentials: true"); 
             header('Access-Control-Allow-Headers: X-Requested-With');
             header('Access-Control-Allow-Headers: Content-Type');
             header('Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT'); // http://stackoverflow.com/a/7605119/578667
             header('Access-Control-Max-Age: 86400'); 
      }
  exit;
}
person Joe    schedule 23.11.2012
comment
идеальное решение - person mhndev; 17.08.2018

В вашем javascript-клиенте вы делаете запрос OPTIONS к /user/auth, но в вашем PHP-коде вы принимаете POST-запросы только через эту конечную точку.

Если вы хотите, чтобы ваш API принимал метод OPTIONS, в вашем коде должно быть что-то вроде этого:

$app->options('/user/auth', function () use ($app) {
    //code here
});

Или, если вы хотите обрабатывать несколько методов HTTP в одной функции:

$app->map('/user/auth', function () use ($app) {
    if ($app->request()->isOptions()) {
        //handle options method
    }

    else if ($app->request()->isPost()) {
        //handle post method
    }
})->via('POST', 'OPTIONS');

Имейте в виду, что метод OPTIONS, согласно W3C:

[...] представляет собой запрос информации о вариантах связи, доступных в цепочке запросов/ответов, идентифицированной Request-URI. Этот метод позволяет клиенту определить параметры и/или требования, связанные с ресурсом, или возможности сервера, не подразумевая действие ресурса или инициируя поиск ресурса.

В качестве альтернативы просто измените код вашего клиента, чтобы сделать запрос POST вместо запроса OPTIONS. Это проще и имеет больше смысла, чем аутентификация пользователя с помощью метода OPTIONS. В zepto.js это будет примерно так:

$.post('/user/auth', { foo: 'bar' }, function(response){ 
    console.log(response);
});
person mayconbordin    schedule 23.11.2012

Ваш запрос OPTIONS должен быть 200, возвращающим пустой ответ. Затем браузер отправит настоящий POST-запрос.

Также не нужно добавлять OPTIONS в заголовок Access-Control-Allow-Methods.

Похоже, вы используете аутентификацию, почему бы не добавить Access-Control- Также заголовок Allow-Credentials.

Для получения дополнительной информации проверьте этот код, он может оказаться полезным.

person julesbou    schedule 09.11.2012

Корслим мне помог. https://github.com/palanik/CorsSlim

<?php 
$app = new \Slim\Slim();
$corsOptions = array("origin" => "*",
"exposeHeaders" => array("Content-Type", "X-Requested-With", "X-authentication", "X-client"),
"allowMethods" => array('GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'));
$cors = new \CorsSlim\CorsSlim($corsOptions);
$app->add($cors);
person Iyke Perry    schedule 24.05.2016