Удаляем пустую строку запроса из URL
- Опубликовано:
Порой URL-адрес оканчивается нежелательным вопросительным знаком: например, /example/?
вместо /example/
. Вопросительный знак отделяет основную часть адреса от строки запроса (query string), но некоторые браузеры добавляют его, даже если GET-форма, результатом отправки которой является такой адрес, не содержит полей и, соответственно, строка запроса пуста.
Это происходит, например, при использовании кнопок-ссылок в браузерах на основе движков Chromium / Blink (Chrome, Opera 15+, Яндекс.Браузер, Vivaldi) и WebKit (Safari) (1, 2). Автоматически удалить вопросительный знак при пустой строке запроса можно с помощью серверного перенаправления (редиректа).
PHP
Наиболее просто задача решается на серверном скриптовом языке PHP. Полный запрошенный путь обычно хранится в серверной переменной REQUEST_URI
. Если первый вопросительный знак в значении этой переменной является её последним символом, следует перенаправлять на адрес без вопросительного знака.
$uri = $_SERVER['REQUEST_URI'];
$qPos = strpos($uri, '?');
if ($qPos === strlen($uri) - 1) {
header('HTTP/1.1 301 Moved Permanently');
header('Location: ' . substr($uri, 0, $qPos));
exit;
}
Этот код следует вставить в индексный файл вашего сайта перед любым другим PHP-кодом. Если не хочется изменять комплектные файлы CMS (например, для возможности её обновления), можно задать собственный индексный файл (например, custom-index.php
), внутрь которого поместить данный код, после которого с помощью require_
подключить истинный индексный файл CMS — обычно это index.php
.
Apache / .htaccess
Собственными средствами популярного веб-сервера Apache несколько проблематично надёжное различение ситуаций, когда строка запроса есть, но пустая (есть только вопросительный знак в конце URL-адреса), и когда строка запроса отсутствует полностью (URL-адрес не содержит даже вопросительного знака).
В серверную переменную REQUEST_URI
в Apache (в отличие от PHP) вопросительный знак при пустой строке запроса, похоже, вообще не попадает.
Остаётся анализировать серверную переменную THE_REQUEST
, содержащую не только запрошенный URL-адрес, а весь HTTP-запрос вида GET uri HTTP/1.1
:
RewriteEngine On
RewriteCond %{THE_REQUEST} ^[^\s]+\s+[^?]*?\?
RewriteCond %{QUERY_STRING} =""
# Для любых версий Apache:
RewriteRule .? %{REQUEST_URI}? [R=301,L]
# Для Apache 2.4+:
# RewriteRule .? %{REQUEST_URI} [R=301,L,QSD]
Метод запроса (например, GET
) и протокол (HTTP/1.1
) вопросительных знаков обычно не содержат, поэтому возможна более простая (хотя теоретически несколько менее надёжная) проверка значения переменной THE_REQUEST
на наличие вопросительного знака в любой части запроса, а не только в URL-адресе:
RewriteCond %{THE_REQUEST} \?