3

I have a rewrite rule that includes a page's URI:

(<page-uri>)/someaction/(\d+)

If the page's URI includes cyrillic characters, such as доска-объявлений, the rule is stored as:

(%d0%b4%d0%be%d1%81%d0%ba%d0%b0-%d0%be%d0%b1%d1%8a%d1%8f%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b9)/someaction/(\d+)

If you go to a page that includes a link to a URL that matches the rule and you click the link, the browser will load the target page without problems and WordPress is able to match the rule with the requested URL.

In Safari (Mac), however, if you copy the URL with Right Click > Copy Link and then try to load the target page by pasting the copied URL into a new tab, you will get a 404 Not Found error.

When you copy URL in Safari, the URL is stored with percent-encoding with the characters used to represent the octets for the cyrillic characters all in uppercase:

%D0%B4%D0%BE%D1%81%D0%BA%D0%B0-%D0%BE%D0%B1%D1%8A%D1%8F%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B9/someaction/1

I haven't been able to reproduce the problem in Chrome or Firefox (both Mac) because, they both store the URL using lowercase characters to represent the octets.

That URL with percent-encoding is what WordPress receives through the $_SERVER['REQUEST_URI'] variable. The problem is that the code responsible for matching requested URI with rewrite rules makes a case sensitive comparison (See parse_request method in /wp-includes/class-wp.php), making it impossible for WordPress to pickup my rule, even though

%D0%B4%D0%BE%D1%81%D0%BA%D0%B0-%D0%BE%D0%B1%D1%8A%D1%8F%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B9

and

%d0%b4%d0%be%d1%81%d0%ba%d0%b0-%d0%be%d0%b1%d1%8a%d1%8f%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b9

represent the same character sequence.

  • Does anyone know how to prevent 404 Not Found errors when browsers sent the request using octets with a different case?
  • Is this something WordPress should support? or should I try to remove page URI's from my rewrite rules to avoid the problem?
1

I ended up following @Kolya Korobochkin advice and added uppercase and lowercase versions of the rewrite rules that include escaped octets.

$regular_page_uri = get_page_uri( $page->ID );

$uppercase_page_uri = preg_replace_callback(
    '/%[0-9a-zA-Z]{2}/',
    create_function( '$x', 'return strtoupper( $x[0] );' ),
    $regular_page_uri
);

The Percent Encode Capital Letter plugin uses a similar approach to convert the octets in every URL to the their uppercase version. However, the plugin is outdated and may not be doing the conversion in all the necessary places. Also, I believe most users of the plugin I'm working on won't have URL with encoded octets, so running preg_replace_callback for all URLs is an unnecessary effort.

Using uppercase characters to represent octets is the recommended way of doing percent-encoding (See RFC3986, Section 2.1). So a better solution would be to get WordPress to update their utf8_uri_encode function to escape octets using them. Most browsers I tested all seem to keep the original case, while others, like Safari, convert it to uppercase, if they get a chance.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.