Make WordPress Core

Ticket #21602: 21602.2.diff

File 21602.2.diff, 8.8 KB (added by dd32, 9 years ago)

another attempt at supporting mixed-case hostnames in canonical - always rebuild the URL

  • tests/phpunit/includes/testcase-canonical.php

    class WP_Canonical_UnitTestCase extends  
    146146
    147147                foreach ( self::$term_ids as $tid => $tax ) {
    148148                        wp_delete_term( $tid, $tax );
    149149                }
    150150
    151151                self::$author_id = null;
    152152                self::$post_ids = array();
    153153                self::$comment_ids = array();
    154154                self::$term_ids = array();
    155155                self::$terms = array();
    156156        }
    157157
    158158        /**
    159159         * Assert that a given URL is the same a the canonical URL generated by WP.
    160160         *
     161         * This runs the canonical tests with the home_url hostname being forced to uppercase in addition to standard.
     162         *
    161163         * @since 4.1.0
    162164         *
    163165         * @param string $test_url                Raw URL that will be run through redirect_canonical().
    164166         * @param string $expected                Expected string.
    165167         * @param int    $ticket                  Optional. Trac ticket number.
    166168         * @param array  $expected_doing_it_wrong Array of class/function names expected to throw _doing_it_wrong() notices.
    167169         */
    168170        public function assertCanonical( $test_url, $expected, $ticket = 0, $expected_doing_it_wrong = array() ) {
     171                $test_url = home_url( $test_url );
     172
     173                $this->_assertCanonical( $test_url, $expected, $ticket, $expected_doing_it_wrong );
     174
     175                // Re-test with the home_url hostname forced to uppercase.
     176                add_filter( 'home_url', array( $this, 'filter_uppercase_hostname' ) );
     177                $this->_assertCanonical( $test_url, $expected, $ticket, $expected_doing_it_wrong );
     178        }
     179
     180        /**
     181         * Internal helper for `::assertCanonical` for force an uppercase hostname in `home_url()`.
     182         *
     183         * @ignore
     184         */
     185        public function filter_uppercase_hostname( $url ) {
     186                return str_replace( '://' . WP_TESTS_DOMAIN, '://' . strtoupper( WP_TESTS_DOMAIN ), $url );
     187        }
     188
     189        /**
     190         * Internal helper for `::assertCanonical`.
     191         *
     192         * @ignore
     193         */
     194        public function _assertCanonical( $test_url, $expected, $ticket = 0, $expected_doing_it_wrong = array() ) {
    169195                $this->expected_doing_it_wrong = array_merge( $this->expected_doing_it_wrong, (array) $expected_doing_it_wrong );
    170196
    171197                if ( $ticket )
    172198                        $this->knownWPBug( $ticket );
    173199
    174200                $ticket_ref = ($ticket > 0) ? 'Ticket #' . $ticket : null;
    175201
    176202                if ( is_string($expected) )
    177203                        $expected = array('url' => $expected);
    178204                elseif ( is_array($expected) && !isset($expected['url']) && !isset($expected['qv']) )
    179205                        $expected = array( 'qv' => $expected );
    180206
    181207                if ( !isset($expected['url']) && !isset($expected['qv']) )
    182208                        $this->markTestSkipped('No valid expected output was provided');
    183209
    184                 $this->go_to( home_url( $test_url ) );
     210                $this->go_to( $test_url );
    185211
    186212                // Does the redirect match what's expected?
    187                 $can_url = $this->get_canonical( $test_url );
     213                $can_response = redirect_canonical( null, false );
     214                $can_url = $can_response ? $can_response : $test_url;
    188215                $parsed_can_url = parse_url($can_url);
    189216
    190                 // Just test the Path and Query if present
    191                 if ( isset($expected['url']) ) {
    192                         $this->assertEquals( $expected['url'], $parsed_can_url['path'] . (!empty($parsed_can_url['query']) ? '?' . $parsed_can_url['query'] : ''), $ticket_ref );
     217                if ( isset( $expected['url'] ) ) {
     218                        if ( $test_url == $expected['url'] ) {
     219                                $this->assertNull( $can_response, $ticket_ref );
     220                        } else {
     221                                $this->assertEquals( WP_TESTS_DOMAIN, $parsed_can_url['host'] );
     222                                $this->assertEquals( $expected['url'], $parsed_can_url['path'] . (!empty($parsed_can_url['query']) ? '?' . $parsed_can_url['query'] : ''), $ticket_ref );
     223                        }
    193224                }
    194225
    195226                if ( ! isset($expected['qv']) )
    196227                        return;
    197228
    198229                // "make" that the request and check the query is correct
    199230                $this->go_to( $can_url );
    200231
    201232                // Are all query vars accounted for, And correct?
    202233                global $wp;
    203234
    204235                $query_vars = array_diff($wp->query_vars, $wp->extra_query_vars);
    205236                if ( !empty($parsed_can_url['query']) ) {
    206237                        parse_str($parsed_can_url['query'], $_qv);
    207238
    208239                        // $_qv should not contain any elements which are set in $query_vars already (ie. $_GET vars should not be present in the Rewrite)
    209240                        $this->assertEquals( array(), array_intersect( $query_vars, $_qv ), 'Query vars are duplicated from the Rewrite into $_GET; ' . $ticket_ref );
    210241
    211242                        $query_vars = array_merge($query_vars, $_qv);
    212243                }
    213244
    214245                $this->assertEquals( $expected['qv'], $query_vars );
    215246        }
    216247
    217         /**
    218          * Get the canonical URL given a raw URL.
    219          *
    220          * @param string $test_url Should be relative to the site "front", ie /category/uncategorized/
    221          *                         as opposed to http://example.com/category/uncategorized/
    222          * @return $can_url Returns the original $test_url if no canonical can be generated, otherwise returns
    223          *                  the fully-qualified URL as generated by redirect_canonical().
    224          */
    225         public function get_canonical( $test_url ) {
    226                 $test_url = home_url( $test_url );
    227 
    228                 $can_url = redirect_canonical( $test_url, false );
    229                 if ( ! $can_url )
    230                         return $test_url; // No redirect will take place for this request
    231 
    232                 return $can_url;
    233         }
    234248}
  • tests/phpunit/tests/canonical/pageOnFront.php

    class Tests_Canonical_PageOnFront extend 
    3232        function data() {
    3333                /* Format:
    3434                 * [0]: $test_url,
    3535                 * [1]: expected results: Any of the following can be used
    3636                 *      array( 'url': expected redirection location, 'qv': expected query vars to be set via the rewrite AND $_GET );
    3737                 *      array( expected query vars to be set, same as 'qv' above )
    3838                 *      (string) expected redirect location
    3939                 * [3]: (optional) The ticket the test refers to, Can be skipped if unknown.
    4040                 */
    4141                 return array(
    4242                        // Check against an odd redirect
    4343                        array( '/page/2/', '/page/2/' ),
    4444                        array( '/?page=2', '/page/2/' ),
    4545                        array( '/page/1/', '/' ),
    4646                        array( '/?page=1', '/' ),
     47                        array( '/', '/' /*, 21602 */ ),
    4748
    4849                        // The page designated as the front page should redirect to the front of the site
    4950                        array( '/front-page/', '/' ),
    5051                        array( '/front-page/2/', '/page/2/' ),
    5152                        array( '/front-page/?page=2', '/page/2/' ),
    5253                        array( '/blog-page/?paged=2', '/blog-page/page/2/' ),
    5354                 );
    5455        }
    5556}
  • src/wp-includes/canonical.php

    function redirect_canonical( $requested_ 
    433433
    434434        // Strip multiple slashes out of the URL
    435435        if ( strpos($redirect['path'], '//') > -1 )
    436436                $redirect['path'] = preg_replace('|/+|', '/', $redirect['path']);
    437437
    438438        // Always trailing slash the Front Page URL
    439439        if ( trailingslashit( $redirect['path'] ) == trailingslashit( $user_home['path'] ) )
    440440                $redirect['path'] = trailingslashit($redirect['path']);
    441441
    442442        // Ignore differences in host capitalization, as this can lead to infinite redirects
    443443        // Only redirect no-www <=> yes-www
    444444        if ( strtolower($original['host']) == strtolower($redirect['host']) ||
    445445                ( strtolower($original['host']) != 'www.' . strtolower($redirect['host']) && 'www.' . strtolower($original['host']) != strtolower($redirect['host']) ) )
    446446                $redirect['host'] = $original['host'];
    447447
    448         $compare_original = array( $original['host'], $original['path'] );
     448        $redirect_url = $redirect['scheme'] . '://' . $redirect['host'];
     449        if ( !empty($redirect['port']) )
     450                $redirect_url .= ':' . $redirect['port'];
     451        $redirect_url .= $redirect['path'];
     452        if ( !empty($redirect['query']) )
     453                $redirect_url .= '?' . $redirect['query'];
    449454
    450         if ( !empty( $original['port'] ) )
    451                 $compare_original[] = $original['port'];
    452 
    453         if ( !empty( $original['query'] ) )
    454                 $compare_original[] = $original['query'];
    455 
    456         $compare_redirect = array( $redirect['host'], $redirect['path'] );
    457 
    458         if ( !empty( $redirect['port'] ) )
    459                 $compare_redirect[] = $redirect['port'];
    460 
    461         if ( !empty( $redirect['query'] ) )
    462                 $compare_redirect[] = $redirect['query'];
    463 
    464         if ( $compare_original !== $compare_redirect ) {
    465                 $redirect_url = $redirect['scheme'] . '://' . $redirect['host'];
    466                 if ( !empty($redirect['port']) )
    467                         $redirect_url .= ':' . $redirect['port'];
    468                 $redirect_url .= $redirect['path'];
    469                 if ( !empty($redirect['query']) )
    470                         $redirect_url .= '?' . $redirect['query'];
    471         }
    472 
    473         if ( ! $redirect_url || $redirect_url == $requested_url ) {
     455        if ( $redirect_url == $requested_url ) {
    474456                return;
    475457        }
    476458
    477459        // Hex encoded octets are case-insensitive.
    478460        if ( false !== strpos($requested_url, '%') ) {
    479461                if ( !function_exists('lowercase_octets') ) {
    480462                        function lowercase_octets($matches) {
    481463                                return strtolower( $matches[0] );
    482464                        }
    483465                }
    484466                $requested_url = preg_replace_callback('|%[a-fA-F0-9][a-fA-F0-9]|', 'lowercase_octets', $requested_url);
    485467        }
    486468
    487469        /**
    488470         * Filter the canonical redirect URL.