I have a custom WordPress REST API endpoint that returns the output
ofget_template_part
Note that the REST API expects your endpoint callback to always return the response (e.g. the template part output in your case), and not echo it or anything else. And after the callback is called, the REST API will send some headers, by default an Allow
header and then any extra headers from your response — see WP_REST_Server::serve_request()
, particularly lines #440 and #472.
So because of that, you should not echo anything in your callback, because for example echo 'foo'; header( 'Allow: GET' );
will cause the “headers already sent” error because the echo
started the output, hence PHP issues a warning if you try to send a (HTTP) header afterwards.
Therefore, despite you said, “The error started when I started making these requests.“, I’m pretty sure the problem is with your call to get_template_part()
which (despite the name) actually simply loads the template part and if successful, the function returns nothing.
And if the template part echo something (which is what happens in most cases) just like yours as in the question, then that will result in the “headers already sent” warning. Try commenting out the get_template_part()
call and see if the warning goes away. 🙂
But even if not, please ensure your callback is not echoing anything because doing so will invalidate the JSON response (both header and content) which is the default response type returned by the REST API endpoint. However, if you need to echo something, then you would want to use output buffering like so in your case:
function build_home() {
ob_start();
// ... your code.
get_template_part( ... your code ... );
$data = ob_get_clean();
// The array key ("html") below can be any other name that you prefer.
return new WP_REST_Response( array(
'html' => $data,
) );
}
And please always set the permission_callback
for your endpoint, because otherwise, you’d get a (_doing_it_wrong()
) notice like so:
The REST API route definition for
theme/v2/homepage
is missing the requiredpermission_callback
argument. For REST API routes that are intended to be public, use__return_true
as the permission callback.
So for example, your code would look like so:
register_rest_route(
'theme/v2', // namespace
'/homepage', // route
array( // options
'methods' => 'GET',
'callback' => 'build_home',
'permission_callback' => '__return_true', // always set a permission callback
),
);
And BTW, if you want a different response type (i.e. Content-Type
) for your endpoint, then you can use the rest_pre_serve_request
hook — see an example in my answer here.