Skip to content

Instantly share code, notes, and snippets.

@matzeeable
Last active February 22, 2024 20:20
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save matzeeable/dfd82239f48c2fedef25141e48c8dc30 to your computer and use it in GitHub Desktop.
Save matzeeable/dfd82239f48c2fedef25141e48c8dc30 to your computer and use it in GitHub Desktop.
Checks if the current request is a WP REST API request.
<?php
if ( !function_exists( 'is_rest' ) ) {
/**
* Checks if the current request is a WP REST API request.
*
* Case #1: After WP_REST_Request initialisation
* Case #2: Support "plain" permalink settings and check if `rest_route` starts with `/`
* Case #3: It can happen that WP_Rewrite is not yet initialized,
* so do this (wp-settings.php)
* Case #4: URL Path begins with wp-json/ (your REST prefix)
* Also supports WP installations in subfolders
*
* @returns boolean
* @author matzeeable
*/
function is_rest() {
if (defined('REST_REQUEST') && REST_REQUEST // (#1)
|| isset($_GET['rest_route']) // (#2)
&& strpos( $_GET['rest_route'] , '/', 0 ) === 0)
return true;
// (#3)
global $wp_rewrite;
if ($wp_rewrite === null) $wp_rewrite = new WP_Rewrite();
// (#4)
$rest_url = wp_parse_url( trailingslashit( rest_url( ) ) );
$current_url = wp_parse_url( add_query_arg( array( ) ) );
return strpos( $current_url['path'] ?? '/', $rest_url['path'], 0 ) === 0;
}
}
@andrewmclagan
Copy link

There are some performance improvements to be had here.

@matzeeable
Copy link
Author

Hi! What exactly can be improved here? Just let me know :-)

@andrewmclagan
Copy link

Before calling $prefix = rest_get_url_prefix( ); you can short circuit the return value when REST_REQUEST is defined. No need to call that function until later.

@kagg-design
Copy link

@matzeeable Thank you for a great piece of code, it is very useful. However, I would like to mention that I tested the code with WP 5.8 and plain permalinks. The proper structure of the URL is like that: site.org/?rest_route=/wp/v2/posts, not site.com/?rest_route=/wp-json/wp/v2/posts. That is why the case #2 code does not work for me. Line 20

&& strpos( trim( $_GET['rest_route'], '\\/' ), rest_get_url_prefix( ) , 0 ) === 0)

should be removed entirely. Without line 20 code works properly.

Kindly check and if I am right, please make modifications here and in the https://wordpress.stackexchange.com/a/317041/108721. Your answer is used widely already, for instance, in the Kadence theme.

@matzeeable
Copy link
Author

@kagg-design what is the result of rest_get_url_prefix() in your case?

@kagg-design
Copy link

wp-json. There is no need to get it, as it is not present in the URL: https://prnt.sc/1qgqeut

@matzeeable
Copy link
Author

@kagg-design Thanks for the hint. Strange, at time of creation of this function I did test all scenarios... I have updated the gist and now I am just checking if rest_route starts with /.

@kagg-design
Copy link

Maybe something changed in the WP Core.

We can look at a simple test site with WP 5.8, 2021 theme and no plugins.

http://test.kagg.eu/?rest_route=/wp-json/wp/v2/posts - 404
http://test.kagg.eu/?rest_route=/wp/v2/posts - works

Many thanks for making changes!

@kadencewp
Copy link

Hi, just a heads up regarding your recent update.

&& strpos( $_GET['rest_route'] ), '/', 0 ) === 0) I think should instead be && strpos( $_GET['rest_route'], '/', 0 ) === 0)

@matzeeable
Copy link
Author

Updated. I should definitely not update gist on my smartphone... :D

@gitgetgotgotten
Copy link

I don't understand what #3 is doing there!

@kagg-design
Copy link

@gitgetgotgotten Look at the code of rest_url() used in line 28.

@gitgetgotgotten
Copy link

@kagg-design Aha, thank you!

@fmurdeni
Copy link

fmurdeni commented Sep 25, 2023

thanks it works for me!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment