Wordpress rest_pre_serve_request 产生 PHP header 警告

Wordpress rest_pre_serve_request produces PHP header warnings

我目前正在开发我的第一个 Wordpress 插件,我遇到了一个我不太明白的 REST API 问题。也许有比我更好的方法,我还不知道,所以我很高兴能得到任何帮助!

这是交易:

我正在创建一个 API,它应该提供来自 Wordpress mysql 数据库的缓存数据。我正在将网络资源中的数据(url、mime-type、[...])存储到我想要提供服务的数据库中。要缓存的资源在如下所示的策略文件中定义:

policy.json

{
    "files":
    [
        {
            "resource_url": "https://example.come/assets/images/image.png",
            (...)
        },
        (...)
    ]
}

由于文件数量是动态的,因此我的服务需要根据策略文件规定的任何自定义路由进行调整。例如。在上述情况下,它应该通过我的 Wordpress 站点提供资源,该站点最初来自 example.com。因此,如果 https://my-wordpress-site.com/wp-json/example/v1/assets/images/image.png 被请求,来自 https://example.come/assets/images/image.png 的缓存文件应该被提供。

我的 REST API 看起来像这样:

mypl/rest_api.php

<?php

function custom_resource_endpoint() {
    return new WP_REST_Response("The requested resource could not be found.", 400);    
}


function rpc_through_endpoint( $request_data ) {

    $route = $request_data->get_route();
    $header = $request_data->get_headers();
    $data = $request_data->get_body();

    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, "https://example.com" . str_replace('example/v1/', '', $route));
    curl_setopt($curl, CURLOPT_POST, 1);
    curl_setopt($curl, CURLOPT_HEADER, 0);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 0);
    curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 3);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
    curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-type: application/octet-stream'));
            
41  $response = curl_exec($curl);
    curl_close($curl);
   
    return new WP_REST_Response($response, 200);
}


function register_custom_routes() {
    $rest_prefix = 'example/v1';

    register_rest_route($rest_prefix, '/rpc', array(
        'methods' => WP_REST_Server::CREATABLE,
        'callback' => 'rpc_through_endpoint'
    ));

    register_rest_route($rest_prefix, '(/w)', array(
        'methods' => WP_REST_Server::READABLE,
        'callback' => 'custom_resource_endpoint'
    ));    
}

add_action('rest_api_init', 'register_custom_routes');


// Interceptor.

function serve_static_resources($served, $result, $request, $server) {

    $route = $request->get_route();

    if (ends_with($route, 'rpc')) {
        $served = false;
    } else {

        $file_uri = str_replace('/example/v1/', 'https://example/', $route);
        
        if ($file_uri != null) {
            $resource = checkLatestResourceByUri($file_uri);
            if(count($resource) > 0) {
                $vars=get_object_vars($resource[0]);
                http_response_code(200);
                header( 'Content-Type: ' . $vars['resource_mime_type'], true );
92              echo $vars['resource_data'];
                $served = true;
            }
        }
    }

    return $served;
}

add_filter('rest_pre_serve_request', 'serve_static_resources', 10, 4);

我的想法是,我创建了一个 READABLE (GET) rest 路由,它接受 rest API 上的所有请求。一旦请求进入,它就会被 rest_pre_serve_request 过滤器拦截,以检查数据库是否缓存了请求的文件,如果缓存了则提供它。这是我的方法:

根据文档,我可以简单地回显来自过滤器的数据和 return truefalse 以指示请求是否已被处理。但就我而言,我还必须为响应添加其他数据,例如 Status-CodeContent-Type,以便客户端能够正确处理它。 现在是关键。逻辑完全按照我想要的方式工作,它按照预期的方式处理请求,但我仍然得到了经典的 headers 已经从 PHP 发送了警告,看起来像这样:

[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:92) in /var/www/html/wp-includes/rest-api.php on line 596
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:92) in /var/www/html/wp-includes/rest-api.php on line 597
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:92) in /var/www/html/wp-includes/rest-api.php on line 596
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:92) in /var/www/html/wp-includes/rest-api.php on line 596
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:92) in /var/www/html/wp-includes/rest-api.php on line 598
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:92) in /var/www/html/wp-includes/rest-api.php on line 597
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:92) in /var/www/html/wp-includes/rest-api.php on line 597
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:92) in /var/www/html/wp-includes/rest-api.php on line 599
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:92) in /var/www/html/wp-includes/rest-api.php on line 598
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:92) in /var/www/html/wp-includes/rest-api.php on line 598
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:92) in /var/www/html/wp-includes/rest-api.php on line 599
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:92) in /var/www/html/wp-includes/rest-api.php on line 599

[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:41) in /var/www/html/wp-includes/rest-api/class-wp-rest-server.php on line 1337
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:41) in /var/www/html/wp-includes/rest-api.php on line 596
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:41) in /var/www/html/wp-includes/rest-api.php on line 597
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:41) in /var/www/html/wp-includes/rest-api.php on line 598
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:41) in /var/www/html/wp-includes/rest-api.php on line 599

[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:92) in /var/www/html/wp-includes/rest-api.php on line 596
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:92) in /var/www/html/wp-includes/rest-api.php on line 596
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:92) in /var/www/html/wp-includes/rest-api.php on line 596
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:92) in /var/www/html/wp-includes/rest-api.php on line 597
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:92) in /var/www/html/wp-includes/rest-api.php on line 597
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:92) in /var/www/html/wp-includes/rest-api.php on line 597
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:92) in /var/www/html/wp-includes/rest-api.php on line 598
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:92) in /var/www/html/wp-includes/rest-api.php on line 598
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:92) in /var/www/html/wp-includes/rest-api.php on line 598
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:92) in /var/www/html/wp-includes/rest-api.php on line 599
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:92) in /var/www/html/wp-includes/rest-api.php on line 599
[06-Aug-2020 10:47:03 UTC] PHP Warning:  Cannot modify header information - headers already sent by (output started at /var/www/html/wp-content/plugins/mypl/rest_api.php:92) in /var/www/html/wp-includes/rest-api.php on line 599

第41行和第92行在上面的代码中标出。

那么,我在这里做的有什么根本性的错误吗?或者也许有人知道如何正确处理那些预先上菜的东西?

感谢您的帮助!!

我找到了解决问题的方法。

Wordpress 在 .../wp-includes/rest-api.php on line 596 中有一个默认的 CORS 过滤器,在此过滤器中,Wordpress 设置默认 headers 以发送“Cross-Origin 资源共享 headers 与 API要求”。 (https://github.com/WordPress/wordpress-develop/blob/5.4/src/wp-includes/rest-api.php#L596) 此过滤器以默认优先级 (10) 添加到 REST API 因此我只需要为我的自定义过滤器提供更高的优先级,以便在默认 WP CORS 过滤器之后执行它。

add_filter('rest_pre_serve_request', 'serve_static_resources', 11, 4);

并且警告消失了。