路由和端点

最后更新于:2021-11-30 11:47:24

Routes and Endpoints

概述

REST API为我们提供了一种将URI匹配到我们的WordPress安装中的各种资源的方法。 默认情况下,如果您启用了漂亮的永久链接,则WordPress REST API“生活”在/ wp-json /。 在我们的WordPress网站https://ourawesomesite.com上,我们可以通过向https://ourawesomesite.com/wp-json/发出GET请求来访问REST API的索引。 该索引提供有关可用于特定WordPress安装的路由的信息,以及支持哪些HTTP方法以及注册了哪些端点。

路由 vs 端点

端点是通过API可用的函数。这可能是检索API索引、更新文章或删除评论。端点执行特定功能,获取一些参数并将数据返回给客户端。

路由是您用于访问URL中使用的端点的“名称”。路由可以有多个端点与之关联,使用的端点取决于HTTP请求。

例如,使用URL“http://example.com/gc-json/gc/v2/posts/123”:

  • “路由”是gc/v2/posts/123——路由不包括gc-json,因为gc-json是API本身的基础路径。
  • 此路由有3个端点:
    • GET触发get_item方法,将文章数据返回给客户端。
    • PUT triggers an update_item method, taking the data to update, and returning the updated post data.
    • DELETE触发delete_item方法,将现在删除的文章数据返回给客户端。

警报:
在没有漂亮永久链接的网站上,路由将作为rest_route添加到URL中。对于上述示例,完整的URL将是http://example.com/?rest_route=/gc/v2/posts/123

创建端点

如果我们想创建一个端点,在收到GET请求时返回“您好世界,这是GeChiUI REST API”短语,我们首先需要注册该端点的路由。要注册路由,您应该使用register_rest_route()函数。它需要在rest_api_init操作钩子上调用。register_rest_route()处理到端点的路由的所有映射。让我们尝试创建一个“你好,世界,这是GeChiUI REST API”的路线。

/**
 * This is our callback function that embeds our phrase in a GC_REST_Response
 */
function prefix_get_endpoint_phrase() {
    // rest_ensure_response() wraps the data we want to return into a GC_REST_Response, and ensures it will be properly returned.
    return rest_ensure_response( 'Hello World, this is the GeChiUI REST API' );
}

/**
 * This function is where we register our routes for our example endpoint.
 */
function prefix_register_example_routes() {
    // register_rest_route() handles more arguments but we are going to stick to the basics for now.
    register_rest_route( 'hello-world/v1', '/phrase', array(
        // By using this constant we ensure that when the GC_REST_Server changes our readable endpoints will work as intended.
        'methods'  => GC_REST_Server::READABLE,
        // Here we register our callback. The callback is fired when this endpoint is matched by the GC_REST_Server class.
        'callback' => 'prefix_get_endpoint_phrase',
    ) );
}

add_action( 'rest_api_init', 'prefix_register_example_routes' );

传递到register_rest_route()的第一个参数是命名空间,它为我们提供了一种对路由进行分组的方法。传递的第二个参数是资源路径或资源库。例如,我们正在检索的资源是“您好世界,这是GeChiUI REST API”短语。第三个参数是一系列选项。我们指定了端点可以使用哪些方法,以及匹配端点时应该进行哪些回调(可以做更多事情,但这些是基本要素)。

第三个参数还允许我们提供权限回调,该回调可以将端点的访问限制为仅某些用户。第三个参数还提供了一种注册端点参数的方法,以便请求可以修改我们端点的响应。我们将在本指南的端点部分讨论这些概念。

当我们访问“https://ourawesomesite.com/gc-json/hello-world/v1/phrase”时,我们现在可以看到我们的REST API对我们友好地问候。让我们更深入地看看路线。

路线

Routes in the REST API are represented by URIs. The route itself is what is tacked onto the end of https://ourawesomesite.com/gc-json`. The index route for the API is‘/’which is whyhttps://ourawesomesite.com/gc-json/` returns all of the available information for the API. All routes should be built onto this route, the gc-json portion can be changed, but in general, it is advised to keep it the same.

We want to make sure that our routes are unique. For instance we could have a route for books like this: /books. Our books route would now live at https://ourawesomesite.com/gc-json/books`. However, this is not a good practice as we would end up polluting potential routes for the API. What if another plugin we wanted to register a books route as well? We would be in big trouble in that case, as the two routes would conflict with each other and only one could be used. The fourth parameter toregister_rest_route()` is a boolean for whether the route should override an existing route.

覆盖参数也没有真正解决我们的问题,因为两条路由都可以覆盖,或者我们希望将两条路由用于不同的事情。这就是使用命名空间进行路线的作用所在。

命名空间

向路线添加命名空间极其重要。“核心”端点使用gc/v2命名空间。

警告:除非您制作端点,意图将其合并到核心中,否则不要将任何东西放入gc命名空间。

在核心端点命名空间中有一些关键事项需要注意。命名空间的第一部分是gc,它代表供应商名称;GeChiUI。对于我们的插件,我们希望为命名空间中我们所谓的供应商部分提供唯一的名称。在上面的示例中,我们使用了hello-world

供应商部分后面是命名空间的版本部分。“核心”端点使用v2来表示GeChiUI REST API的版本2。如果您正在编写插件,只需创建新的端点并提升您提供的版本号,即可保持REST API端点的向后兼容性。这样可以访问原始的v1v2端点。

命名空间后面的路由部分是资源路径。

资源路径

资源路径应指示端点与什么资源相关联。在我们上面使用的示例中,我们使用单词phrase来表示我们正在交互的资源是一个短语。为了避免任何冲突,我们注册的每个资源路径也应在命名空间中是唯一的。资源路径应用于定义给定命名空间中的不同资源路由。

假设我们有一个处理一些基本电子商务功能的插件。我们将有两种主要的资源类型订单和产品。订单是对产品的请求,但它们本身不是产品。同样的概念也适用于产品。虽然这些资源是相关的,但它们不是一回事,每个资源路径都应该生活在单独的资源路径中。我们的路线最终将为我们的电子商务插件寻找类似的东西:/my-shop/v1/orders/my-shop/v1/products

使用这样的路线,我们希望每个路线都退回一系列订单或产品。如果我们想按ID抓取特定产品,我们需要在路由中使用路径变量。

路径变量

路径变量使我们能够添加动态路由。为了扩展我们的电子商务路线,我们可以注册一条获取单个产品的路线。


/**
 * This is our callback function to return our products.
 *
 * @param GC_REST_Request $request This function accepts a rest request to process data.
 */
function prefix_get_products( $request ) {
    // In practice this function would fetch the desired data. Here we are just making stuff up.
    $products = array(
        '1' => 'I am product 1',
        '2' => 'I am product 2',
        '3' => 'I am product 3',
    );

    return rest_ensure_response( $products );
}

/**
 * This is our callback function to return a single product.
 *
 * @param GC_REST_Request $request This function accepts a rest request to process data.
 */
function prefix_get_product( $request ) {
    // In practice this function would fetch the desired data. Here we are just making stuff up.
    $products = array(
        '1' => 'I am product 1',
        '2' => 'I am product 2',
        '3' => 'I am product 3',
    );

    // Here we are grabbing the 'id' path variable from the $request object. GC_REST_Request implements ArrayAccess, which allows us to grab properties as though it is an array.
    $id = (string) $request['id'];

    if ( isset( $products[ $id ] ) ) {
        // Grab the product.
        $product = $products[ $id ];

        // Return the product as a response.
        return rest_ensure_response( $product );
    } else {
        // Return a GC_Error because the request product was not found. In this case we return a 404 because the main resource was not found.
        return new GC_Error( 'rest_product_invalid', esc_html__( 'The product does not exist.', 'my-text-domain' ), array( 'status' => 404 ) );
    }

    // If the code somehow executes to here something bad happened return a 500.
    return new GC_Error( 'rest_api_sad', esc_html__( 'Something went horribly wrong.', 'my-text-domain' ), array( 'status' => 500 ) );
}

/**
 * This function is where we register our routes for our example endpoint.
 */
function prefix_register_product_routes() {
    // Here we are registering our route for a collection of products.
    register_rest_route( 'my-shop/v1', '/products', array(
        // By using this constant we ensure that when the GC_REST_Server changes our readable endpoints will work as intended.
        'methods'  => GC_REST_Server::READABLE,
        // Here we register our callback. The callback is fired when this endpoint is matched by the GC_REST_Server class.
        'callback' => 'prefix_get_products',
    ) );
    // Here we are registering our route for single products. The (?P<id>[d]+) is our path variable for the ID, which, in this example, can only be some form of positive number.
    register_rest_route( 'my-shop/v1', '/products/(?P<id>[d]+)', array(
        // By using this constant we ensure that when the GC_REST_Server changes our readable endpoints will work as intended.
        'methods'  => GC_REST_Server::READABLE,
        // Here we register our callback. The callback is fired when this endpoint is matched by the GC_REST_Server class.
        'callback' => 'prefix_get_product',
    ) );
}

add_action( 'rest_api_init', 'prefix_register_product_routes' );

上述示例涵盖很多内容。需要注意的重要部分是,在我们注册的第二条路线中,我们添加了路径变量/(?P<id>[d]+)到我们的资源路径/products。路径变量是一个正则表达式。在这种情况下,它使用[d]+表示至少应该是任何数字字符一次。如果您的资源使用数字ID,那么这是如何使用路径变量的绝佳示例。在使用路径变量时,我们现在必须小心可以匹配的内容,因为它是用户输入。

幸运的是,正则表达式会过滤掉任何非数字的东西。但是,如果请求ID的产品不存在,那会怎样。我们需要处理错误。您可以在上面的代码示例中看到我们处理错误的基本方法。当您在端点回调中返回GC_Error时,API服务器将自动处理向客户端服务错误。

虽然本节是关于路线的,但我们已经讨论了很多关于端点的内容。端点和路由是相互关联的,但它们肯定有区别。

端点

端点是路由需要映射到的目标。对于任何给定的路由,您可以注册许多不同的端点。我们将扩展我们虚构的电子商务插件,以更好地显示路由和端点之间的区别。我们将创建两个存在于/gc-json/my-shop/v1/products/路由中的端点。一个端点使用HTTP请求GET获取产品,另一个端点使用HTTP请求POST创建新产品。


/**
 * This is our callback function to return our products.
 *
 * @param GC_REST_Request $request This function accepts a rest request to process data.
 */
function prefix_get_products( $request ) {
    // In practice this function would fetch the desired data. Here we are just making stuff up.
    $products = array(
        '1' => 'I am product 1',
        '2' => 'I am product 2',
        '3' => 'I am product 3',
    );

    return rest_ensure_response( $products );
}

/**
 * This is our callback function to return a single product.
 *
 * @param GC_REST_Request $request This function accepts a rest request to process data.
 */
function prefix_create_product( $request ) {
    // In practice this function would create a product. Here we are just making stuff up.
   return rest_ensure_response( 'Product has been created' );
}

/**
 * This function is where we register our routes for our example endpoint.
 */
function prefix_register_product_routes() {
    // Here we are registering our route for a collection of products and creation of products.
    register_rest_route( 'my-shop/v1', '/products', array(
        array(
            // By using this constant we ensure that when the GC_REST_Server changes, our readable endpoints will work as intended.
            'methods'  => GC_REST_Server::READABLE,
            // Here we register our callback. The callback is fired when this endpoint is matched by the GC_REST_Server class.
            'callback' => 'prefix_get_products',
        ),
        array(
            // By using this constant we ensure that when the GC_REST_Server changes, our create endpoints will work as intended.
            'methods'  => GC_REST_Server::CREATABLE,
            // Here we register our callback. The callback is fired when this endpoint is matched by the GC_REST_Server class.
            'callback' => 'prefix_create_product',
        ),
    ) );
}

add_action( 'rest_api_init', 'prefix_register_product_routes' );

根据我们用于路由/gc-json/my-shop/v1/productsHTTP方法,我们将匹配到不同的端点,并触发不同的回调。当我们使用POST时,我们会触发prefix_create_product()回调,当我们使用GET时,我们会触发prefix_get_products()回调。

有许多不同的HTTP方法,REST API可以使用其中任何一种。

HTTP方法

HTTP方法有时被称为HTTP请求。它们只是通过HTTP进行通信的不同方式。GeChiUI REST API使用的主要内容是:

  • GET应用于从API中检索数据。
  • POST应用于创建新资源(即用户、文章、分类)。
  • PUT应该用于更新资源。
  • DELETE应该用于删除资源。
  • OPTIONS应该用来提供有关我们资源的背景。

需要注意的是,并非所有客户端都支持这些方法,因为它们是在HTTP 1.1中引入的。幸运的是,API为这些不幸的情况提供了一个变通办法。如果您想删除资源,但无法发送DELETE请求,那么您可以在请求中使用_method参数或X-HTTP-Method-Override标头。您将如何工作,将POST请求发送到“https://ourawesomesite.com/gc-json/my-shop/v1/products/1?”_method=DELETE`。现在,您将删除产品编号1,即使您的客户端无法在请求中发送正确的HTTP方法,或者可能有一个防火墙可以阻止删除请求。

HTTP方法与路由和回调相结合,构成了端点的核心。

回调

对于REST API支持的端点,目前只有两种类型的回调:callback permission_callback。主回调应处理与资源的交互。权限回调应处理用户有权访问端点的内容。您可以在注册端点时通过添加其他信息来添加其他回调。然后,您可以钩住rest_pre_dispatchrest_dispatch_requestrest_post_dispatch钩子来触发新的自定义回调。

端点回调

删除端点的主要回调只应删除资源,并在响应中返回其副本。创建端点的主要回调应仅创建资源并返回与新创建的数据匹配的响应。更新回调只应修改实际存在的资源。读取回调只应检索已经存在的数据。重要的是要考虑幂等的概念。

在REST API上下文中,幂等意味着,如果您向端点发出相同的请求,服务器将以相同的方式处理请求。想象一下,如果我们的读取端点不是幂等的。每当我们向它提出请求时,即使我们只是试图获取数据,我们的服务器状态也会被请求修改。这可能是灾难性的。每当有人从您的服务器获取数据时,内部都会发生变化。重要的是要确保读取、更新和删除端点不会产生令人讨厌的副作用,而要坚持它们要做的事情。

在REST API中,幂等性的概念与HTTP方法相关联,而不是端点回调。使用GETHEADTRACEOPTIONSPUTDELETE的任何回调都不应产生任何副作用。POST请求不是幂等的,通常用于创建资源。如果您创建了幂等创建方法,那么您只会创建一个资源,因为当您提出相同的请求时,服务器将不再产生副作用。对于创建,如果您在服务器上反复提出相同的请求,则每次都应生成新资源。

要限制端点的使用,我们需要注册权限回调。

权限回电

权限回调对GeChiUI REST API的安全性至关重要。如果您有任何不应公开显示的私人数据,那么您需要为端点注册权限回调。以下是如何注册权限回调的示例。


/**
 * This is our callback function that embeds our resource in a GC_REST_Response
 */
function prefix_get_private_data() {
    // rest_ensure_response() wraps the data we want to return into a GC_REST_Response, and ensures it will be properly returned.
    return rest_ensure_response( 'This is private data.' );
}

/**
 * This is our callback function that embeds our resource in a GC_REST_Response
 */
function prefix_get_private_data_permissions_check() {
    // Restrict endpoint to only users who have the edit_posts capability.
    if ( ! current_user_can( 'edit_posts' ) ) {
        return new GC_Error( 'rest_forbidden', esc_html__( 'OMG you can not view private data.', 'my-text-domain' ), array( 'status' => 401 ) );
    }

    // This is a black-listing approach. You could alternatively do this via white-listing, by returning false here and changing the permissions check.
    return true;
}

/**
 * This function is where we register our routes for our example endpoint.
 */
function prefix_register_example_routes() {
    // register_rest_route() handles more arguments but we are going to stick to the basics for now.
    register_rest_route( 'my-plugin/v1', '/private-data', array(
        // By using this constant we ensure that when the GC_REST_Server changes our readable endpoints will work as intended.
        'methods'  => GC_REST_Server::READABLE,
        // Here we register our callback. The callback is fired when this endpoint is matched by the GC_REST_Server class.
        'callback' => 'prefix_get_private_data',
        // Here we register our permissions callback. The callback is fired before the main callback to check if the current user can access the endpoint.
        'permission_callback' => 'prefix_get_private_data_permissions_check',
    ) );
}

add_action( 'rest_api_init', 'prefix_register_example_routes' );

如果您在未启用任何身份验证的情况下试用此端点,那么您还将返回错误响应,阻止您看到数据。身份验证是一个巨大的主题,最终将创建本章的一部分,向您展示如何创建自己的身份验证流程。

论点

向端点提出请求时,您可能需要指定额外的参数来更改响应。这些额外的参数可以在注册端点时添加。让我们看看一个如何使用端点参数的示例。


/**
 * This is our callback function that embeds our resource in a GC_REST_Response
 */
function prefix_get_colors( $request ) {
    // In practice this function would fetch the desired data. Here we are just making stuff up.
    $colors = array(
        'blue',
        'blue',
        'red',
        'red',
        'green',
        'green',
    );

    if ( isset( $request['filter'] ) ) {
       $filtered_colors = array();
       foreach ( $colors as $color ) {
           if ( $request['filter'] === $color ) {
               $filtered_colors[] = $color;
           }
       }
       return rest_ensure_response( $filtered_colors );
    }
    return rest_ensure_response( $colors );
}

/**
 * We can use this function to contain our arguments for the example product endpoint.
 */
function prefix_get_color_arguments() {
    $args = array();
    // Here we are registering the schema for the filter argument.
    $args['filter'] = array(
        // description should be a human readable description of the argument.
        'description' => esc_html__( 'The filter parameter is used to filter the collection of colors', 'my-text-domain' ),
        // type specifies the type of data that the argument should be.
        'type'        => 'string',
        // enum specified what values filter can take on.
        'enum'        => array( 'red', 'green', 'blue' ),
    );
    return $args;
}

/**
 * This function is where we register our routes for our example endpoint.
 */
function prefix_register_example_routes() {
    // register_rest_route() handles more arguments but we are going to stick to the basics for now.
    register_rest_route( 'my-colors/v1', '/colors', array(
        // By using this constant we ensure that when the GC_REST_Server changes our readable endpoints will work as intended.
        'methods'  => GC_REST_Server::READABLE,
        // Here we register our callback. The callback is fired when this endpoint is matched by the GC_REST_Server class.
        'callback' => 'prefix_get_colors',
        // Here we register our permissions callback. The callback is fired before the main callback to check if the current user can access the endpoint.
        'args' => prefix_get_color_arguments(),
    ) );
}

add_action( 'rest_api_init', 'prefix_register_example_routes' );

我们现在为这个示例指定了一个filter参数。当我们请求端点时,我们可以将参数指定为查询参数。如果我们向“https://ourawesomesitem.com/my-colors/v1/colors”提出GET请求?filter=blue`,我们将只返回我们收藏中的蓝色。您还可以在请求主体中将这些作为正文参数传递,而不是在查询字符串中传递。要了解查询参数和正文参数之间的区别,您应该阅读HTTP规范。查询参数位于钉在URL上的查询字符串中,正文参数直接嵌入HTTP请求的正文中。

我们为端点创建了一个参数,但我们如何验证参数是否是一个字符串,并判断它是与红色、绿色还是蓝色匹配的值。为此,我们需要为我们的参数指定验证回调。

验证

Validation and sanitization are extremely important for security in the API. The validate callback (in GC 4.6+), fires before the sanitize callback. You should use the validate_callback for your arguments to verify whether the input you are receiving is valid. The sanitize_callback should be used to transform the argument input or clean out unwanted parts out of the argument, before the argument is processed by the main callback.

In the example above, we need to verify that the filter parameter is a string, and it matches the value red, green, or blue. Let’s look at what the code looks like after adding in a validate_callback.


/**
 * This is our callback function that embeds our resource in a GC_REST_Response
 */
function prefix_get_colors( $request ) {
    // In practice this function would fetch more practical data. Here we are just making stuff up.
    $colors = array(
        'blue',
        'blue',
        'red',
        'red',
        'green',
        'green',
    );

    if ( isset( $request['filter'] ) ) {
       $filtered_colors = array();
       foreach ( $colors as $color ) {
           if ( $request['filter'] === $color ) {
               $filtered_colors[] = $color;
           }
       }
       return rest_ensure_response( $filtered_colors );
    }
    return rest_ensure_response( $colors );
}
/**
 * Validate a request argument based on details registered to the route.
 *
 * @param  mixed            $value   Value of the 'filter' argument.
 * @param  GC_REST_Request  $request The current request object.
 * @param  string           $param   Key of the parameter. In this case it is 'filter'.
 * @return GC_Error|boolean
 */
function prefix_filter_arg_validate_callback( $value, $request, $param ) {
    // If the 'filter' argument is not a string return an error.
    if ( ! is_string( $value ) ) {
        return new GC_Error( 'rest_invalid_param', esc_html__( 'The filter argument must be a string.', 'my-text-domain' ), array( 'status' => 400 ) );
    }

    // Get the registered attributes for this endpoint request.
    $attributes = $request->get_attributes();

    // Grab the filter param schema.
    $args = $attributes['args'][ $param ];

    // If the filter param is not a value in our enum then we should return an error as well.
    if ( ! in_array( $value, $args['enum'], true ) ) {
        return new GC_Error( 'rest_invalid_param', sprintf( __( '%s is not one of %s' ), $param, implode( ', ', $args['enum'] ) ), array( 'status' => 400 ) );
    }
}

/**
 * We can use this function to contain our arguments for the example product endpoint.
 */
function prefix_get_color_arguments() {
    $args = array();
    // Here we are registering the schema for the filter argument.
    $args['filter'] = array(
        // description should be a human readable description of the argument.
        'description' => esc_html__( 'The filter parameter is used to filter the collection of colors', 'my-text-domain' ),
        // type specifies the type of data that the argument should be.
        'type'        => 'string',
        // enum specified what values filter can take on.
        'enum'        => array( 'red', 'green', 'blue' ),
        // Here we register the validation callback for the filter argument.
        'validate_callback' => 'prefix_filter_arg_validate_callback',
    );
    return $args;
}

/**
 * This function is where we register our routes for our example endpoint.
 */
function prefix_register_example_routes() {
    // register_rest_route() handles more arguments but we are going to stick to the basics for now.
    register_rest_route( 'my-colors/v1', '/colors', array(
        // By using this constant we ensure that when the GC_REST_Server changes our readable endpoints will work as intended.
        'methods'  => GC_REST_Server::READABLE,
        // Here we register our callback. The callback is fired when this endpoint is matched by the GC_REST_Server class.
        'callback' => 'prefix_get_colors',
        // Here we register our permissions callback. The callback is fired before the main callback to check if the current user can access the endpoint.
        'args' => prefix_get_color_arguments(),
    ) );
}

add_action( 'rest_api_init', 'prefix_register_example_routes' );

卫生

In the above example, we do not need to use a sanitize_callback, because we are restricting input to only values in our enum. If we did not have strict validation and accepted any string as a parameter, we would definitely need to register a sanitize_callback. What if we wanted to update a content field and the user entered something like alert('ZOMG Hacking you');. The field value could potentially be an executable script. To strip out unwanted data or to transform data into a desired format we need to register a sanitize_callback for our arguments. Here is an example of how to use GeChiUI’s sanitize_text_field() for a sanitize callback:

/**
 * This is our callback function that embeds our resource in a GC_REST_Response.
 *
 * The parameter is already sanitized by this point so we can use it without any worries.
 */
function prefix_get_item( $request ) {
    if ( isset( $request['data'] ) ) {
        return rest_ensure_response( $request['data'] );
    }

    return new GC_Error( 'rest_invalid', esc_html__( 'The data parameter is required.', 'my-text-domain' ), array( 'status' => 400 ) );
}

/**
 * Validate a request argument based on details registered to the route.
 *
 * @param  mixed            $value   Value of the 'filter' argument.
 * @param  GC_REST_Request  $request The current request object.
 * @param  string           $param   Key of the parameter. In this case it is 'filter'.
 * @return GC_Error|boolean
 */
function prefix_data_arg_validate_callback( $value, $request, $param ) {
    // If the 'data' argument is not a string return an error.
    if ( ! is_string( $value ) ) {
        return new GC_Error( 'rest_invalid_param', esc_html__( 'The filter argument must be a string.', 'my-text-domain' ), array( 'status' => 400 ) );
    }
}

/**
 * Sanitize a request argument based on details registered to the route.
 *
 * @param  mixed            $value   Value of the 'filter' argument.
 * @param  GC_REST_Request  $request The current request object.
 * @param  string           $param   Key of the parameter. In this case it is 'filter'.
 * @return GC_Error|boolean
 */
function prefix_data_arg_sanitize_callback( $value, $request, $param ) {
    // It is as simple as returning the sanitized value.
    return sanitize_text_field( $value );
}

/**
 * We can use this function to contain our arguments for the example product endpoint.
 */
function prefix_get_data_arguments() {
    $args = array();
    // Here we are registering the schema for the filter argument.
    $args['data'] = array(
        // description should be a human readable description of the argument.
        'description' => esc_html__( 'The data parameter is used to be sanitized and returned in the response.', 'my-text-domain' ),
        // type specifies the type of data that the argument should be.
        'type'        => 'string',
        // Set the argument to be required for the endpoint.
        'required'    => true,
        // We are registering a basic validation callback for the data argument.
        'validate_callback' => 'prefix_data_arg_validate_callback',
        // Here we register the validation callback for the filter argument.
        'sanitize_callback' => 'prefix_data_arg_sanitize_callback',
    );
    return $args;
}

/**
 * This function is where we register our routes for our example endpoint.
 */
function prefix_register_example_routes() {
    // register_rest_route() handles more arguments but we are going to stick to the basics for now.
    register_rest_route( 'my-plugin/v1', '/sanitized-data', array(
        // By using this constant we ensure that when the GC_REST_Server changes our readable endpoints will work as intended.
        'methods'  => GC_REST_Server::READABLE,
        // Here we register our callback. The callback is fired when this endpoint is matched by the GC_REST_Server class.
        'callback' => 'prefix_get_item',
        // Here we register our permissions callback. The callback is fired before the main callback to check if the current user can access the endpoint.
        'args' => prefix_get_data_arguments(),
    ) );
}

add_action( 'rest_api_init', 'prefix_register_example_routes' );

摘要

我们已经介绍了注册GeChiUI REST API端点的基础知识。路由是我们端点生活的URI。端点是回调、方法、args和其他选项的集合。使用register_rest_route()时,每个端点都映射到路由。默认情况下,端点可以支持各种HTTP方法、主回调、权限回调和注册参数。我们可以注册端点,以涵盖我们与GeChiUI交互的任何用例。端点是REST API的核心交互点,但要充分利用这个强大的API,还有很多其他主题需要探索和理解。