• Resolved bof1946

    (@bof1946)


    I’m trying to implement a custom route for the REST API which will take a member’s surname and membership number and validate if they are really a member. My custom endpoint uses a path expression and ends …/status/(?P<surname>[\w-]+)/(?P<memno>[\w-]{1,7}). This worked well until I tested it with the name O’Malley. The path expression didn’t match the apostrophe (single quote) so I got a “no route was found” response.
    So I changed the path expression to (?P<surname>[\w’-]+)/(?P<memno>[\w-]{1,7}) but this didn’t work, I tried a number of variations on the expression without success. Digging into the code I found that it was because WordPress had added a backslash in front of the apostrophe in the path from the URL. I could get it to work if I changed the expression to (?P<surname>[\w\\’-]+)/(?P<memno>[\w-]{1,7})a, but this matches any number of backslashes in the name, which feels a bit of a hack to me. So then I wondered if I could filter the path and remove the backslash, but the best I could come up with was this:

    add_filter( 'rest_pre_dispatch', array( $this, 'rest_pre_dispatch' ), 10, 3 );
    public function rest_pre_dispatch( $result, $instance, $request ) {
    $route = $request->get_route();
    // is the request for our namespace?
    if ( preg_match( '/musa-member-display/', $route ) ) {
    $request->set_route( wp_unslash( $route ) );
    }
    return $result;
    }

    This now works, but there’s a further complication. I’m using the Disable REST API plugin so that only logged in users can access the API, but I need to tell it to whitelist my custom route and the single quote in the expression corrupts the plugin’s settings page. So I can’t add my route to the whitelist.
    I have the feeling that my original approach is wrong. Is there any better way I could define my custom route to achieve what I need?
    (I’ve done a number of searches to see if anyone else has had this problem and solved it, but without any luck).

Viewing 3 replies - 1 through 3 (of 3 total)
  • Moderator bcworkz

    (@bcworkz)

    Using literal name strings in URLs is bad idea. You’ll also have trouble with names using diacritics or non-Latin alphabet. Names in URLs should be processed like post slugs — all lowercase Latin chars, no diacritics, only - punctuation allowed. But you cannot use such slugs to match literal name strings in the DB, so the member’s slug would need to be saved along with their literal name string.

    Why do you need the name in the endpoint if their member number is also used? If you want to validate the provided name to the number, pass the name as an URL encoded query string.

    Thread Starter bof1946

    (@bof1946)

    Thanks very much, that’s exactly the sort of inspiration I was hoping for. This is the first time I’ve done anything with the REST api, and I’m still feeling my way reading tutorials and studying the code for other plugins with custom endpoints. It hadn’t occurred to me to use a query string, I can’t remember seeing any examples, but I could have missed their significance. I wasn’t happy about putting the name in the URL for the reasons you point out, but it does seem to work, probably more luck than judgement.

    I’ll rewrite my code.

    I need the name because anyone could guess a membership number, but the name/number combination is unique.

    Thread Starter bof1946

    (@bof1946)

    This was so easy I’m embarrassed to confess, but I only had to change the URL of the route and append the data in a query string instead – a one line change – and everything else just worked. For the benefit of any other dimwits like me, WP_REST_Request::get_params returns all parameters, whether they come from a path expression, the query string, or $_POST.

Viewing 3 replies - 1 through 3 (of 3 total)
  • The topic ‘REST route with single quote in path expression’ is closed to new replies.