5

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?
Jaakko Karhu
  • 2,030
  • 1
  • 23
  • 38

2 Answers2

4

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");
}
Ruslan Stelmachenko
  • 3,746
  • 28
  • 43
Arman sheikh
  • 147
  • 2
  • 7
  • Unfortunately this did not solve the problem, but modifying .htaccess got me closer to the solution. I edited the original question to reflect what I found out. – Jaakko Karhu Jan 16 '19 at 18:42
  • This could mean that you're htaccess is not allowed to override on your other server change allowOverride None to allowOverride All in the httpd.conf file of apache let me know if it works. Or your mod_headers is enabled. – Arman sheikh Jan 17 '19 at 06:23
1

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.

Adam Griffith
  • 312
  • 1
  • 11