Перенаправление Apache 308 меняет протокол с https на http

Поэтому я недавно обновил свой .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 работать так, как описано.

Кто-нибудь может объяснить это странное поведение?

Если можете, включите ведение журнала перезаписи и посмотрите, даст ли это больше ясности относительно того, где именно что-то идет не так.

CBroe 12.07.2024 08:02

Вы пишете: «Я тоже пробовал добавлять такую ​​схему запроса, но это не дало никакого эффекта». ... Если вы это сделаете, не будет ли гораздо разумнее вместо этого использовать жестко запрограммированную схему https?

arkascha 12.07.2024 13:15

Но тогда он сломается для http.

Brad 14.07.2024 06:31

@CBroe У меня нет доступа для включения журналов. Хорошее предложение, хотя я посмотрю, смогу ли я его получить.

Brad 15.07.2024 03:14
Как установить LAMP Stack 1/2 на Azure Linux VM
Как установить LAMP Stack 1/2 на Azure Linux VM
В дополнение к нашему предыдущему сообщению о намерении Azure прекратить поддержку Azure Database для MySQL в качестве единого сервера после 16...
1
4
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Мне пришло в голову, что если 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).

Другие вопросы по теме