Make WordPress Core

Opened 6 months ago

Last modified 3 hours ago

#62163 new defect (bug)

WP_REST_Request::get_params() includes unregistered args including rest_route when not using pretty permalinks

Reported by: westonruter's profile westonruter Owned by:
Milestone: 6.8 Priority: low
Severity: normal Version: 4.4
Component: REST API Keywords: good-first-bug has-patch changes-requested
Focuses: Cc:

Description

I discovered that calling WP_REST_Request::get_params() includes all of the GET, POST, URL, etc parameters even when they have not been registered as args via register_rest_route(). Perhaps this is intentional. But what certainly isn't intentional is that when pretty permalinks aren't enabled (i.e. when plain permalinks are enabled), REST API calls are made using a URL like:

/index.php?rest_route=/wp/v2/posts

And the presence of the rest_route query parameter in the URL is resulting in a rest_route key being returned by WP_REST_Request::get_params().

My expectation was that WP_REST_Request::get_params() would only return validated and sanitized parameters which I had registered when creating the endpoint. Perhaps this would be too restrictive and would be too much of a backwards-compatibility break as some plugin code may be taking advantage of accessing parameters that aren't explicitly registered.

In any case, when pretty permalinks aren't enabled, the rest_route query parameter should probably be omitted from the collected params, and/or when registering an arg there should be a warning if someone attempts to use the "rest_route" name.

Change History (9)

#1 @TimothyBlynJacobs
6 months ago

  • Keywords good-first-bug added
  • Milestone changed from Awaiting Review to 6.8

Yeah, it is intentional behavior that unregistered parameters make it through. I’d love to introduce a strict arguments flag that would have the behavior you describe. Because you’re exactly right, it isn’t a requirement that folks register their parameters ahead of time and I’ve seen plenty of examples where people don’t.

For the plain permalinks issue, I agree. We should probably always drop rest_route when building the request from globals I think.

This ticket was mentioned in PR #7503 on WordPress/wordpress-develop by @debarghyabanerjee.


6 months ago
#2

  • Keywords has-patch added

Trac Ticket: Core-62163

## Overview

  • This Pull Request introduces a modification to the get_params() method within the WordPress REST API. The change ensures that the rest_route parameter is excluded from the parameters returned when pretty permalinks are not enabled.

## Changes Made

  • Exclusion of rest_route:
  • The get_params() method has been updated to check the permalink settings. If pretty permalinks are disabled, the method will omit the rest_route parameter from the returned array of parameters. This adjustment helps prevent confusion and potential issues for developers relying on the REST API.
  • Motivation: When pretty permalinks are not enabled, the presence of the rest_route parameter can lead to unexpected behavior. This change aims to streamline the parameter handling in the REST API, providing a clearer and more predictable response.

## Impact

  • This update enhances the developer experience by ensuring that the parameters returned by get_params() are relevant and do not include unnecessary values, thereby reducing potential confusion and errors.

#3 @dilip2615
8 weeks ago

Hello @westonruter according to my thoughts, the WP_REST_Request::get_params() function includes all query parameters, including rest_route when pretty permalinks are disabled. To prevent this, you can manually unset the rest_route parameter before processing the request.

<?php
add_filter('rest_request_before_callbacks', function($response, $handler, $request) {
    if ($request->has_param('rest_route')) {
        $request->set_param('rest_route', null);
    }
    return $response;
}, 10, 3);

This filter ensures the rest_route parameter is removed, preventing unintended behavior while maintaining backward compatibility.

Last edited 8 weeks ago by westonruter (previous) (diff)

#4 follow-up: @westonruter
8 weeks ago

If you do really want to get all of the query parameters then I think you should rather just use $_GET. It seems to me that WP_REST_Request::get_params() should be limited to just those passed to the REST API.

#5 in reply to: ↑ 4 @dilip2615
8 weeks ago

Replying to westonruter: yes I agree with your point. depends on our needs as per the core coding point view.

If you do really want to get all of the query parameters then I think you should rather just use $_GET. It seems to me that WP_REST_Request::get_params() should be limited to just those passed to the REST API.

This ticket was mentioned in Slack in #core by audrasjb. View the logs.


9 days ago

@audrasjb commented on PR #7503:


9 days ago
#7

The logic in the PR looks good to me. Pinging @TimothyBJacobs or @spacedmonkey for a quick review when possible.

#8 @sheulyshila
7 days ago

  • Keywords changes-requested added

#9 @oglekler
3 hours ago

@sheulyshila Can you elaborate on what change is needed? Thank you!

Note: See TracTickets for help on using tickets.