Apakah ada sesuatu seperti is_rest () ada

17

Saya mulai sedikit dengan REST API. Jika saya tidak sepenuhnya menyesatkan, inithook tindakan juga dieksekusi saat permintaan REST API. Sekarang, saya ingin menjalankan beberapa kode saja, ketika itu bukan permintaan REST API.

Jadi saya mencari perintah seperti is_rest()untuk melakukan sesuatu seperti

<?php
if( ! is_rest() ) echo 'no-rest-request';
?>

Tetapi saya tidak dapat menemukan sesuatu seperti ini. Apakah ada di is_rest()luar sana?

websupporter
sumber
1
Mungkin Anda bisa menguraikan apa yang ingin Anda lakukan ketika itu bukan permintaan REST? Jenis permintaan tidak ditentukan sampai permintaan penguraian, yang terjadi setelah init. Perhatikan juga bahwa bagian-bagian dari API dapat digunakan secara internal pada permintaan yang bukan permintaan REST, sehingga Anda berisiko melanggar sesuatu jika Anda mengandalkan deteksi itu.
Milo
Terima kasih banyak, kalian berdua. @ Borgire: Dapatkah Anda memposting ini sebagai jawaban, jadi saya bisa memeriksanya. Pada dasarnya, ini adalah jawaban untuk pertanyaan saya :)
websupporter

Jawaban:

14

Ini poin yang bagus oleh @Milo, REST_REQUESTkonstanta didefinisikan sebagai true, di dalam rest_api_loaded()jika $GLOBALS['wp']->query_vars['rest_route']tidak kosong.

Ini terhubung ke parse_requestmelalui:

add_action( 'parse_request', 'rest_api_loaded' );

tetapi parse_requestkebakaran lebih lambat dari init- Lihat misalnya Codex di sini .

Ada saran (oleh Daniel Bachhuber) di tiket # 34373 tentang WP_Query::is_rest(), tetapi ditunda / dibatalkan.

birgire
sumber
11

Hanya tersandung masalah yang sama dan menulis fungsi sederhana is_restyang memungkinkan Anda untuk memeriksa apakah permintaan saat ini adalah permintaan API WP REST.

<?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
     * 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() {
        $prefix = rest_get_url_prefix( );
        if (defined('REST_REQUEST') && REST_REQUEST // (#1)
                || isset($_GET['rest_route']) // (#2)
                        && strpos( trim( $_GET['rest_route'], '\\/' ), $prefix , 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;
    }
}

Referensi:

Matthias Günter
sumber
4

Untuk mengatasi masalah ini, saya menulis fungsi kustom sederhana berdasarkan asumsi bahwa jika URI yang diminta berada di bawah URL API Rest situs WordPress, maka itu adalah permintaan API Rest.

Apakah itu titik akhir yang valid, atau dikonfirmasi, bukan untuk fungsi ini untuk menentukan. Pertanyaannya adalah ini: apakah URL tersebut merupakan URL potensial Rest API?

function isRestUrl() {
    $bIsRest = false;
    if ( function_exists( 'rest_url' ) && !empty( $_SERVER[ 'REQUEST_URI' ] ) ) {
        $sRestUrlBase = get_rest_url( get_current_blog_id(), '/' );
        $sRestPath = trim( parse_url( $sRestUrlBase, PHP_URL_PATH ), '/' );
        $sRequestPath = trim( $_SERVER[ 'REQUEST_URI' ], '/' );
        $bIsRest = ( strpos( $sRequestPath, $sRestPath ) === 0 );
    }
    return $bIsRest;
}

Jika Anda $_SERVER['REQUEST_URI']tidak terisi dengan benar, fungsi ini akan tetap kembali false, apa pun.

Tidak ada pengodean URL sehingga jika Anda karena suatu alasan mengubah basis URL API Anda, ini akan beradaptasi.

Paul G.
sumber
3

Mungkin tidak benar, tetapi saya berakhir dengan

if (strpos($_SERVER[ 'REQUEST_URI' ], '/wp-json/') !== false) {
    // Cool API stuff here
}

Silakan beri tahu saya jika ini tidak benar. Mencoba membuat starter plugin yang bermanfaat untuk akhirnya berbagi: https://gitlab.com/ripp.io/wordpress/plugin-starter

Charly
sumber
1
Saya pikir, ini akan gagal, jika Anda tidak memiliki permalink cantik aktif.
websupporter
Anda pasti benar
Charly
Ok itu memerlukan permalink yang cantik ... tapi siapa yang tidak menginginkannya !!!? Bagi saya ini cara paling aman untuk melakukan ini. Semua solusi lain bagus tetapi seiring waktu jika Anda ingin kode Anda tetap berjalan pada versi wp nanti ... ini menurut saya cara yang aman !!
Antony Gibbs
1

Dua opsi di sini benar-benar,

  1. Periksa apakah REST_REQUESTsudah ditentukan.
  2. Kaitkan ke rest_api_inittempat yang Anda inginkan init.
Menandai
sumber
0

Inilah yang saya pikirkan:

/**
 * Determines if the current request we are handling is a REST Request.
 * This function can be called even on mu-plugins.
 *
 * You might want to prefix this function name with
 * something more unique to your project.
 *
 * @return bool
 */
function is_rest(): bool {
    $is_cli              = php_sapi_name() === 'cli';
    $permalink_structure = get_option( 'permalink_structure' );
    $rest_prefix         = rest_get_url_prefix();

    if ( ! empty( $permalink_structure ) && ! $is_cli ) {
        /*
         * HTTP request with Pretty Permalinks.
         */
        if ( substr( $_SERVER['REQUEST_URI'], 0, strlen( $rest_prefix ) ) === $rest_prefix ) {
            return true;
        }
    } elseif ( empty( $permalink_structure ) && ! $is_cli ) {
        /*
         * HTTP Requests with Plain Permalinks
         *
         * We can rely on "?rest_route" for plain permalinks, this value don't change:
         * wp/wp-includes/rest-api.php:145
         *
         * All ?rest_route must start with "/":
         * wp/wp-includes/rest-api.php:159
         */
        if ( isset( $_GET['rest_route'] ) && substr( $_GET['rest_route'], 0, 1 ) === '/' ) {
            return true;
        }
    } elseif ( $is_cli ) {
        /*
         * CLI request
         */
        if ( did_action( 'parse_request' ) ) {
            return defined( 'REST_REQUEST' ) && REST_REQUEST;
        } else {
            throw new RuntimeException( "Maybe someone at StackOverflow can help fill this gap of identifying REST requests on CLI before the parse_request action has fired and the REST_REQUEST constant is available?" );
        }
    }

    return false;
}

Saya belum punya banyak waktu untuk melihat ke dalam membuat CLI mendeteksi permintaan REST sebelum parse_requesttindakan telah dipecat. Saya terbuka untuk saran!

Saya belum menulis beberapa tes di sekitar fitur ini, saya akan memperbarui jawaban ini begitu saya lakukan.

- Edit

Baru saja menemukan bagaimana WooCommerce menangani ini. WooCommerce tampaknya tidak memperhitungkan permalink polos:

public function is_rest_api_request() {
    if ( empty( $_SERVER['REQUEST_URI'] ) ) {
        return false;
    }

    $rest_prefix         = trailingslashit( rest_get_url_prefix() );
    $is_rest_api_request = ( false !== strpos( $_SERVER['REQUEST_URI'], $rest_prefix ) );

    return apply_filters( 'woocommerce_is_rest_api_request', $is_rest_api_request );
}
Lucas Bustamante
sumber