Является ли $_SERVER ['REQUEST_SCHEME'] надежным?

Недавно я искал способ правильно определить протокол, в соответствии с которым запрос url был отправлен на сервер.

Я просмотрел parse_url() и хотя $_SERVER суперглобальная переменная, и нашел это:

<?php
header('Content-Type: text/plain');

print_r($_SERVER);
?>

Вывод:

[REQUEST_SCHEME] = > http

Однако мне не удалось найти его на php.net или Google. Хотя мне удалось найти этот вопрос. Q # 1: Если $_SERVER['REQUEST_SCHEME'] не было документировано, возможно, оно ненадежно или ему можно доверять?

Я использую VC9 PHP 5.4.14 TS под окнами для разработки. Но моя продукция находится под ubuntu. Q # 2: Является ли это свойство также доступным и под Linux ubuntu?

Ответ 1

Трудно доказать, что он надежен, но легко доказать, что он ненадежный (если бы я мог предоставить случай, который он не работает). И я могу доказать, что он ненадежен, потому что он не работает с IIS 7.0 + PHP 5.3

Ответ 2

Переменная среды REQUEST_SCHEME документирована на странице Apache mod_rewrite. Однако он не стал доступен до Apache 2.4.

У меня только Apache 2.2, поэтому я создал переменную окружения. Я добавил следующее в верхнюю часть моего файла .htaccess.

RewriteEngine on

# Set REQUEST_SCHEME (standard environment variable in Apache 2.4)
RewriteCond %{HTTPS} off
RewriteRule .* - [E=REQUEST_SCHEME:http]

RewriteCond %{HTTPS} on
RewriteRule .* - [E=REQUEST_SCHEME:https]

Теперь я могу использовать

  • %{ENV:REQUEST_SCHEME} в других условиях и правилах перезаписи
  • $_SERVER['REQUEST_SCHEME'] в моем PHP-коде

Мне не нужно делать лишние беспорядочные условные проверки везде, и мой PHP-код является совместимым с Outlook. Когда Apache обновляется, я могу изменить файл .htaccess.

Я не знаю, как вы примените это к среде Windows. Это, вероятно, не очень хорошее решение для распределенного кода, но оно хорошо работает для моих нужд.

Ответ 3

Я тоже не смог найти ссылку на REQUEST_SCHEME, но если вы хотите определить, был ли запрос сделан http: или https:, вы можете использовать $_SERVER['HTTPS'], который установлен к непустому значению, если запрос был сделан https:. Он зарегистрирован на сайте PHP здесь

Ответ 4

В новой версии Nginx установите по умолчанию fastcgi_param REQUEST_SCHEME $scheme.

Ответ 5

Поскольку эта переменная недоступна во всех версиях сервера, безусловно, она не является надежной только для ее тестирования. Вместо этого вы можете изменить свой PHP-код, чтобы проверить еще две переменные среды сервера, которые также могут указывать на то, что https используется, как показано ниже:

if ( (! empty($_SERVER['REQUEST_SCHEME']) && $_SERVER['REQUEST_SCHEME'] == 'https') || (! empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') || (! empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == '443') ) {
    $server_request_scheme = 'https';
} else {
    $server_request_scheme = 'http';
}

Как сказал toxalot, REQUEST_SCHEME является собственной переменной Apache с версии 2.4 (у Apache 2.2 ее нет). И, если переменная не задана сервером, PHP не будет включать ее в свой глобальный массив $_SERVER.

К счастью, для совместимости с кодами, основанными исключительно на проверке REQUEST_SCHEME, вы можете создать эту переменную в Apache 2.2, редактируя все ваши файлы конфигурации хоста (httpd.conf, ssl.conf, 000-default.conf, vhosts.conf), добавляя следующие строки:

# FOR HOSTS LISTENING AT PORT 80
SetEnvIf Request_Protocol ^HTTP/ REQUEST_SCHEME=http

# FOR HOSTS LISTENING AT PORT 443
SetEnvIf Request_Protocol ^HTTP/ REQUEST_SCHEME=https

Ответ 6

Усиление предложения токсикола для пользователей CloudFlare:

RewriteEngine on

RewriteCond %{HTTPS} !on [OR]
RewriteCond %{HTTP:CF-Visitor} '"scheme":"http"'
RewriteRule .* - [E=REQUEST_SCHEME:http]

RewriteCond %{HTTPS} on [OR]
RewriteCond %{HTTP:CF-Visitor} '"scheme":"https"'
RewriteRule .* - [E=REQUEST_SCHEME:https]

Ответ 7

Это значение зависит от вашего веб-сервера. Если вы используете nginx (v1.10), в файле /etc/nginx/fastcgi_params вы можете увидеть следующие строки:

fastcgi_param  REQUEST_SCHEME     $scheme; 
fastcgi_param  HTTPS              $https if_not_empty;

Как правило, эти значения по умолчанию являются достаточными. Но возможно, что это не сработает, вы можете заставить эти значения в своем vhost:

include fastcgi_params;
fastcgi_param  REQUEST_SCHEME     https; 
fastcgi_param  HTTPS              On;

Если вы используете Apache, вы можете взглянуть на сообщение "toxalot".