Setting up CORS
CORS - Cross origin resource sharing
A good flowchart for implementing CORS support Reference:
You can test your CORS Support here: http://www.test-cors.org/
You can read the specification here: https://www.w3.org/TR/cors/
The simple solution
For simple CORS requests, the server only needs to add the following header to its response:
Access-Control-Allow-Origin: <domain>, … | *
The following code should enable 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://mysite')
->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization')
->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
});
Add the following route as the last route:
// 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) {
$handler = $this->notFoundHandler; // handle using the default Slim page not found handler
return $handler($req, $res);
});
Access-Control-Allow-Methods
The following middleware can be used to query Slim’s router and get a list of methods a particular pattern implements.
Here is a complete example application:
require __DIR__ . "/vendor/autoload.php";
// This Slim setting is required for the middleware to work
$app = new Slim\App([
"settings" => [
"determineRouteBeforeAppMiddleware" => true,
]
]);
// This is the middleware
// It will add the Access-Control-Allow-Methods header to every request
$app->add(function($request, $response, $next) {
$route = $request->getAttribute("route");
$methods = [];
if (!empty($route)) {
$pattern = $route->getPattern();
foreach ($this->router->getRoutes() as $route) {
if ($pattern === $route->getPattern()) {
$methods = array_merge_recursive($methods, $route->getMethods());
}
}
//Methods holds all of the HTTP Verbs that a particular route handles.
} else {
$methods[] = $request->getMethod();
}
$response = $next($request, $response);
return $response->withHeader("Access-Control-Allow-Methods", implode(",", $methods));
});
$app->get("/api/{id}", function($request, $response, $arguments) {
});
$app->post("/api/{id}", function($request, $response, $arguments) {
});
$app->map(["DELETE", "PATCH"], "/api/{id}", function($request, $response, $arguments) {
});
// Pay attention to this when you are using some javascript front-end framework and you are using groups in slim php
$app->group('/api', function () {
// Due to the behaviour of browsers when sending PUT or DELETE request, you must add the OPTIONS method. Read about preflight.
$this->map(['PUT', 'OPTIONS'], '/{user_id:[0-9]+}', function ($request, $response, $arguments) {
// Your code here...
});
});
$app->run();
A big thank you to tuupola for coming up with this!