I was developing an Ionic Hybrid App that fetches results from the Drupal 8 website and shows recent news with categories. That app also has some basic features like login, signup, bookmarking articles and commenting.
Drupal 8 have built-in modules for REST Web Services which expose entities and other resource using REST API endpoints. I also build some custom REST resources to send a response in my way, And in App, I have implemented some providers which send ajax request to endpoints with HTTP Basic Authentication and get JSON response for App. It’s a simple approach but during the development phase, I got CORS error when App ajax hit the to REST endpoint. After some research, I have found some solution which works for me.
How to set CORS headers in drupal 8?
You can set CORS header in either way listed below.
1:- Setting CORS in services.yml
cors.config:
enabled: true
# Specify allowed headers, like 'x-allowed-header'.
allowedHeaders: ['x-csrf-token','authorization','content-type','accept','origin','x-requested-with', 'access-control-allow-origin','x-allowed-header']
# Specify allowed request methods, specify ['*'] to allow all possible ones.
allowedMethods: ['POST', 'GET', 'OPTIONS', 'PATCH', 'DELETE']
# Configure requests allowed from specific origins.
allowedOrigins: ['*']
# Sets the Access-Control-Expose-Headers header.
exposedHeaders: true
# Sets the Access-Control-Max-Age header.
maxAge: false
# Sets the Access-Control-Allow-Credentials header.
supportsCredentials: true
Make sure you put only those header which you required ( Avoid extra ) or enable only that configuration that you required for security purpose.
2:- Send header from your custom REST plugin resource with the response.
<?php
/**
* function can be get, post, patch, delete
**/
function post($lang) {
// Resource response
$headers = [
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Methods' => 'POST, GET, OPTIONS, PATCH, DELETE',
'Access-Control-Allow-Headers' => 'Authorization'
];
$response = new ResourceResponse($response_result, $response_code, $headers);
// Configure caching for results
if ($response instanceof CacheableResponseInterface) {
$response->addCacheableDependency(new ArticleCachableDepenency(count($response_result),$entities));
}
return $response;
}
This function is extracted from my custom rest resource plugin.
3:- Using Event Subscriber.
Register event subscriber service in module's service file.
services:
cross_origin_request:
class: Drupal\custom_api\EventSubscriber\CrossOriginRequestEventSubscriber
tags:
- {name: event_subscriber}
And CrossOriginRequestEventSubscriber class is below
<?php
namespace Drupal\custom_api\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
class CrossOriginRequestEventSubscriber implements EventSubscriberInterface {
public function setCrossOriginHeader(FilterResponseEvent $event) {
// This will run for all the response
// You might need to add a check here to identify api calls
$response = $event->getResponse();
$response->headers->set('Access-Control-Allow-Origin', '*');
$response->headers->set('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PATCH, DELETE');
$response->headers->set('Access-Control-Allow-Headers', 'Authorization,Content-Type,X-CSRF-Token');
}
/**
* {@inheritdoc}
*/
static public function getSubscribedEvents() {
$events[KernelEvents::RESPONSE][] = ['setCrossOriginHeader', -10];
return $events;
}
}