Doug Doug - 1 month ago 11
Javascript Question

Unable to get CORS working with a Slim API

I am really struggling to get CORS working with Slim and AngularJS

AngularJS HTTP Request:

$http({
method: 'GET',
headers: {
'Content-Type': 'application/json',
Accepts: 'application/json'
},
url: 'https://apisite/v1/users/'
})
.success(function(data){
users.users_list = data.results;
})
.error(function(){

});


On the API server I am using slim and have the following:

use Slim\Slim as Slim;
Slim::registerAutoloader();
$slim = new Slim();
$http_origin = $slim->request->headers->get('Origin');
$slim->response->headers->set('Access-Control-Allow-Origin', '*');
$slim->response->headers->set('Access-Control-Allow-Credentials', 'true');
$slim->response->headers->set('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,OPTIONS');
$slim->response->headers->set('Access-Control-Allow-Headers', 'Origin, Content-Type, Accept, Authorization');

//Routes in here

$slim->run();


While I am not overly happy about always setting the headers regardless like this and not purely on options requests, it works to remove the preflight error on
Access-Control-Allow-Origin
. My issue is now that every time I try access the API I get an preflight error on
OPTIONS
. I cannot figure out how to return a success in Slim on a preflight options check.

I have tried adding conditional steps in to catch options and set headers:

if($slim->request->isOptions()){
header("HTTP/1.1 200 OK");
}


However that doesn't seem to have any effect. I have also tried to create a generic route for all
OPTIONS
request, but again with no luck.

$slim->options('/(:request/)', function () use ($slim){
header("HTTP/1.1 200 OK");
});


I know it is likely something really simple to fix this and likely caused by my complete lack of understanding about the request process between the two servers and which headers are required. Any help would be muchly appreciated.

Error output when trying to load the AngularJS page:

OPTIONS https://apisite/api/v1/users/
(anonymous function) @ angular.js:10514sendReq @ angular.js:10333serverRequest @ angular.js:10045processQueue @ angular.js:14567(anonymous function) @ angular.js:14583Scope.$eval @ angular.js:15846Scope.$digest @ angular.js:15657Scope.$apply @ angular.js:15951done @ angular.js:10364completeRequest @ angular.js:10536requestLoaded @ angular.js:10477
XMLHttpRequest cannot load https://apisite/api/v1/users/. Response for preflight has invalid HTTP status code 404

Answer

A simple solution may be to create a middleware:

use Slim\Slim as Slim;

Slim::registerAutoloader();        
$slim = new Slim();

class CorsMiddleware extends \Slim\Middleware
{
    public function call()
    {
        //The Slim application
        $app = $this->app;

        //Response
        $response = $app->response;
        $response->headers->set('Access-Control-Allow-Origin', '*');
        $response->headers->set('Access-Control-Allow-Credentials', 'true');
        $response->headers->set('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,OPTIONS');
        $response->headers->set('Access-Control-Allow-Headers', 'Origin, Content-Type, Accept, Authorization');

        $this->next->call();
    }
}

$slim->add(new \CorsMiddleware());

$slim->get('/test', function () use ($slim){
    echo "Test!";
});

$slim->run();

All the responses in this application will contain Access-Control-Allow-* headers.