Ce que j'ai testé
Version Wordpress : 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
Serveur Web : Nginx 1.10.1/Apache 2.4.10
Environment/Host : Flywheel local https://local.getflywheel.com/
Version de la bibliothèque PCRE : 8.38 2015-11-23
J'ai essayé de travailler avec register_rest_route
mais je rencontrais des problèmes de regex. Il semble qu'il y ait un filtrage sur la regex avant son exécution.
La fonction que j'essaie de créer est de saisir un message par le lien permanent. Fondamentalement, j'ai un client qui structure son URL similaire à wordpress afin qu'il souhaite passer le lien permanent à wordpress afin que je puisse obtenir les données de publication
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
));
C’est la fonction que j’utilise et qui fonctionne dans certains cas. Cependant, c'est uniquement parce que ceux qui fonctionnent ne génèrent aucun caractère spécial.
À l’heure actuelle, mon plan consistait à convertir le permalien en base64 afin de faciliter le passage de l’URL, bien que je sois ouvert aux suggestions s’ils fonctionnent (je n’ai pensé qu’à base64, car urlencode était encore plus cauchemardesque).
Fondamentalement, le seul regex qui fonctionne dans wordpress semble être (?P<path>[\w-]+)
et (?P<path>[\d]+)
. Tout le reste ne fonctionne pas, même s'il a réussi à le tester dans quelque chose comme http://www.phpliveregex.com
Par exemple, selon le testeur (?P<path>[\S]+)
devrait fonctionner, mais tout ce que je reçois de wordpress est rest_no_route
Y a-t-il un moyen pour que WordPress gère normalement regex? Ou au moins lui dire de permettre une expression qui pourrait attraper base64? J'ai vu quelques options en ligne, mais aucune ne fonctionne, probablement en raison de changements dans le repos de wp au fil du temps (tous disent "utilisez simplement regex", mais cela semble filtrer les regex plus complexes)
EDIT: exemple étendu
app/v1/post_by_permalink/(?P<path>[\S-]+)
Est ce qui fonctionnera dans http://www.phpliveregex.com
La chaîne de recherche étant
/wp-json/app/v1/post_by_permalink/dGVzdC90ZXN0
Cette même expression rationnelle ne fonctionnera pas dans wordpress, seul (?P<path>[\w-]+)
fonctionnera. Pour l'exemple ci-dessus, cela fonctionnera également dans les deux cas, car il n'y a pas de caractères spéciaux.
Toutefois, pour cette chaîne, il ne sera pas
/wp-json/app/v1/post_by_permalink/dGVzdC90ZXN0LzM1NzM0Ly0=
Puisqu'il a un =
Ainsi, bien que dans le testeur de regex (?P<path>[\S]+)
fonctionne, cela ne fonctionnera pas dans wordpress.
Edit: autres tests
J'ai réussi à rechercher rest_pre_dispatch
et à le faire fonctionner pour intercepter la demande avant qu'il ne vérifie les itinéraires.
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;
}
Est capable de définir le chemin correctement, donc cela ne semble pas être un problème avec preg_match. Au moins, avec cela, je peux contourner wp-rest et contourner ce problème, mais je n’ai toujours pas trouvé la cause réelle de tous les environnements dans lesquels j’essayais d’échouer, et pourtant personne d’autre ne peut le recréer .....
Après des tests plus approfondis, le fonctionnement ci-dessous a fonctionné. J'utilisais $wp->request
qui incluait wp-json
et qui causait l'échec de la regex.
Cependant, lorsque j'utilise preg_match( '@^' . $route . '$@i', $path, $matches )
, je ne parviens pas à le faire fonctionner (c’est ainsi que wp-rest le fait, $ route étant ce qui est passé par register_rest_route
), et utiliser preg_match
de cette manière n’est pas pris en charge dans le testeur de regex http: //. www.phpliveregex.com/ soit. Il ajoute plus de questions puis de réponses.
Je suis devenu curieux, alors j'ai testé cette démo barebone:
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;
}
Essai:
donne
{
path: "https://wordpress.stackexchange.com/q/301067/"
}
Testé aussi
cela a donné:
{
path: "https://wordpress.stackexchange.com/questions/301067/register-rest-route-regex-option-for-base64-or-alternate/301076"
}
Testé plus loin:
https://example.com/wp-json/wpse/v1/post_by_permalink/dGVzdC90ZXN0LzM1NzM0Ly0=
avec sortie:
{
path: "test/test/35734/-"
}
Finalement, j'ai compris, et je ne peux que m'en vouloir.
Lors de mes tests, j'avais désactivé tous les plugins, mais pendant ce temps, je l'avais laissé en utilisant (?P<path>[\w-]+)
lors du test avec une chaîne base64 contenant un =
. Pendant tout ce temps, j'avais éliminé les plugins car je pensais l'avoir recréé malgré l'absence de plugins actifs.
Le coupable était Rest Manager
https://wordpress.org/plugins/rest-manager/
J'ai ouvert un ticket de support pour informer le développeur.
Il utilise rest_pre_dispatch
pour filtrer les routes que vous avez définies comme étant inactives. Le problème est que si vous modifiez les routes, vous devez entrer et réenregistrer la configuration. Heureusement, il était réparable car il contenait un crochet avant de filtrer les routes. Je pouvais donc "réparer" la fonction et supposer que les routes sans configuration devaient être activées par défaut.
Merci à @mmm, @birire et @Otto d'avoir pris le temps d'essayer de recréer le problème.
Désactiver les plugins lorsque vous essayez d'isoler un problème enfants ;-)