CORS not working in php slim framework
Solution 1
There is no point of wrapping up header statements enabling CORS in your API with those conditions you have.
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.
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
Solution 2
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.
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');
Solution 3
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
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.
Solution 4
For Slim Framework 2.4 Version I did a small hack to tackle the Preflight OPTIONS request
\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.
My .htaccess file was like as follows
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.
Solution 5
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');
Neel Kamal
Updated on June 04, 2022Comments
-
Neel Kamal almost 2 years
I have created rest api using php slim framework. Here is my code
<?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
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.
Here is my 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'); ?>