web-dev-qa-db-fra.com

$ _SERVER ['REQUEST_SCHEME'] est-il fiable?

Récemment, je cherchais un moyen de déterminer correctement le protocole, en vertu duquel une demande d’URL était fournie au serveur.

J'ai regardé à travers parse_url() et quoique $_SERVER variable superglobal, et j'ai trouvé ceci:

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

print_r($_SERVER);
?>

Sortie:

[REQUEST_SCHEME] => http

Cependant, je n'ai pas pu le trouver sur php.net ou sur Google. Bien que j'ai pu trouver this question. Q # 1: Si $_SERVER['REQUEST_SCHEME'] n'a pas été documenté, il est probablement peu fiable ou peut-on faire confiance?

J'utilise VC9 PHP 5.4.14 TS sous Windows pour le développement. Mais ma production est sous Ubuntu. Q # 2: Cette propriété est-elle également disponible sous Ubuntu Linux?

32
BlitZ

Il est difficile de prouver sa fiabilité, mais il est facile de prouver que ce n’est pas fiable (si seulement je pouvais fournir un cas où cela ne fonctionnerait pas). Et je peux prouver qu'il n'est pas fiable car il ne fonctionne pas avec IIS 7.0 + PHP 5.3

33
invisal

La variable d'environnement REQUEST_SCHEME est documentée dans la page Apache mod_rewrite . Cependant, il n’est devenu disponible qu’après Apache 2.4.

Je n'ai que Apache 2.2, alors j'ai créé une variable d'environnement. J'ai ajouté le texte suivant en haut de mon fichier .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]

Maintenant je peux utiliser

  • %{ENV:REQUEST_SCHEME} dans d'autres conditions et règles de réécriture
  • $_SERVER['REQUEST_SCHEME'] dans mon code PHP

Je n'ai pas besoin de faire des vérifications conditionnelles compliquées partout, et mon code PHP est compatible avec les transferts. Lorsque Apache est mis à niveau, je peux modifier mon fichier .htaccess.

Je ne sais pas comment vous appliqueriez cela à un environnement Windows. Ce n'est probablement pas une bonne solution pour le code distribué, mais cela fonctionne bien pour mes besoins.

50
toxalot

Comme cette variable n’est pas disponible dans toutes les versions de serveur, il n’est pas fiable et ne teste que le . Vous pouvez également modifier votre code PHP pour tester deux autres variables d’environnement de serveur, qui peuvent également indiquer: que https est utilisé, comme ci-dessous:

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';
}

Comme le fait remarquer Toxalot, REQUEST_SCHEME est une variable native du serveur Web Apache depuis sa version 2.4. Apache 2.2 ne l’a pas (voir Variables serveur Apache 2.2) et Microsoft IIs 8.5 ne l’a pas non plus (voir IIS 8.5 Variables serveur) . Naturellement, si une variable n'est pas définie par le serveur, PHP ne l'inclura pas dans son tableau global $ _SERVER.

Heureusement, pour assurer la compatibilité avec les codes basés exclusivement sur la vérification REQUEST_SCHEME, vous pouvez créer cette variable dans Apache 2.2 en modifiant tous vos fichiers de configuration de l'hôte (httpd.conf, ssl.conf, 000-default.conf, vhosts.conf), en ajoutant les lignes suivantes:

# 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

Le code ci-dessus présume l’utilisation d’un vhost pour chaque protocole (pratique recommandée dans Apache - voir this et que ).

8
aldemarcalazans

Moi aussi, je n'ai pas trouvé de référence à REQUEST_SCHEME, mais si vous cherchez à déterminer si une demande a été faite par http: ou https:, vous pouvez utiliser $_SERVER['HTTPS'], qui est défini sur une valeur non vide si une demande est faite par https:. C'est documenté sur le site PHP ici

7
user1864610

Dans la nouvelle version Nginx, définissez par défaut fastcgi_param REQUEST_SCHEME $scheme.

5
S.A.N

Amélioration de la suggestion de toxalot pour les utilisateurs de 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]
2
Sinus Mackowaty

Cette valeur dépend de votre serveur Web. Si vous utilisez nginx (v1.10), vous pouvez voir les lignes suivantes dans le fichier /etc/nginx/fastcgi_params:

fastcgi_param  REQUEST_SCHEME     $scheme; 
fastcgi_param  HTTPS              $https if_not_empty;

Généralement, ces valeurs par défaut sont suffisantes . Mais il est possible que cela ne fonctionne pas, vous pouvez forcer ces valeurs dans votre vhost:

include fastcgi_params;
fastcgi_param  REQUEST_SCHEME     https; 
fastcgi_param  HTTPS              On;

Si vous utilisez Apache, vous pouvez jeter un oeil à la réponse de toxalot

1
Arno