Поэтому я недавно обновил свой .htaccess, чтобы реплицировать директиву косой черты каталога с помощью 308 вместо 301, которую обычно использует Apache, чтобы браузер повторял один и тот же запрос вместо того, чтобы менять его на запрос GET и удалять данные из других методов запроса.
# Disable
DirectorySlash Off
# Recreate the DirectorySlash directive with 308
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+[^/])$ /$1/ [R=308,L]
Это отлично работает в моих локальных тестах, но когда я использую свой тестовый сервер, использующий HTTPS, он внезапно ломается. В инструментах разработчика Chrome я вижу, что он направлен на незащищенный URL-адрес или по какой-то причине.
Ошибка:
Mixed Content: The page at 'https://...' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://...'. This request has been blocked; the content must be served over HTTPS.
Я также пробовал добавить такую схему запроса, но это не дало никакого эффекта.
RewriteRule ^(.+[^/])$ %{REQUEST_SCHEME}://%{HTTP_HOST}/$1/ [R=308,L]
Кто-нибудь знает, почему Apache меняет протокол на небезопасный?
ОБНОВЛЯТЬ: Я попытался проверить протокол и сохранить его в переменной, потому что REQUEST_SCHEME не всегда определен и приводит к тому, что по умолчанию он снова возвращается к http.
RewriteCond %{HTTPS} on
RewriteRule .* - [E=PROTO:https]
RewriteCond %{HTTPS} !on
RewriteRule .* - [E=PROTO:http]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+[^/])$ %{ENV:PROTO}://%{HTTP_HOST}/$1/ [R=308,L]
Первоначально это работало, но по-прежнему перенаправляет HTTPS на HTTP, когда запрос является POST.
ОБНОВЛЕНИЕ: Как предложил Аркаша, я попробовал жестко запрограммировать HTTPS, и это работает.
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+[^/])$ https://%{HTTP_HOST}/$1/ [R=308,L]
Это крайне странно, поскольку переменный подход должен давать тот же результат. Первоначальный запрос — HTTPS, поэтому переменная должна в конечном итоге использовать HTTPS так же, как это происходит при жестко запрограммированном подходе.
Поэтому я думаю, мне придется использовать проверку на основе домена или какой-либо другой обходной путь и продублировать логику для HTTP и HTTPS.
Я чувствую, что это все ненужная гимнастика, чтобы заставить редирект 308 работать так, как описано.
Кто-нибудь может объяснить это странное поведение?
Вы пишете: «Я тоже пробовал добавлять такую схему запроса, но это не дало никакого эффекта». ... Если вы это сделаете, не будет ли гораздо разумнее вместо этого использовать жестко запрограммированную схему https
?
Но тогда он сломается для http.
@CBroe У меня нет доступа для включения журналов. Хорошее предложение, хотя я посмотрю, смогу ли я его получить.
Мне пришло в голову, что если RewriteCond %{HTTPS} on
или %{REQUEST_SCHEME}
вели себя так, как если бы запрос был HTTP, то это означает, что Apache каким-то образом должен получать HTTP-запрос независимо от исходного протокола.
Тестовый сервер размещен на AWS, и кажется, что HTTPS-запрос должен быть расшифрован AWS, а затем отправлен в незашифрованном виде на экземпляр Apache. (Я не знаю, как изначально был настроен этот сервер).
Решением было проверить наличие X-Forarded-Proto
и установить переменную для использования в перенаправлении:
# Assume HTTP by default for local devs.
RewriteRule .* - [E=PROTO:http]
# Change to HTTPS if forwarded/current request is HTTPS.
RewriteCond %{HTTP:X-Forwarded-Proto} =https [OR]
RewriteCond %{HTTPS} on
RewriteRule .* - [E=PROTO:https]
# Recreate the DirectorySlash directive with 308
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+[^/])$ %{ENV:PROTO}://%{HTTP_HOST}/$1/ [R=308,L]
Что касается того, почему это были только мои перенаправления POST 308, моя единственная теория заключается в том, что браузер молча корректирует протокол для нас, когда это запрос GET, и более внимательно следует директиве 308, если это не запрос GET. В противном случае запросы GET должны были бы иметь ту же проблему.
Мне было бы очень интересно получить другие ответы, более подробно объясняющие, что происходит, особенно поведение браузера (Chrome && Firefox).
Если можете, включите ведение журнала перезаписи и посмотрите, даст ли это больше ясности относительно того, где именно что-то идет не так.