Я думаю, что это, вероятно, ошибка в том, как Apache 2.2 и ниже обрабатывает данную конкретную ситуацию.
Кажется, что при чтении SSL 400 Bad Request
ошибка, Apache 2.2 не возвращает код ответа HTTP или заголовки, только тело ответа HTTP. Я проверяю, подключаясь к порту 443 по telnet и отправляя:
GET / HTTP/1.1
Сервер немедленно возвращает (для меня):
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
Reason: You're speaking plain HTTP to an SSL-enabled server port.<br />
Instead use the HTTPS scheme to access this URL, please.<br />
<blockquote>Hint: <a href="https://server.tld/"><b>https://server.tld/</b></a></blockquote></p>
</body></html>
Обратите внимание на отсутствие кода ответа HTTP или каких-либо заголовков HTTP.
Когда я делаю это с сервером Apache 2.4 , Я получаю:
HTTP/1.1 400 Bad Request
Date: Sun, 10 Feb 2013 00:47:23 GMT
Server: Apache/2.4.3 (Unix) OpenSSL/1.0.0g
Content-Length: 462
Connection: close
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
Reason: You're speaking plain HTTP to an SSL-enabled server port.<br />
Instead use the HTTPS scheme to access this URL, please.<br />
</p>
<hr>
<address>Apache/2.4.3 (Unix) OpenSSL/1.0.0g Server at server.tld Port 443</address>
</body></html>
Если я настраиваю строку ErrorDocument, как вы:
ErrorDocument 400 https://server.tld/
Затем я получаю HTML для перенаправления 302, но опять же, ни одного из заголовков. Без кода ответа перенаправления 302 и заголовка Location:
браузер не будет выполнять перенаправление.
Попробуйте выполнить обновление до Apache 2.4 и посмотрите, работает ли он. Я тестировал и подтверждал как минимум Apache 2.4.3, но я не приложил усилий, чтобы точно определить, когда это поведение было обновлено. Я подозреваю, что в ходе большой работы по подготовке версии 2.4 они исправили нежелательное поведение как побочный эффект.
Соответствующие ошибки Apache httpd:
ОБНОВЛЕНИЕ
Вы можете заставить Apache с ошибками дать вам желаемое поведение (перенаправление), заставив скрипт распечатать свои заголовки (которые не будут отправлены клиенту), а затем вручную снова распечатать нужные заголовки. Вот базовый сценарий Perl, который работает под Apache 2.2.22:
#!/usr/bin/perl
use strict;
use CGI;
my $q = CGI->new();
# this will cause Apache to handle the response properly, but is meaningless otherwise
print $q->redirect("https://localhost/");
# this actually performs the redirect
print "HTTP/1.1 302 Found\r\n";
print "Location: https://localhost/\r\n";
print "\r\n";
# you can do whatever you want here; this will be the HTML body
Вы должны знать, что есть и другие причины, по которым может быть сгенерировано 400, помимо простого разговора с портом SSL без SSL. Самый простой способ определить это - поискать переменную среды HTTPS
. Если он установлен, тогда SSL был согласован правильно, и что-то еще вызывает 400 (не используйте трюк с двойным заголовком, если это так). Если HTTPS
не установлен, верните свое перенаправление, как указано выше.
Вы можете исправить это с помощью mod-rewrite. Установите правило, соответствующее чему угодно. См. Этот ответ на Stackoverflow