The Problem
Nowadays I was creating a new version of my library https://github.com/enzolutions/backbone.drupal to enable to use Drupal 8 in mode Headless Drupal using front end in a different domain or subdomain.
The problem I found with CORS requests is related with the way jQuery execute the first request Ajax because before to do execution of a GET|PUT|DELETE|POST|PATCH request an OPTIONS request is performed to validate request methods accepted for backend server more information at http://api.jquery.com/jquery.ajax/ in contentType section.
The current status of Rest module (part of Drupal Core) doesn’t implement the OPTIONS method, so my first approach has implemented that method in class Drupal\rest\Plugin\rest\resource\EntityResource using the following code
public function options(EntityInterface $entity) {
$response = new ResourceResponse();
$response->setStatusCode(ResourceResponse::HTTP_OK);
$response->headers->set('Allow', 'GET,POST,PATCH,DELETE,OPTIONS');
return $response->send();
}
After adding that extra function in class EntityResource the method was available and double checked with module RestUI, but this solution wasn’t enough because I can’t enable OPTIONS method without authentication and jQuery trigger the OPTIONS method without CRC Token or Basic Auth method even if you provide in the original call.
The Solution
To resolve the problem I use .htaccess and Apache mod_rewrite to enable CORS and intercept the OPTIONS request to avoid Drupal reject the request because doesn’t have the proper credentials, I did a patch for Drupal 8, and you can download the patch here.
But let me explain the changes introduced in my patch.
Intercept OPTIONS Request
I added a Mod Rewrite Condition and Rule to avoid all OPTIONS request be processed by Drupal and rejected, instead of an HTTP 200 OK code is returned to enable jQuery request to continue with the normal workflow.
Check the code below.
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule .* / [R=200,L]
Enable CORS
If you search how to enable CORS using .htaccess you will find tons of similar information, and this information usually works, but in our case, we have a unique situation the intercept process we implemented above.
Because the interception the usual statements to enable CORS doesn’t work, and Apache will reject our request, to resolve this problem I found the condition always for Header directive.
Check the implementation below.
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, PATCH,
DELETE"
Header always set Access-Control-Allow-Headers: Authorization
I strongly recommend changing * for your frontend domain, i.e., frontend-example.com.
I expect you have found this entry useful.