适用于Base64或备用的REGISTER_REST_ROUTE正则表达式选项

时间:2018-04-17 作者:Jordan Ramstad

What I tested

Wordpress Version: 4.9.5

PHP Version: 7.1.7/7.1.4/7.2.0/7.0.3/5.6.20/5.5.38/5.4.45

Web Server: Nginx 1.10.1/Apache 2.4.10

Environment/Host: 飞轮本地https://local.getflywheel.com/

PCRE Library Version: 8.38 2015-11-23

我一直在努力register_rest_route 但遇到了regex问题。似乎在执行regex之前对其进行了一些过滤。

我试图创建的功能是通过permalink获取帖子。基本上,我有一个客户端,它的url结构类似于wordpress,因此它希望将永久链接传递给wordpress,以便我可以获取帖子数据

register_rest_route( $this->namespace, \'/post_by_permalink/(?P<path>[\\w-]+)\', array(
   \'methods\'             => WP_REST_Server::READABLE,
   \'callback\'            => array( $this, \'postByPermalink\' ),
   \'permission_callback\' => array( $this, \'permissions\' ),
   \'show_in_rest\' => true
));
这是我正在使用的函数,它在某些情况下有效。然而,这仅仅是因为工作的角色不会产生任何特殊的角色。

目前,我的计划是在客户端将永久链接转换为base64,以便更容易通过url,但如果它们有效,我愿意接受建议(我只想到base64,因为urlencode更像是一场噩梦)。

基本上,wordpress中唯一有效的正则表达式似乎是(?P<path>[\\w-]+)(?P<path>[\\d]+). 其他任何东西都不起作用,即使它在以下方面测试成功http://www.phpliveregex.com

例如,根据测试仪(?P<path>[\\S]+) 应该有用,但我从wordpress得到的只是rest_no_route

有没有办法让wordpress正常处理regex?或者至少告诉它允许一个可以捕获base64的表达式?我在网上看到了一些选项,但没有任何效果,可能是由于wp rest随时间的变化(都说“只使用regex”,但它似乎过滤了更复杂的regex)

https://local.getflywheel.com/一七是什么会起作用http://www.phpliveregex.com

搜索字符串为

/wp-json/app/v1/post_by_permalink/dGVzdC90ZXN0

同样的正则表达式仅在wordpress中不起作用(?P<path>[\\w-]+) 将起作用,对于上面的示例,由于没有特殊字符,因此在这两种情况下都会起作用。

但是,对于此字符串,它不会

/wp-json/app/v1/post_by_permalink/dGVzdC90ZXN0LzM1NzM0Ly0=

因为它有= 所以虽然在regex测试程序中(?P<path>[\\S]+) 工作,但在wordpress中不工作。

Edit: further testing

我设法抬头看了看rest_pre_dispatch 并让它在检查路由之前捕获请求。

add_filter(\'rest_pre_dispatch\', \'filter_request\');
function filter_request($result) {
    global $wp;

    //print_r($wp->request); die;
    preg_match("/app\\/v1\\/post_by_permalink\\/(?P<path>[\\S]+)/", $wp->request, $output);
    print_r($output); die;
    return $result;
}
能够正确设置路径,因此它似乎不是preg\\u匹配问题。至少有了这个,我可以绕过wp rest,绕过这个问题,但我仍然没有找到导致我尝试的每个环境都失败的真正原因,而且没有其他人可以重新创建它。。。。。

经过更彻底的测试,我得到了下面的工作,我使用$wp->request 包括witchwp-json 这导致正则表达式失败

虽然当我使用preg_match( \'@^\' . $route . \'$@i\', $path, $matches ) 我无法让它工作(这就是wp rest的工作方式,$路由是通过的register_rest_route), 和使用preg_match regex tester不支持这种方式http://www.phpliveregex.com/ 任何一个它添加了更多的问题,然后是答案。

2 个回复
最合适的回答,由SO网友:birgire 整理而成

我很好奇,所以我测试了这个裸体演示:

add_action( \'rest_api_init\', function () {
    register_rest_route( \'wpse/v1\', \'/post_by_permalink/(?P<path>[\\S]+)\', [
        \'methods\'      => WP_REST_Server::READABLE,
        \'callback\'     => \'wpse_callback\',
        \'show_in_rest\' => true
    ] );
});

function wpse_callback( $request ) {
    $data = [ \'path\' => base64_decode( $request[\'path\'] ) ];
    return $data;
}
测试:

https://example.com/wp-json/wpse/v1/post_by_permalink/aHR0cHM6Ly93b3JkcHJlc3Muc3RhY2tleGNoYW5nZS5jb20vcS8zMDEwNjcv

给予

{
   path: "https://wordpress.stackexchange.com/q/301067/"
}
也进行了测试

https://example.com/wp-json/wpse/v1/post_by_permalink/aHR0cHM6Ly93b3JkcHJlc3Muc3RhY2tleGNoYW5nZS5jb20vcXVlc3Rpb25zLzMwMTA2Ny9yZWdpc3Rlci1yZXN0LXJvdXRlLXJlZ2V4LW9wdGlvbi1mb3ItYmFzZTY0LW9yLWFsdGVybmF0ZS8zMDEwNzY=

这给了:

{
path: "https://wordpress.stackexchange.com/questions/301067/register-rest-route-regex-option-for-base64-or-alternate/301076"
}
进一步测试:

https://example.com/wp-json/wpse/v1/post_by_permalink/dGVzdC90ZXN0LzM1NzM0Ly0=

带输出:

{
path: "test/test/35734/-"
}

SO网友:Jordan Ramstad

终于明白了,我只能怪自己。。。。

在测试时,我禁用了所有插件,但在这段时间里,我让它使用(?P<path>[\\w-]+) 使用包含=. 在这段时间里,我一直把插件作为一个问题来消除,认为尽管没有激活的插件,但我还是重新创建了插件。

罪魁祸首是Rest Manager https://wordpress.org/plugins/rest-manager/

我已经打开了一张支持票,让开发人员知道。

它利用rest_pre_dispatch 要筛选出设置为非活动的路由,问题是如果更改路由,则需要进入并重新保存配置。谢天谢地,它是可以修复的,因为它在过滤掉路由之前有一个挂钩,所以我可以“修复”功能,并假设没有配置的路由应该默认为活动的。

感谢@mmm、@birire和@Otto花时间试图重现这一问题。

尝试隔离问题时禁用插件孩子;-)

结束