We have registered a custom REST GET endpoint using register_rest_route()
, consisting in the retrieval of posts of a custom post type (my_custom_post
). We're using our own endpoint to do so as we do not want to allow direct requests to the endpoint of the concerned post type.
Code Example:
Plugin File Content:
add_action(
'rest_api_init',
function () {
register_rest_route(
'namespace',
'/endpoint',
[
[
'methods' => 'GET',
'callback' => [
SampleController::class,
'test'
],
'args' => [
'test' => [
'type' => 'string',
'description' => 'This is just a test',
'required' => true
]
]
]
]
);
}
);
Request Controller:
class SampleController {
public static function test( WP_REST_Request $request ):WP_REST_Response
{
$search_request = new WP_REST_Request(
method: 'GET',
route: '/wp/v2/my_custom_post'
);
$search_request->set_param(
'_fields',
'id,meta.my_custom_meta'
);
$search_response = rest_do_request($search_request);
$search_response_data = rest_get_server()->response_to_data(
response: $search_response,
embed: false
);
$answer = new WP_REST_Response(
[
'success' => true,
'message' => $search_response_data
],
200
);
$answer->header(
key: 'Cache-Control',
value: 'no-cache',
replace: true
);
return $answer;
}
}
JavaScript:
async function sendRequest() {
const response = await fetch(
'https://example.org/namespace/endpoint?test=hello',
{
method : 'GET',
headers: {
'Content-Type':'application/json',
},
mode : 'same-origin',
cache : 'no-cache'
}
);
const responseData = await response.json();
if (!response.ok || response.status !== 200) {
throw Error('An Error ocurred');
}
return responseData;
}
The requests to the endpoint do not report any errors ever, and everything works fine.
The problem is that, let's say you have 6 posts of the type my_custom_post
. Via the code above, you fire the request once, and get your data.
You then go to the WP Admin, update exclusively the my_custom_meta
of 2 of your posts, and then fire the request again. Problem: the changes are not immediately reflected in your returned response; it always takes about 10 minutes and / or multiple requests. And this although we're applying the Cache-Control: no-cache
headers to our request as well as to the response.
So we wonder, does wordpress actually cache responses of internally executed REST API requests on the server-side? Or what is happening here?
We've also tried to apply the Cache-Control
headers to our internal request, by changing the body of the Controller's test
method above to:
...
$search_request->set_param(
'_fields',
'id,meta.my_custom_meta'
);
$search_request->set_headers(
headers: [ 'Cache-Control' => 'no-cache' ],
override: false
);
$search_response = rest_do_request($search_request);
$search_response->header(
key: 'Cache-Control',
value: 'no-cache',
replace: true
);
...
But the problem persists.
We've then also heard about the rest_send_nocache_headers
hook thanks to this ticket; but we're unsure about how applying that filter to a specific REST API namespace only (because we basically do not want any of our endpoints of a specific namespace to return cached responses).
no-cache
tono-store
based on a reading of hacks.mozilla.org/2016/03/…, in fetchno-cache
doesn't mean never cache if a copy already exists in the HTTP cache, the semantics aren't quite as expected