What can prevent overriding Access-Control-Allow-Origin in server?

Viewed 3708

I am having an WP site with API and I am calling it with other site. I get this error

Access to XMLHttpRequest at www.wpsiteurl.com from origin www.theothersiteurl.com has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header contains multiple values 'www.theothersiteurl.com, *', but only one is allowed.

I found solutions here and here, which basically introduce adding this to the register function:

remove_filter( 'rest_pre_serve_request', 'rest_send_cors_headers' );
add_action( 'rest_pre_serve_request', function ($value) {
    $origin = get_http_origin();
    header( 'Access-Control-Allow-Headers: X-Requested-With' );
    header( 'Access-Control-Allow-Methods: POST, GET' );
    header( 'Access-Control-Allow-Origin: *');
    header( 'Access-Control-Allow-Credentials: true');
    return $value;
});

For me this does not work, since it just returns * or whatever is added as origin and another *. Changing the second argument does not help, it seems like there is wildcard added to the origins after adding this action.

I edited the .htaccess file as was advised in the answers. This worked on other environment, where I was testing the solution. However, on other server it did not - the origin was added to the string of origins just as if it was added with the php.

To me it seems there is something preventing from completely overriding the access-control-allow-origin and forces adding to it.

My questions are:

  • What can cause the server not allowing to set one Access-Control-Allow-Origin?
  • How do I "override" or clear the Access-Control-Allow-Origin?
2 Answers

There are more than one way to achieve this with multiple host. One is with .htaccess and the other is with php.

With .htaccess:

<IfModule mod_headers.c>
    SetEnvIf Origin "http(s)?://(www\.)?(google.com|staging.google.com|development.google.com|otherdomain.example|dev02.otherdomain.example)$" AccessControlAllowOrigin=$0
    Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
    Header merge Vary Origin
</IfModule>

With PHP:

$origin = $_SERVER['HTTP_ORIGIN'];

if ($origin == "http://www.domain1.com"
        || $origin == "http://www.domain2.com"
        || $origin == "http://www.domain3.com") {
    header("Access-Control-Allow-Origin: $origin");
}

The 'Access-Control-Allow-Origin' header contains multiple values 'www.theothersiteurl.com, *', but only one is allowed.

You have to be very careful to only set this header at one point. This can be done in 3 places:

  • Core Apache config
  • .htaccess
  • PHP

I would recommend doing it inside the core Apache config, due to performance and security reasons.

However if you wish to achieve this using the .htaccess file then make sure nothing is modifying it in PHP and make sure AllowOverride is allowed in the <VirtualHost> block.

Related