I have an issue with what I believe to be caching of the origin header when querying the WordPress API. However, I am struggling to work out exactly what is happening and how I can fix it.
First - here's what's happening:
I have a HubSpot page that queries via ajax the WordPress API and specifically the endpoints added by the WP API Menus plugin - I then build the menu so that when updated in WordPress by the client (or one of the marketing team) - the menu is updated on the HubSpot pages too.
The HubSpot page is on a subdomain of the WordPress site, and initially the WordPress site had the header Access-Control-Allow-Origin added with just the subdomain URL explicitly set.
If I browse to the edit screen within HubSpot - the main menu doesn't load, but the second call (for a different menu) succeeds. The error for the main menu is as follows:
The 'Access-Control-Allow-Origin' header has a value 'http://subdomain.example.com' that is not equal to the supplied origin. Origin 'https://preview.hs-sites.com' is therefore not allowed access.
The http://subdomain.example.com being the URL of the live page. Strangely the actual URL of the preview page is not https://preview.hs-sites.com - but I assume this may be because perhaps preview loads in an iframe.
Now, when I then go to the live URL, the same thing happens - the first call errors, but the second succeeds. This time the error is as follows:
The 'Access-Control-Allow-Origin' header has a value 'https://preview.hs-sites.com' that is not equal to the supplied origin. Origin 'http://subdomain.example.com' is therefore not allowed access.
Question 1 - is this because the origin has been cached by the WordPress site?
I have now added both http://subdomain.example.com and https://preview.hs-sites.com to the allowed_http_origins filter within WordPress - as follows:
add_filter( 'allowed_http_origins', 'my_add_origins' );
function my_add_origins($origins) {
$origins[] = 'https://preview.hs-sites.com';
$origins[] = 'http://subdomain.example.com';
return $origins;
}
Question 2: Regardless of the presumed caching - why is https://preview.hs-sites.com not acceptable if it has been added to the allowed origins?
I was unsure how to test the above function - so I also tried the following:
add_action( 'rest_api_init', function() {
remove_filter('rest_pre_serve_request', 'rest_send_cors_headers');
add_filter('rest_pre_serve_request', function($value) {
$domains = [
'https://preview.hs-sites.com',
'http://subdomain.example.com'
];
$allowed = get_http_origin();
if ($allowed && (in_array($allowed, $domains))) {
header("Access-Control-Allow-Origin:" . esc_url_raw($allowed));
} elseif (!$allowed) {
header("Access-Control-Allow-Origin: http://subdomain.example.com");
}
header('Access-Control-Allow-Methods: GET');
return $value;
});
});
But the exact same errors occur.
Question 3: Could somebody please explain the process that takes place in this situation and what the errors are saying - specifically where they are getting their values from - is origin the current page? And the 'The 'Access-Control-Allow-Origin' header has a value' ... - this value is being set by whatever has been set as the Access-Control-Allow-Origin header in WordPress - correct?
Note I have also tried setting no-cache header in the ajax request, but this errors because of the preflight request. I've also added a random querystring to the request, which has no effect.
I'd like to avoid adding a wildcard value as the Access-Control-Allow-Origin header for security reasons. And I'd really like to understand what's going on!