私がテストしたこと
Wordpressのバージョン:4.9.5
PHPバージョン:7.1.7/7.1.4/7.2.0/7.0.3/5.6.20/5.5.38/5.4.45
Webサーバ:Nginx 1.10.1/Apache 2.4.10
環境/ホスト:フライホイールローカル https://local.getflywheel.com/
PCREライブラリバージョン:8.38 2015-11-23
私はregister_rest_route
を操作しようとしましたが、正規表現の問題に遭遇しました。実行前に正規表現に何らかのフィルタリングがあるようです。
私が作成しようとしている機能は、パーマリンクで投稿を取得することです。基本的に、私は自分の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を通過させやすくすることをクライアントに提案していました。
基本的にwordpressで使える唯一の正規表現は(?P<path>[\w-]+)
と(?P<path>[\d]+)
です。それ以外のものは、 http://www.phpliveregex.com のようなものでテストに成功したとしても、機能しません。
例えば、テスターによると(?P<path>[\S]+)
は動作するはずですが、私がワードプレスから得るすべてはrest_no_route
です
ワードプレスに正規表現を処理させる方法はありますか。それとも少なくともbase64をキャッチすることができる式を許可するようにそれを言って?私はオンラインでいくつかのオプションを見ましたが、おそらく時間の経過とともにwp restの変化が原因でうまくいきません(すべて "regexを使う"と言っても、もっと複雑なregexをフィルタリングするようです)。
編集:拡張例
app/v1/post_by_permalink/(?P<path>[\S-]+)
http://www.phpliveregex.com で動作するのでしょうか
検索文字列は
/wp-json/app/v1/post_by_permalink/dGVzdC90ZXN0
同じ正規表現はワードプレスでは機能せず、(?P<path>[\w-]+)
のみが機能し、上記の例では、特殊文字がないため、両方で機能します。
しかし、この文字列ではそうなりません
/wp-json/app/v1/post_by_permalink/dGVzdC90ZXN0LzM1NzM0Ly0=
それは=
を持っているので、正規表現テスタでは(?P<path>[\S]+)
は動作しますが、ワードプレスでは動作しません。
編集:さらにテストを行う
私はなんとか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_matchの問題ではないようです。少なくともこれで私はwp-restを迂回してこの問題を回避することができますが、これを試みるすべての環境が実際に失敗する原因を実際には何も見つけていません。
より徹底的にテストした結果、以下のものが動作するようになったので、正規表現が失敗する原因となった$wp->request
を含むwp-json
を使用していました。
私はpreg_match( '@^' . $route . '$@i', $path, $matches )
を使うときそれを働かせることができません(つまりwp-restがそれをする方法、$ routeがregister_rest_route
を通して渡されるものである)、そしてこのようにpreg_match
を使うことはregexテスターでサポートされません http:/ /www.phpliveregex.com/ いずれか。それはより多くの質問とそれに続く答えを追加します。
私は興味を持ったので、このベアボーンデモをテストしました:
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;
}
テスト:
与える
{
path: "https://wordpress.stackexchange.com/q/301067/"
}
またテスト済み
それは与えました:
{
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/-"
}
ついにそれを考え出した、そして私は自分自身を非難することしかできない…….
私がテストしていたときは、すべてのプラグインを無効にしていましたが、その間は、(?P<path>[\w-]+)
を含むbase64文字列でテストしながら=
を使用していました。プラグインをアクティブにしていないにもかかわらず再作成したと考える問題として、私はプラグインを排除していました。
犯人はRest Manager
でしたhttps://wordpress.org/plugins/rest-manager/
開発者に知らせるためにサポートチケットを開きました。
非アクティブとして設定したルートを除外するためにrest_pre_dispatch
を利用します。問題は、あなたが入ってルートを変更して設定を保存する必要がある場合です。幸いなことに、それはルートを除外する前にフックを持っていたので修復可能でした、それで私は機能を "修正"して、設定を持たないルートがデフォルトでアクティブになるべきであると仮定できます。
問題を再現するために時間を割いてくれてありがとう、@ mmm、@ birire、@ Otto。
問題の子供を隔離しようとするときにプラグインを無効にします;-)