WordPress 5.6新增REST API批处理框架

WordPress 5.6新增REST API批处理框架

当需要进行大量的写操作时,这对性能优化很有帮助

WordPress5.6 引入了一个框架,该框架可在对服务器的一个请求中进行一系列 REST API 调用。简单地说,当需要进行大量的写操作时,这对性能优化很有帮助。它还可以选择提供基本的并发控制。

WordPress 5.6新增REST API批处理框架

注册

为了在批处理请求中使用,路由必须在注册过程中首先声明对功能的支持。例如下方代码的第 5 行:

register_rest_route( 'my-ns/v1', 'my-route', array(
    'methods'             => WP_REST_Server::CREATABLE,
    'callback'            => 'my_callback',
    'permission_callback' => 'my_permission_callback',
    'allow_batch'         => array( 'v1' => true ),
) );

如果 REST API 路由是使用最佳实践实现的,则声明支持应足以使该路由可通过批处理端点写入。具体来说,这些是要注意的事情:

1、路由必须使用该 WP_REST_Request 对象来获取所有请求数据。换句话说,它不应该访问$_GET,$_POST 或$_SERVER 变量得到参数或头。
2、路线必须返回数据。这可以是一个 WP_REST_Response 对象,一个 WP_Error 对象或任何类型的 JSON 可序列化数据。这意味着路 3、由一定不能直接回显响应和 die()。例如,使用 wp_send_json()或 wp_die()。
路线必须是可重入的。准备好同一批路由被多次调用。

发出请求

要发送批处理,发送一个 POST 请求到 https://yoursite.test/wp-json/batch/v1 使用所需的请求数组。例如,最简单的批处理请求如下所示。

{
  "requests": [
    {
      "path": "/my-ns/v1/route"
    }
  ]
}

请求格式

每个请求都是一个可以接受以下属性的对象。

{
  "method": "PUT",
  "path": "/my-ns/v1/route/1?query=param",
  "headers": {
    "My-Header": "my-value",
    "Multi": [ "v1", "v2" ]
  },
  "body": {
    "project": "Gutenberg"
  }
}

method 是用于请求的 HTTP 方法。如果省略,则使用 POST 方法。path 是要调用的 REST API 路由。可以包含查询参数。此属性是必需的。headers 是标头名称到标头值的对象。如果标头具有多个值,则可以将其作为数组传递。body 是传递给路线的参数。填写 POST 参数类型。

发现最大请求

默认情况下,REST API 在一个批次中最多接受 25 个请求。但是,此值是可过滤的,因此可以根据服务器资源按比例放大或缩小。

function my_prefix_rest_get_max_batch_size() {
    return 50;
}
 
add_filter( 'rest_get_max_batch_size', 'my_prefix_rest_get_max_batch_size' );

因此,强烈建议客户提出请求前要求以发现限制。例如,发出 OPTIONS 请求到 batch/v1 将返回以下响应。

{
  "namespace": "",
  "methods": [ "POST" ],
  "endpoints": [
    {
      "methods": [ "POST" ],
      "args": {
        "validation": {
          "type": "string",
          "enum": [ "require-all-validate", "normal" ],
          "default": "normal",
          "required": false
        },
        "requests": {
          "type": "array",
          "maxItems": 25,
          "items": {
            "type": "object",
            "properties": {
              "method": {
                "type": "string",
                "enum": [ "POST", "PUT", "PATCH", "DELETE" ],
                "default": "POST"
              },
              "path": {
                "type": "string",
                "required": true
              },
              "body": {
                "type": "object",
                "properties": [],
                "additionalProperties": true
              },
              "headers": {
                "type": "object",
                "properties": [],
                "additionalProperties": {
                  "type": [ "string", "array" ],
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "required": true
        }
      }
    }
  ],
  "_links": {
    "self": [
      {
        "href": "http://trunk.test/wp-json/batch/v1"
      }
    ]
  }
}

该限制在 endpoints[0].args.requests.maxItems 属性中指定。

回应格式

批处理端点将以与请求相同的顺序返回 207 状态码和每个请求的响应。例如:

{
  "responses": [
    {
      "body": {
        "id": 1,
        "_links": {
          "self": [
            {
              "href": "http://trunk.test/wp-json/my-ns/v1/route/1"
            }
          ]
        }
      },
      "status": 201,
      "headers": {
        "Location": "http://trunk.test/wp-json/my-n1/v1/route/1",
        "Allow": "GET, POST"
      }
    }
  ]
}

在内部,REST API 信封包括它中之前每个响应 responses 阵列。

验证方式

默认情况下,每个请求都是独立处理的。这意味着批处理响应可以包含一些成功的请求和一些失败的请求。有时希望仅在所有请求均有效的情况下处理批处理。例如,在古腾堡(Gutenberg),我们不想保存某些菜单项,理想情况下将保存所有菜单项,或者不保存任何菜单项。

为此,REST API 允许传递的 validation 模式 require-all-validate。设置此选项后,REST API 将根据 WP_REST_Request::has_valid_params()和 WP_REST_Request::sanitize_params()首先检查每个请求是否有效。如果有任何请求未通过验证,则整个批次都将被拒绝。

在此示例中,发出了两个请求的批处理,第二个请求验证失败。由于 responses 的顺序仍与 requests 的顺序相同,因此用 null 表示请求未通过验证。

{
  "failed": "validation",
  "responses": [
    null,
    {
      "body": {
        "code": "error_code",
        "message": "Invalid request data",
        "data": { "status": 400 }
      },
      "status": 400,
      "headers": {}
    }
  ]
}

注意:使用 require-all-validate 不能保证所有请求都会成功。路由回调仍可能返回错误。

验证回调

在注册路由时,这些 WP_REST_Request 方法使用 validate_callback 和 sanitize_callback 为每个参数指定。在大多数情况下,这将意味着基于架构的验证。

路线内部完成的任何验证(例如在 prepare_item_for_database 方法中)都不会导致批次被拒绝。如果这是一个令人担忧的问题,建议将尽可能多的验证移到 validate_callback 每个单独的参数中。例如,这可以建立在基于现有架构的验证之上。

'post' => array(
    'type'        => 'integer',
    'minimum'     => 1,
    'required'    => true,
    'arg_options' => array(
        'validate_callback' => function ( $value, $request, $param ) {
            $valid = rest_validate_request_arg( $value, $request, $param );
 
            if ( is_wp_error( $valid ) ) {
                return $valid;
            }
 
            if ( ! get_post( $value ) || ! current_user_can( 'read_post', $value ) ) {
                return new WP_Error( 'invalid_post', __( 'That post does not exist.' ) );
            }
 
            return true;
        }
    )
)

有时在执行验证时,需要请求的完整上下文。通常,此验证将在 prepare_item_for_database 中完成,但 WordPress 5.6 引入了替代方法。注册路线时,现在可以指定 validate_callback 顶层。它将接收完整的 WP_REST_Request 对象,并可以返回 WP_Error 实例或 false。如果参数级验证未成功,则不会执行该回调。

register_rest_route( 'my-ns/v1', 'route', array(
    'callback'            => '__return_empty_array',
    'permission_callback' => '__return_true',
    'validate_callback'   => function( $request ) {
        if ( $request['pass1'] !== $request['pass2'] ) {
            return new WP_Error(
                'passwords_must_match',
                __( 'Passwords must match.' ),
                array( 'status' => 400 )
            );
        }
 
        return true;
    }
) );

注意:请求验证在权限检查之前进行。在考虑是否将逻辑移至 validate_callback 时要牢记这一点。

局限性

当前没有内置路由允许批处理。这将在将来的版本中添加,最有可能立即从 WordPress 5.7 开始。
不支持 GET 请求。相反,鼓励开发人员暂时使用链接和嵌入或利用并行请求。

分享到 :
相关推荐

发表评论

登录... 后才能评论