Кириллические символы в правилах перезаписи вызывают ошибки 404 Not Found

20 янв. 2016 г., 17:46:18
Просмотры: 958
Голосов: 3

У меня есть правило перезаписи, которое включает URI страницы:

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

Если URI страницы содержит кириллические символы, например доска-объявлений, правило сохраняется как:

(%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+)

Если перейти на страницу, содержащую ссылку на URL, соответствующий правилу, и кликнуть по этой ссылке, браузер загрузит целевую страницу без проблем, и WordPress сможет сопоставить правило с запрошенным URL.

Однако в Safari (Mac), если скопировать URL через Правой Кнопкой > Копировать Ссылку и затем попытаться загрузить целевую страницу, вставив скопированный URL в новую вкладку, вы получите ошибку 404 Not Found.

При копировании URL в Safari, URL сохраняется с процентным кодированием, где символы, представляющие октеты для кириллических символов, записываются в верхнем регистре:

%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

Мне не удалось воспроизвести эту проблему в Chrome или Firefox (оба на Mac), потому что они сохраняют URL, используя символы в нижнем регистре для представления октетов.

Этот URL с процентным кодированием передается в WordPress через переменную $_SERVER['REQUEST_URI']. Проблема в том, что код, отвечающий за сопоставление запрошенного URI с правилами перезаписи, выполняет сравнение с учетом регистра (см. метод parse_request в /wp-includes/class-wp.php), из-за чего WordPress не может распознать мое правило, несмотря на то что

%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

и

%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

представляют одну и ту же последовательность символов.

  • Кто-нибудь знает, как предотвратить ошибки 404 Not Found, когда браузеры отправляют запрос с октетами в разном регистре?
  • Должен ли WordPress поддерживать это? Или мне стоит попытаться исключить URI страниц из моих правил перезаписи, чтобы избежать проблемы?
3
Комментарии

А если самому сконвертировать доска-объявлений в URI, и затем добавить правило сначала для нижнего регистра, а потом перевести этот же URI в верхний регистр и добавить правило еще раз?

Kolya Korobochkin Kolya Korobochkin
21 янв. 2016 г. 01:59:21

Полезные ссылки: http://serverfault.com/questions/308415/wordpress-escaped-encoded-hex-url-case-sensitive-problem и плагин для решения проблемы https://wordpress.org/plugins/percent-encode-capital-letter/

Kolya Korobochkin Kolya Korobochkin
21 янв. 2016 г. 02:08:18

Также еще одна http://wordpress.stackexchange.com/questions/27779/using-redirection-plugin-to-pass-urls-as-lowercase-to-wordpress

Kolya Korobochkin Kolya Korobochkin
21 янв. 2016 г. 02:08:59
Все ответы на вопрос 1
0

В итоге я последовал совету @Коли Коробочкина и добавил правила перезаписи в верхнем и нижнем регистрах, включающие экранированные октеты.

$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
);

Плагин Percent Encode Capital Letter использует аналогичный подход для преобразования октетов в каждом URL в их версию в верхнем регистре. Однако плагин устарел и может не выполнять преобразование во всех необходимых местах. Кроме того, я считаю, что большинство пользователей плагина, над которым я работаю, не имеют URL с закодированными октетами, поэтому выполнение preg_replace_callback для всех URL — это излишняя нагрузка.

Использование символов в верхнем регистре для представления октетов является рекомендованным способом процентного кодирования (см. RFC3986, раздел 2.1). Поэтому лучшее решение — заставить WordPress обновить их функцию utf8_uri_encode, чтобы экранировать октеты с их использованием. Большинство протестированных мной браузеров сохраняют исходный регистр, в то время как другие, такие как Safari, преобразуют его в верхний регистр, если у них есть возможность.

22 янв. 2016 г. 18:56:13