[wp-trac] [WordPress Trac] #51733: redirect_canonical unneeded redirect

WordPress Trac noreply at wordpress.org
Mon Nov 9 18:27:18 UTC 2020


#51733: redirect_canonical unneeded redirect
--------------------------+-----------------------------
 Reporter:  aidvu         |      Owner:  (none)
     Type:  defect (bug)  |     Status:  new
 Priority:  normal        |  Milestone:  Awaiting Review
Component:  Canonical     |    Version:  3.3
 Severity:  minor         |   Keywords:  needs-patch
  Focuses:                |
--------------------------+-----------------------------
 Recently caught an unneeded redirect in `redirect_canonical`. Started
 caching responses, and ended in a redirect loop.

 tl;dr
 Per [https://tools.ietf.org/html/rfc3986#section-2.2 RFC3986], `+` is a
 reserved character, and we should use `%20` to encode a space in URLs
 (percent encoding).
 Per [https://tools.ietf.org/html/rfc1866#section-8.2.2 RFC1866], encode
 query args as `application/x-www-form-urlencoded` in which case a space is
 encoded as a `+`.

 Posting here to discuss whether we want to fix this in core, or simply
 leave it as is.

 To reproduce:
 - Use any `twenty{year}` theme
 - Customize homepage
 - Select `A static page`
 - Visit homepage with query args, e.g.
 https://vubuesinessplantest.help/?test=a+b+c
 - A redirect occurs to https://vubuesinessplantest.help/?test=a%20b%20c

 Considering we're using `parse_str()` to parse query variables, and it
 correctly parses both RFCs I'd argue we shouldn't redirect in the case
 when query args are the same.

 Here's a filter I've written to skip redirects in this case:
 {{{#!php
 <?php
 // Don't redirect if we're only re-encoding query params
 add_filter(
         'redirect_canonical',
         function ( $redirect_url, $requested_url ) {
                 $parsed_redirect = parse_url( $redirect_url );
                 $parsed_requested = parse_url( $requested_url );
                 // Scheme changed, do redirect
                 if ( $parsed_requested['scheme'] !==
 $parsed_redirect['scheme'] ) {
                         return $redirect_url;
                 }
                 // Host changed, do redirect
                 if ( $parsed_requested['host'] !==
 $parsed_redirect['host'] ) {
                         return $redirect_url;
                 }
                 // Path changed, do redirect
                 if ( $parsed_requested['path'] !==
 $parsed_redirect['path'] ) {
                         return $redirect_url;
                 }
                 // Parse query args
                 parse_str( $parsed_redirect['query'], $query_redirect );
                 parse_str( $parsed_requested['query'], $query_request );
                 // Sort by keys, if the order changed
                 ksort( $query_redirect );
                 ksort( $query_request );
                 // If parsed query args are the same, skip redirect
                 if ( $query_redirect === $query_request ) {
                         return false;
                 }
                 // Otherwise, do redirect
                 return $redirect_url;
         },
         10,
         2
 );
 }}}

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/51733>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list