enable cors in .htaccess

Devin Crossman picture Devin Crossman · Jan 22, 2013 · Viewed 163.2k times · Source

I have created a basic RESTful service with the SLIM PHP framework and now I'm trying to wire it up so that I can access the service from an Angular.js project. I have read that Angular supports CORS out of the box and all I needed to do was add this line: Header set Access-Control-Allow-Origin "*" to my .htaccess file.

I've done this and my REST application is still working (no 500 internal server error from a bad .htaccess) but when I try to test it from test-cors.org it is throwing an error.

Fired XHR event: loadstart
Fired XHR event: readystatechange
Fired XHR event: error

XHR status: 0
XHR status text: 
Fired XHR event: loadend

My .htaccess file looks like this

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ /index.php [QSA,L]
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods: "GET,POST,OPTIONS,DELETE,PUT"

Is there something else I need to add to my .htaccess to get this to work properly or is there another way to enable CORS on my server?

Answer

Devin Crossman picture Devin Crossman · Jan 22, 2013

Since I had everything being forwarded to index.php anyway I thought I would try setting the headers in PHP instead of the .htaccess file and it worked! YAY! Here's what I added to index.php for anyone else having this problem.

// Allow from any origin
if (isset($_SERVER['HTTP_ORIGIN'])) {
    // should do a check here to match $_SERVER['HTTP_ORIGIN'] to a
    // whitelist of safe domains
    header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
    header('Access-Control-Allow-Credentials: true');
    header('Access-Control-Max-Age: 86400');    // cache for 1 day
}
// Access-Control headers are received during OPTIONS requests
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {

    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
        header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");         

    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
        header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");

}

credit goes to slashingweapon for his answer on this question

Because I'm using Slim I added this route so that OPTIONS requests get a HTTP 200 response

// return HTTP 200 for HTTP OPTIONS requests
$app->map('/:x+', function($x) {
    http_response_code(200);
})->via('OPTIONS');