An endpoint of https://example.com/wp-json/wp/v2/pages/123
returns a combination of HTML and JSON format such as:
<div class="my-class">HTML Content</div>
{ "id" : 123, ... }
There is an excerpt filter in functions.php
that set the outputted HTML, in this line:
function my_custom_filter(){
echo '<div class="my-class">HTML Content</div>';
}
add_filter ('the_excerpt', 'my_custom_filter' );
How to prevent such filter from intervening with the JSON response?
If you can modify the filter, then you can detect the REST API inside the filter function, like this:
function my_custom_filter(){
if (! defined("REST_REQUEST")) {
echo '<div class="my-class">HTML Content</div>';
}
}
add_filter ('the_excerpt', 'my_custom_filter' );
The constant REST_REQUEST
is only defined inside a request that was handled by the REST API. So, with the code above, if a request is being handled by the normal WP request cycle, the constant will not be defined, so the if
statement we added will evaluate as true
and the echo
will occur like normal. If the constant is defined, then the if
will evaluate as false and the filter will not add any output to the response.
See https://wpseek.com/constant/rest_request/
UPDATE: while the code above will work, I think we can do better.
The problem is that if you have many filters, every one of them needs to duplicate the if
statement and your code become littered with checks for REST_REQUEST
, which
Instead, we can introduce the REST_REQUEST
checks earlier in the cycle by making it a concern of the code that adds the filter.
This would look like:
function my_custom_filter(){
echo '<div class="my-class">HTML Content</div>';
}
if (! defined("REST_REQUEST")) {
add_filter ('the_excerpt', 'my_custom_filter' );
//add other HTML filters here
} else {
//attach REST API actions
}
This seems like a small change (if you catch it early, when the number of filters is small), but it potentially brings some big advantages:
it keeps the REST_REQUEST
checks all in one place: maintainability
the filters don't need to know or care about whether it's a REST_REQUEST
or not - if they get called, they're good to go. Keeping it simple.
you can potentially do other things like logging or role-based access checks in that place: extensibility
It's a relatively easy change to make early on in your application, but becomes more difficult and error prone as you add further filters and actions. Always better to do it right the first time!