javascript CORS 在 php slim 框架中不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31618734/
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
CORS not working in php slim framework
提问by Neel Kamal
I have created rest api using php slim framework. Here is my code
我已经使用 php slim 框架创建了 rest api。这是我的代码
<?php
require 'Slim/Slim.php';
require '../lib/cors_enable.php';
require '../lib/logger.php';
require '../../db_config/config.php';
require '../lib/predis-0.8/lib/Predis/Autoloader.php';
Predis\Autoloader::register();
require '../lib/RedisMethods.php';
require '../lib/APICaller.php';
require '../lib/FosterGemOAuth.php';
require '../lib/FosterGemUser.php';
require '../lib/NewsFeed.php';
require '../lib/FosterGemBookmarks.php';
require '../lib/TopicWebsite.php';
require '../lib/FetchFullArticle.php';
require '../lib/PushNotification.php';
\Slim\Slim::registerAutoloader();
$app = new \Slim\Slim();
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
// return only the headers and not the content
// only allow CORS if we're doing a GET - i.e. no saving for now.
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) {
if($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] == 'GET' || $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] == 'POST') {
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: X-Requested-With, X-authentication,Content-Type, X-client');
}
}
exit;
}
$app->post('/messagebhej(/)(:profile_id/?)(:app_auth_token/?)', 'messagebhej');
$app->post('/login','login');
$app->run();
function messagebhej($profile_id, $app_auth_token){
$error='';
$request = file_get_contents('php://input');
try {
$request_data = json_decode($request,true);
if($app_auth_token == APP_AUTH_TOKEN){
$obj = new PushNotification();
$res = $obj->sendMessage($profile_id, $request_data);
} else {
$error='Access Denied';
}
} catch (Exception $ex) {
$error=$ex->getMessage();
log_error($error,"index.php | sendMessage function");
}
if($error) {
$return_data= '{"Status":"Failed","Message":"'.$error.'"}';
} else {
$return_data='{"Status":"Success"}';
}
echo $return_data;
}
function login() {
$error='';
$request = file_get_contents('php://input');
try {
$request_data = json_decode($request,true);
if(isset($request_data['EmailAddress']) && isset($request_data['Password'])){
if($request_data['EmailAddress']){
$obj = new FosterGemUser();
$user_data = $obj->get_user($request_data['EmailAddress'],$request_data['Password'],$request);
} else {
$error='Please enter your email address.';
}
} else {
$error='Wrong Data Format.';
}
} catch (Exception $ex) {
$error=$ex->getMessage();
log_error($error,"index.php | login function");
}
if($error) {
$return_data= '{"Status":"Error","Message":"'.$error.'"}';
} else {
$return_data=$user_data;
}
echo $return_data;
}
Now both the api works fine when I call it using Rest client. However when I call login api from javascript it works well but messagebhej api gives error
现在,当我使用 Rest 客户端调用它时,这两个 api 都可以正常工作。但是,当我从 javascript 调用 login api 时,它运行良好但 messagebhej api 出现错误
XMLHttpRequest cannot load http://api.fostergem.com/messagebhej/556714b04ec0a40d3cda0118/{app_auth_token}. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63343' is therefore not allowed access. The response had HTTP status code 404.
I am getting crazy. Everything is is same then how the cors is enabled for one api and not for other.
我快疯了。一切都是相同的,然后是如何为一个 API 启用 cors 而不是为其他 API 启用 cors。
Here is my cors_enable.php
这是我的 cors_enable.php
<?php
// Specify domains from which requests are allowed
header('Access-Control-Allow-Origin: *');
// Specify which request methods are allowed
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
// Additional headers which may be sent along with the CORS request
// The X-Requested-With header allows jQuery requests to go through
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
// Set the age to 1 day to improve speed/caching.
header('Access-Control-Max-Age: 86400');
?>
回答by Ammadu
There is no point of wrapping up header statements enabling CORS in your API with those conditions you have.
使用您拥有的条件在 API 中启用 CORS 的头语句是没有意义的。
Right now it would set headers only if the REQUEST_METHOD is OPTIONS and HTTP_ACCESS_CONTROL_REQUEST_METHOD is either GET or POST, but your request wont comply to this.
现在它只会在 REQUEST_METHOD 是 OPTIONS 并且 HTTP_ACCESS_CONTROL_REQUEST_METHOD 是 GET 或 POST 时设置标头,但您的请求不会遵守这一点。
So replace
所以更换
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
// return only the headers and not the content
// only allow CORS if we're doing a GET - i.e. no saving for now.
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) {
if($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] == 'GET' || $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] == 'POST') {
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: X-Requested-With, X-authentication,Content-Type, X-client');
}
}
exit;
}
from your code with
从你的代码中
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
PS:Unless you have a server variable set as HTTP_ACCESS_CONTROL_REQUEST_METHOD, change it to REQUEST_METHOD
PS:除非您将服务器变量设置为 HTTP_ACCESS_CONTROL_REQUEST_METHOD,否则将其更改为 REQUEST_METHOD
回答by Velu S Gautam
For Slim Framework 2.4 Version I did a small hack to tackle the Preflight OPTIONS request
对于 Slim Framework 2.4 版本,我做了一个小技巧来解决 Preflight OPTIONS 请求
\Slim\Slim::registerAutoloader();
$app = new \Slim\Slim();
if($app->request->isOptions()) {
return true;
break;
}
$app->post('/authenticate', 'authenticateUser');
$app->run();
So this will track all OPTIONS requests and return true and it worked for me.
所以这将跟踪所有 OPTIONS 请求并返回 true 并且它对我有用。
My .htaccess file was like as follows
我的 .htaccess 文件如下
Header add Access-Control-Allow-Origin "*"
Header add Access-Control-Allow-Headers "X-Requested-With, Content-Type, Accept, Origin, Authorization"
Header add Access-Control-Allow-Methods "GET, POST, OPTIONS"
Hope this helps.
希望这可以帮助。
回答by tHymans3
I was having the same issue while working on an ionic hybrid mobile application. I added the following code below to my index.php file.
我在开发离子混合移动应用程序时遇到了同样的问题。我将以下代码添加到我的 index.php 文件中。
header('Access-Control-Allow-Origin:*');
header('Access-Control-Allow-Headers:X-Request-With');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
回答by Gudgip
I ended up creating this simple middleware class:
我最终创建了这个简单的中间件类:
<?php
class CorsMiddleware
{
private $router;
public function __construct(\Slim\Router $router)
{
$this->router = $router;
}
/**
* Cors middleware invokable class
*
* @param \Psr\Http\Message\ServerRequestInterface $request PSR7 request
* @param \Psr\Http\Message\ResponseInterface $response PSR7 response
* @param callable $next Next middleware
*
* @return \Psr\Http\Message\ResponseInterface
*/
public function __invoke($request, $response, $next)
{
// https://www.html5rocks.com/static/images/cors_server_flowchart.png
if ($request->isOptions()
&& $request->hasHeader('Origin')
&& $request->hasHeader('Access-Control-Request-Method')) {
return $response
->withHeader('Access-Control-Allow-Origin', '*')
->withHeader('Access-Control-Allow-Headers', '*')
->withHeader("Access-Control-Allow-Methods", '*');
} else {
$response = $response
->withHeader('Access-Control-Allow-Origin', '*')
->withHeader('Access-Control-Expose-Headers', '*');
return $next($request, $response);
}
}
}
I use it like this (it's a string because of dependency-injection):
我像这样使用它(由于依赖注入,它是一个字符串):
$app->add('CorsMiddleware');
回答by ficuscr
$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']
looks wrong. That a valid _SERVER variable? You mean just REQUEST_METHOD
?
$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']
看起来不对。那是一个有效的 _SERVER 变量吗?你是说只是REQUEST_METHOD
?
Is the ORIGIN header in fact actually sent? Trust the error message.
ORIGIN 标头实际上是否实际发送?相信错误消息。
Can you use something like WireShark or at least step through your code somehow? Even echo/log calls to make sure your logic is working as expected.
你可以使用像 WireShark 这样的东西,或者至少以某种方式单步执行你的代码吗?甚至 echo/log 调用以确保您的逻辑按预期工作。
回答by jap1968
I had the same problem, but at the end I achieved to get it working
我遇到了同样的问题,但最后我实现了让它工作
I am using cors-middleware https://github.com/tuupola/cors-middleware
我正在使用 cors-middleware https://github.com/tuupola/cors-middleware
These are my settings:
这些是我的设置:
$app->add(new \Tuupola\Middleware\Cors([
"origin" => ["*"],
"methods" => ["GET", "POST", "PUT", "PATCH", "DELETE"],
"headers.allow" => ["Accept", "Content-Type"],
"headers.expose" => [],
"credentials" => false,
"cache" => 0,
"logger" => $container['logger']
]));
Pay attention to the headers.allow
key. If you try using "*"
it will fail. You must enumerate at least these two headers as allowed.
注意headers.allow
关键。如果您尝试使用"*"
它将失败。您必须至少枚举这两个标头作为允许。
回答by Ashwyn Horton
Follow the instructions on the lazy CORS in the following link...this worked for me...
按照以下链接中有关懒惰 CORS 的说明进行操作...这对我有用...
to be exact I made a cors.php file to serperate the routes you handle for cores and pasted all the code in the file.
确切地说,我制作了一个 cors.php 文件来处理您为内核处理的路由,并将所有代码粘贴到文件中。
http://www.slimframework.com/docs/v3/cookbook/enable-cors.html
http://www.slimframework.com/docs/v3/cookbook/enable-cors.html
UPDATE
更新
Since I faced this problem from my internal server where I had two web servers running for my back-end API and the other on Angular CLI the solution is in that context.
由于我在内部服务器上遇到了这个问题,其中我有两个 Web 服务器为我的后端 API 运行,另一个在 Angular CLI 上运行,因此解决方案就是在这种情况下。
CORS operates by checking if the request url is valid by sending a preflight request using OPTIONS method, the problem is that your restful API router is not configured to handle that request so it gives a NOT_FOUND response. So what you do is add the routing for all OPTIONS requests as a simple solution, though you can be more specific.
CORS 通过使用 OPTIONS 方法发送预检请求来检查请求 url 是否有效,问题是您的 Restful API 路由器未配置为处理该请求,因此它给出了 NOT_FOUND 响应。因此,您要做的是为所有 OPTIONS 请求添加路由作为一个简单的解决方案,尽管您可以更具体。
To be nice and tidey, create a cors.php file where you will put the routes for your cors routes and add this code in it
为了美观大方,创建一个 cors.php 文件,您将在其中放置 cors 路由的路由并在其中添加此代码
<?php
// Handling CORS with a simple lazy CORS
$app->options('/{routes:.+}', function ($request, $response, $args) {
return $response;
});
$app->add(function ($req, $res, $next) {
$response = $next($req, $res);
return $response
->withHeader('Access-Control-Allow-Origin', 'http://localhost:4200')
->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization')
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
});
// Catch-all route to serve a 404 Not Found page if none of the routes match
// NOTE: make sure this route is defined last
$app->map(['GET', 'POST', 'PUT', 'DELETE', 'PATCH'], '/{routes:.+}', function($req, $res) {
// handle using the default Slim
$handler = $this->notFoundHandler;
//page not found handler
return $handler($req, $res);
});
Basically what this is saying is, for all options requests on all routes, just return a response without handling it. What's important here is the middleware which executes after returning the response, it sets the response headers that will tell your browser that it's OK to send the real request.
基本上这就是说,对于所有路由上的所有选项请求,只返回一个响应而不处理它。这里重要的是在返回响应后执行的中间件,它设置响应标头,告诉您的浏览器可以发送真正的请求。
Note: Make sure that the cors.php file falls as the last set of routes. Also don't put an asterix as your domain origin, it doesn't work either.
注意:确保 cors.php 文件属于最后一组路由。也不要将星号作为您的域来源,它也不起作用。