Apache HTTPD 2.4.x: как «направить» пользователей на пользовательскую страницу ошибки, если в URL/URI присутствуют определенные символы?

Apache HTTPD 2.4.x: как «направить» пользователей на пользовательскую страницу ошибки, если в URL/URI присутствуют определенные символы?

Итак, у меня есть конфигурация Apache, в которой я пытаюсь «переписать» пользователей на пользовательскую страницу ошибки, но это не работает. Я вошел http://localhost/index.html/ddgdg%:sdsdfsв браузер и не получил свою страницу ошибки.

Я могу просмотреть пользовательскую страницу ошибки, напрямую введя ее URL-адрес в браузере ( http://localhost/my-error.html).

Есть идеи, что я могу делать неправильно?


мой полный httpd.conf:ссылка на httpd.conf


мои изменения в httpd.conf по умолчанию(Мне также пришлось раскомментировать LoadModule для mod_rewrite.so)

RewriteEngine On
LogLevel alert rewrite:info
#if invalid characters are present in the URI, display 404 page
RewriteCond %{REQUEST_URI} ^\/.+[:%].+  
RewriteRule "^/$" "http://%{SERVER_NAME}/my-error.html" [L,R=301]

содержимое пользовательской страницы ошибок

$ cat /Library/WebServer/Documents/my-error.html 
<html><body><h1>404 error here</h1></body></html>

версия апача

$ apachectl -v
Server version: Apache/2.4.34 (Unix)
Server built:   Feb 22 2019 20:20:11

правка1:На данный момент использую macOS Mojave, но через некоторое время настрою виртуальную машину Ubuntu.

решение1

Здесь есть несколько разных проблем...

http://localhost/index.html/ddgdg%:sdsdfs

Вы на самом деле не указали, какой ответ вы получаете, а только то, чтоне происходит. Однако из-за случайного символа %(не предшествующего шестнадцатеричному закодированному октету) этот URL-адрес строго недействителен, и я ожидаю, что Apache ответит 400 Bad Request. Единственный способ обойти это — создать пользовательский документ об ошибке 400, в котором вы проверяете запрошенный URL-адрес и настраиваете ответ. Например:

ErrorDocument 400 /my-error.html

Если бы не заблудившийся, %вы могли бы поймать этот запрос с помощью mod_rewrite и перенаправить соответствующим образом. Однако вы RewriteRuleпроверяете пустой URL-путь (т.е. "^/$"), тогда как запрошенный URL в вашем примере далек от пустого (т.е. /index.html/ddgdg%:sdsdfs) - поэтому RewriteRuleдиректива никогда не будет соответствовать вашему примеру URL. Чтобы проверить %или :где-либо в URL-пути и перенаправить, вы можете сделать что-то вроде следующего:

# Checks for a "%" or ":" in the URL-path
RewriteRule [%:] /my-error.html [L,R=302]

Но обратите внимание, что URL-путь, соответствующийRewriteRule шаблон(а также REQUEST_URIпеременная сервера) уже %-декодирована, поэтому это будет соответствовать только URL-адресам, где специальные символы были дважды закодированы (редко). (Как отмечено выше, в противном случае случайный ответ, %скорее всего, сгенерирует ответ 400)доmod_rewrite способен обработать запрос.)

Я бы также спросил, почему вы хотите «перенаправить» на свой пользовательский документ об ошибке (т. е. my-error.html), а не отдать его напрямую? Перенаправление имеет ряд недостатков: клиенту отправляется ответ 3xx, теряется информация об URL, вызвавшем ошибку, дублируются запросы к вашему серверу и т. д.

Вы могли бывнутренне переписатьзапрос на /my-error.html, вместо перенаправления, просто сняв флаг R. Например:

RewriteRule [%:] /my-error.html [L]

Но если вы вручную не установите статус HTTP, my-error.htmlто пользователь увидит 200 OKответ, что нежелательно.

ИЛИ (предпочтительно) создайте пользовательский 404 (который выглядит как то, что вы пытаетесь сделать) и вызовите его вместо этого. Например:

ErrorDocument 404 /my-error.html

RewriteRule [%:] - [R=404]

Затем Apache устанавливает статус ответа HTTP «404 Not Found».

Однако, вам, вероятно, вообще не нужно использовать mod_rewrite здесь. В вашем примере URL, все после index.htmlURL-пути, а именно /ddgdg%:sdsdfs, являетсядополнительная информация о пути(он же path-info / PATH_INFO). По умолчанию обработчик, который обрабатывает текстовые/html-ответы, не разрешает path-info и неявно вызовет 404 (если бы не случайный %- как обсуждалось выше), вызывая ваш custom ErrorDocument(если он определен). Таким образом, RewriteRuleдирективу в последнем примере можно просто удалить, поскольку Apache в любом случае вызовет 404 (если вы не переопределите это поведение с помощью AcceptPathInfo).

Связанный контент