rest_ensure_response( WP_REST_Response|WP_Error|WP_HTTP_Response|mixed $response ): WP_REST_Response|WP_Error
- Since
- 4.4.0
- Source
wp-includes/rest-api.php:690
Wraps a REST callback's return value in a WP_REST_Response object so WP_REST_Server::dispatch() can call methods like set_status() on it. It passes an existing WP_REST_Response through untouched, rebuilds a WP_HTTP_Response by copying its data, status, and headers, and leaves a WP_Error alone so callers can still check for it with is_wp_error(). It doesn't validate or sanitize the underlying data, so it's meant as the last step of a REST callback rather than a substitute for building the response correctly in the first place.
Description
This implements WP_REST_Response, allowing usage of set_status/header/etc without needing to double-check the object. Will also allow WP_Error to indicate error responses, so users should immediately check for this value.
Compatibility
- WordPress
- since 4.4.0
- PHP
- 7.4–8.6-dev
- 6.7.7
- 6.8.8
- 6.9.7
- 7.0.4
- 7.1.0
Present in every tracked release (6.7.7 to 7.1.0), and compiles on PHP 7.4 through 8.6-dev.
Parameters
$responseWP_REST_Response|WP_Error|WP_HTTP_Response|mixed- Response to check.
Return value
WP_REST_Response|WP_Error- If response generated an error, WP_Error, if response is already an instance, WP_REST_Response, otherwise returns a new WP_REST_Response instance.
Code examples
Every example is editable and runs in a real WordPress booted in your browser by WordPress Playground. Press Run, then edit the code: clicking away re-runs it. Nothing is sent anywhere until you do.
Normalize a REST callback's array return value into a WP_REST_Response
A REST callback often just returns a plain array; run it through rest_ensure_response to see what it becomes.
$raw_data = array(
'post_id' => 2,
'price' => get_post_meta( 2, 'price', true ),
);
$response = rest_ensure_response( $raw_data );
printf(
'Response class: %s, status: %d, data: %s',
esc_html( get_class( $response ) ),
esc_html( (string) $response->get_status() ),
esc_html( wp_json_encode( $response->get_data() ) )
);get_status() returns 200 by default because rest_ensure_response never sets a status when it builds a new WP_REST_Response.
Let a REST callback return either data or a WP_Error and normalize both
This mirrors how a real endpoint callback works, returning an array on success or a WP_Error on failure, then passing both through rest_ensure_response.
function example_rest_lookup_callback( $post_id ) {
$post = get_post( absint( $post_id ) );
if ( ! $post ) {
return new WP_Error( 'not_found', 'No post with that ID.', array( 'status' => 404 ) );
}
return array( 'title' => $post->post_title );
}
$missing = rest_ensure_response( example_rest_lookup_callback( 999 ) );
$found = rest_ensure_response( example_rest_lookup_callback( 1 ) );
printf( 'Missing post result class: %s' . "\n", esc_html( get_class( $missing ) ) );
printf(
'Found post result class: %s, data: %s',
esc_html( get_class( $found ) ),
esc_html( wp_json_encode( $found->get_data() ) )
);Because a WP_Error is returned unchanged, code that calls rest_ensure_response still has to check is_wp_error() before calling response-only methods like get_status().
Common problems and fixes · 4
- Why does rest_ensure_response still give me back a WP_Error instead of a response object?
- Why can't I set a custom status code or headers after calling rest_ensure_response?
- Does rest_ensure_response sanitize or validate the data I return from my endpoint?
- Why does my WP_HTTP_Response lose custom behavior after this runs?
Why does rest_ensure_response still give me back a WP_Error instead of a response object?
Why can't I set a custom status code or headers after calling rest_ensure_response?
new WP_REST_Response( $response ) with no status or header arguments, so it defaults to a 200 with no extra headers.Does rest_ensure_response sanitize or validate the data I return from my endpoint?
Why does my WP_HTTP_Response lose custom behavior after this runs?
Alternatives and related functions
WP_REST_Response- When you already know you need full control over status codes, headers, and links, construct WP_REST_Response directly instead of relying on the default wrapping.
rest_convert_error_to_response- When you specifically want a WP_Error turned into a WP_REST_Response rather than left untouched, use this instead since rest_ensure_response passes errors through unchanged.
is_wp_error- When you need to branch on whether a REST callback's return value is an error before deciding how to handle it, check this before or after calling rest_ensure_response.
WP_HTTP_Response- When writing code that only needs data, status, and headers and isn't REST-specific, use this lighter base class instead of WP_REST_Response.
Performance profile
How much work a call to rest_ensure_response() does, and what it touches: the algorithmic scaling, the Zend instruction count per call across PHP versions, the hooks it hands control to, and the core code that calls it. Measured from the compiled opcodes, not a stopwatch, so every number is identical on any machine running the same PHP version, and every function in core is ranked by cost.
- Cost class
- Trivial
- Scaling
- Constant
- Instructions
- 6–21
- Plugin surface
- None
- Called by
- 50
Touches nothing outside its own arguments.
No loop in the body: the same number of instructions runs whatever you pass in.
Executed per call on PHP 8.5, depending on the branch taken. The body compiles to 27.
Nothing here hands control to plugin code.
50 places in core call this, so the cost is paid more often than your own code shows.
What it touches
- hookthird-party callbacks
do_action()one call below rest_ensure_response()
What one call costs · 2 distinct outcomes
One number would be a lie: the work depends on which branch runs. These are every distinct cost rest_ensure_response() can have, taken from its control-flow graph on PHP 8.5.
| When | Instructions | Calls it makes |
|---|---|---|
| always | 6–13 | is_wp_error() |
!is_wp_error() && !($response instanceof) && $response instanceof | 21 | is_wp_error(), ->get_data(), ->get_status(), ->get_headers() |
Across PHP versions
Compiles the same on PHP 7.4, 8.1, 8.2, 8.3, 8.4, 8.5 and 8.6-dev: 27 instructions, 6–21 executed per call, 3 branches. The work does not change between versions.
An instruction is not a fixed amount of time, so a matching count is not necessarily the same speed; what it rules out is a difference in the work itself.
Uses · 2
- is_wp_error()Checks whether the given variable is a WordPress Error.
- WP_REST_Response::__construct()
Used by · 50
- WP_REST_Abilities_V1_Categories_Controller::get_item()Retrieves a specific ability category.
- WP_REST_Abilities_V1_Categories_Controller::get_items()Retrieves all ability categories.
- WP_REST_Abilities_V1_Categories_Controller::prepare_item_for_response()Prepares an ability category for response.
- WP_REST_Abilities_V1_List_Controller::get_item()Retrieves a specific ability.
- WP_REST_Abilities_V1_List_Controller::get_items()Retrieves all abilities.
- WP_REST_Abilities_V1_List_Controller::prepare_item_for_response()Prepares an ability for response.
- WP_REST_Abilities_V1_Run_Controller::execute_ability()Executes an ability.
- WP_REST_Attachments_Controller::create_item()Creates a single attachment.
- WP_REST_Attachments_Controller::prepare_item_for_response()Prepares a single attachment output for response.
- WP_REST_Attachments_Controller::update_item()Updates a single attachment.
- WP_REST_Autosaves_Controller::create_item()Creates, updates or deletes an autosave revision.
- WP_REST_Autosaves_Controller::get_items()Gets a collection of autosaves using wp_get_post_autosave.
Show all 50
- WP_REST_Block_Directory_Controller::get_items()Search and retrieve blocks metadata
- WP_REST_Block_Pattern_Categories_Controller::get_items()Retrieves all block pattern categories.
- WP_REST_Block_Pattern_Categories_Controller::prepare_item_for_response()Prepare a raw block pattern category before it gets output in a REST API response.
- WP_REST_Block_Patterns_Controller::get_items()Retrieves all block patterns.
- WP_REST_Block_Patterns_Controller::prepare_item_for_response()Prepare a raw block pattern before it gets output in a REST API response.
- WP_REST_Block_Renderer_Controller::get_item()Returns block output from block's registered render_callback.
- WP_REST_Block_Types_Controller::get_item()Retrieves a specific block type.
- WP_REST_Block_Types_Controller::get_items()Retrieves all post block types, depending on user context.
- WP_REST_Block_Types_Controller::prepare_item_for_response()Prepares a block type object for serialization.
- WP_REST_Comments_Controller::create_item()Creates a comment.
- WP_REST_Comments_Controller::get_item()Retrieves a comment.
- WP_REST_Comments_Controller::get_items()Retrieves a list of comment items.
- WP_REST_Comments_Controller::prepare_item_for_response()Prepares a single comment output for response.
- WP_REST_Comments_Controller::update_item()Updates a comment.
- WP_REST_Font_Collections_Controller::get_items()Gets the font collections available.
- WP_REST_Font_Collections_Controller::prepare_item_for_response()Prepare a single collection output for response.
- WP_REST_Font_Faces_Controller::prepare_item_for_response()Prepares a single font face output for response.
- WP_REST_Font_Families_Controller::prepare_item_for_response()Prepares a single font family output for response.
- WP_REST_Global_Styles_Controller::get_theme_item()Returns the given theme global styles config.
- WP_REST_Global_Styles_Controller::get_theme_items()Returns the given theme global styles variations.
- WP_REST_Global_Styles_Controller::prepare_item_for_response()Prepare a global styles config output for response.
- WP_REST_Global_Styles_Revisions_Controller::get_items()Returns paginated revisions of the given global styles config custom post type.
- WP_REST_Global_Styles_Revisions_Controller::prepare_item_for_response()Prepares the revision for the REST response.
- WP_REST_Icons_Controller::get_item()Retrieves a specific icon.
- WP_REST_Icons_Controller::get_items()Retrieves all icons.
- WP_REST_Icons_Controller::prepare_item_for_response()Prepare a raw icon before it gets output in a REST API response.
- WP_REST_Menu_Items_Controller::create_item()Creates a single nav menu item.
- WP_REST_Menu_Items_Controller::prepare_item_for_response()Prepares a single nav menu item output for response.
- WP_REST_Menu_Items_Controller::update_item()Updates a single nav menu item.
- WP_REST_Menu_Locations_Controller::get_item()Retrieves a specific menu location.
- WP_REST_Menu_Locations_Controller::get_items()Retrieves all menu locations, depending on user context.
- WP_REST_Menu_Locations_Controller::prepare_item_for_response()Prepares a menu location object for serialization.
- WP_REST_Menus_Controller::create_item()Creates a single term in a taxonomy.
- WP_REST_Menus_Controller::prepare_item_for_response()Prepares a single term output for response.
- WP_REST_Menus_Controller::update_item()Updates a single term from a taxonomy.
- WP_REST_Navigation_Fallback_Controller::get_item()Gets the most appropriate fallback Navigation Menu.
- WP_REST_Navigation_Fallback_Controller::prepare_item_for_response()Matches the post data to the schema we want.
- WP_REST_Post_Statuses_Controller::get_item()Retrieves a specific post status.
Source code
function rest_ensure_response( $response ) { if ( is_wp_error( $response ) ) { return $response; } if ( $response instanceof WP_REST_Response ) { return $response; } /* * While WP_HTTP_Response is the base class of WP_REST_Response, it doesn't provide * all the required methods used in WP_REST_Server::dispatch(). */ if ( $response instanceof WP_HTTP_Response ) { return new WP_REST_Response( $response->get_data(), $response->get_status(), $response->get_headers() ); } return new WP_REST_Response( $response );}Changelog
Introduced in 4.4.0. Unchanged from 6.7.7 through 7.1.0.
Signature, return type and hooks compared across 5 parsed releases.
About this page
- Parsed data
- Generated from the wordpress-develop 7.0.4 tag, from
src/wp-includes/rest-api.php, and regenerated for each WordPress release so it tracks the code rather than a snapshot of it. - Corrections
- Something wrong on this page? Report it and it gets fixed in the next regeneration.