public options ( Imbo\EventManager\EventInterface $event ) | ||
$event | Imbo\EventManager\EventInterface | The event instance |
public function options(EventInterface $event)
{
$request = $event->getRequest();
$response = $event->getResponse();
$origin = $request->headers->get('Origin');
// This is an OPTIONS request, send 204 since no more content will follow
$response->setStatusCode(204);
// Vary on Origin to prevent caching allowed/disallowed requests
$event->getResponse()->setVary('Origin', false);
// Fall back if the passed origin is not allowed
if (!$origin || !$this->originIsAllowed($origin)) {
return;
}
$resource = (string) $request->getRoute();
$allowedMethods = ['OPTIONS'];
if (isset($this->params['allowedMethods'][$resource])) {
$allowedMethods = array_merge($allowedMethods, $this->params['allowedMethods'][$resource]);
}
$allowedHeaders = ['Content-Type', 'Accept'];
$requestHeaders = $request->headers->get('Access-Control-Request-Headers', '');
$requestHeaders = array_map('trim', explode(',', $requestHeaders));
foreach ($requestHeaders as $header) {
if (strpos($header, 'x-imbo') === 0) {
$allowedHeaders[] = implode('-', array_map('ucfirst', explode('-', $header)));
}
}
$response->headers->add(['Access-Control-Allow-Origin' => $origin, 'Access-Control-Allow-Methods' => implode(', ', $allowedMethods), 'Access-Control-Allow-Headers' => implode(', ', $allowedHeaders), 'Access-Control-Max-Age' => (int) $this->params['maxAge']]);
// Since this is an OPTIONS-request, there is no need for further parsing
$event->stopPropagation();
}
/** * @covers Imbo\EventListener\Cors::options */ public function testSetsCorrectResposeHeadersOnOptionsRequestWhenOriginIsAllowed() { $listener = new Cors(['allowedOrigins' => ['*'], 'allowedMethods' => ['image' => ['HEAD']], 'maxAge' => 60]); $route = $this->getMock('Imbo\\Router\\Route'); $route->expects($this->once())->method('__toString')->will($this->returnValue('image')); $this->request->expects($this->once())->method('getRoute')->will($this->returnValue($route)); $this->request->headers = $this->getMock('Symfony\\Component\\HttpFoundation\\HeaderBag'); $this->request->headers->expects($this->at(0))->method('get')->with('Origin')->will($this->returnValue('http://imbo-project.org')); $this->request->headers->expects($this->at(1))->method('get')->with('Access-Control-Request-Headers', '')->will($this->returnValue('x-imbo-signature,something-else')); $headers = $this->getMock('Symfony\\Component\\HttpFoundation\\HeaderBag'); $headers->expects($this->once())->method('add')->with(['Access-Control-Allow-Origin' => 'http://imbo-project.org', 'Access-Control-Allow-Methods' => 'OPTIONS, HEAD', 'Access-Control-Allow-Headers' => 'Content-Type, Accept, X-Imbo-Signature', 'Access-Control-Max-Age' => 60]); $this->response->headers = $headers; $this->response->expects($this->once())->method('setStatusCode')->with(204); $this->event->expects($this->once())->method('stopPropagation'); $listener->options($this->event); }