javascript Backbone & Slim PHP - Access-Control-Allow-Headers - 可以获取信息,不能发布?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13293157/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 18:20:07  来源:igfitidea点击:

Backbone & Slim PHP - Access-Control-Allow-Headers - Can GET information, can't POST it?

javascriptbackbone.jsheadercross-domainslim

提问by Danny

I'm using Backbone and the Slim PHP framework. I'm trying to post information to my API, however Access-Control-Allow-Headers keeps causing me problems...

我正在使用 Backbone 和 Slim PHP 框架。我正在尝试将信息发布到我的 API,但是 Access-Control-Allow-Headers 不断给我带来问题......

My console reads:

我的控制台显示:

    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.

My headers read:

我的标题是:

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

My headers in my slim index.php file are:

我纤薄的 index.php 文件中的标题是:

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

To handle the post data:

处理帖子数据:

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

In my javascript (i'm using the backbone framework) my code is:

在我的 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);
  }
});

Any help would be much appreciated, I've been stuck on this for ages!

任何帮助将不胜感激,我多年来一直坚持这个!

回答by Joe

I had a similar cross domain POSTproblem (in fact with all headers except GET). The following resolved it:

我有一个类似的跨域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;
}

回答by mayconbordin

In your javascript client you're making an OPTIONS request to /user/auth, but in your PHP code you're only accepting POST requests through this endpoint.

在您的 javascript 客户端中,您正在向/user/auth发出 OPTIONS 请求,但在您的 PHP 代码中,您仅通过此端点接受 POST 请求。

If you want your API to accept OPTIONS method you should have something like this in your code:

如果你想让你的 API 接受 OPTIONS 方法,你应该在你的代码中有这样的东西:

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

Or, if you want to handle multiple HTTP methods in the same function:

或者,如果您想在同一个函数中处理多个 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');

Keep in mind that the OPTIONS method, according to W3C:

请记住,根据 W3C的 OPTIONS 方法:

[...] represents a request for information about the communication options available on the request/response chain identified by the Request-URI. This method allows the client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action or initiating a resource retrieval.

[...] 表示请求有关由 Request-URI 标识的请求/响应链上可用的通信选项的信息。此方法允许客户端确定与资源相关联的选项和/或要求,或服务器的能力,而无需暗示资源操作或启动资源检索。

Alternatively, just change your client's code to make a POST request instead of OPTIONS request. It's easier and makes more sense than authenticating a user through the OPTIONS method. In zepto.js it would be something like this:

或者,只需更改客户端的代码以发出 POST 请求而不是 OPTIONS 请求。这比通过 OPTIONS 方法对用户进行身份验证更容易也更有意义。在 zepto.js 中,它会是这样的:

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

回答by julesbou

Your OPTIONS request should be a 200 returning an empty response. Then the browser will send the real POST request.

您的 OPTIONS 请求应该是 200 返回一个空响应。然后浏览器将发送真正的 POST 请求。

Also no need to add OPTIONS in Access-Control-Allow-Methodsheader.

也无需在Access-Control-Allow-Methods标题中添加 OPTIONS 。

It seems your using authentication, why not add Access-Control-Allow-Credentialsheader too.

看来您正在使用身份验证,为什么不也添加Access-Control-Allow-Credentials标头。

For more informations check this codeit may be helpful.

有关更多信息,请查看此代码,它可能会有所帮助。

回答by Iyke Perry

CorsSlim helped me. https://github.com/palanik/CorsSlim

CorsSlim 帮助了我。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);