php - parser - ¿Es $_SERVER[''REQUEST_SCHEME''] confiable?
php build url (7)
Hace poco buscaba una manera de determinar correctamente el protocolo, bajo qué solicitud de URL se suministraba al servidor.
Miré a través de parse_url()
y aunque $_SERVER
variable superglobal, y encontré esto:
<?php
header(''Content-Type: text/plain'');
print_r($_SERVER);
?>
Salida:
[REQUEST_SCHEME] => http
Sin embargo, no pude encontrarlo en $_SERVER o Google. Sin embargo, pude encontrar this pregunta. Q # 1: Si $_SERVER[''REQUEST_SCHEME'']
no se documentó, ¿es probable que no sea confiable o se pueda confiar?
VC9 PHP 5.4.14 TS
usando VC9 PHP 5.4.14 TS
en windows para desarrollo. Pero mi producción está bajo ubuntu. Q # 2: ¿Esta propiedad también está disponible bajo ubuntu linux también?
Como esta variable no está disponible en todas las versiones de servidor, no es confiable probarla solo . En su lugar, puede cambiar su código PHP para probar dos variables de entorno de servidor más, que también pueden indicar que se está utilizando https, como se muestra a continuación:
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'';
}
Como lo señala toxalot, REQUEST_SCHEME es una variable nativa del servidor web Apache desde su versión 2.4. Apache 2.2 no lo tiene (vea las variables del servidor Apache 2.2) y Microsoft IIs 8.5 tampoco lo tiene (vea IIS 8.5 Server Variables) . Naturalmente, si el servidor no establece una variable, PHP no la incluirá en su matriz global $ _SERVER.
Afortunadamente, para compatibilidad con códigos basados exclusivamente en la comprobación REQUEST_SCHEME, puede crear esta variable en Apache 2.2 editando todos sus archivos de configuración de host (httpd.conf, ssl.conf, 000-default.conf, vhosts.conf), agregando las siguientes líneas :
# 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
El código anterior presupone el uso de un vhost para cada protocolo (una buena práctica en Apache: vea this y that ).
En la nueva versión de Nginx, establece de manera predeterminada el fastcgi_param REQUEST_SCHEME $scheme
.
Es difícil probar que es confiable, pero es fácil demostrar que no es confiable (si solo pudiera proporcionar un caso que no funciona). Y puedo probar que no es confiable porque no funciona con IIS 7.0 + PHP 5.3
Este valor depende de su servidor web. Si usa nginx (v1.10), en el archivo /etc/nginx/fastcgi_params
puede ver las siguientes líneas:
fastcgi_param REQUEST_SCHEME $scheme;
fastcgi_param HTTPS $https if_not_empty;
En general, estos valores predeterminados son suficientes. Pero es posible que no funcione, puedes forzar estos valores en tu vhost:
include fastcgi_params;
fastcgi_param REQUEST_SCHEME https;
fastcgi_param HTTPS On;
Si usas Apache, puedes echarle un vistazo a la respuesta de toxalot
La variable de entorno REQUEST_SCHEME
está documentada en la página mod_rewrite de Apache . Sin embargo, no estuvo disponible hasta Apache 2.4.
Solo tengo Apache 2.2, así que creé una variable de entorno. Agregué lo siguiente a la parte superior de mi archivo .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]
Ahora puedo usar
-
%{ENV:REQUEST_SCHEME}
en otras condiciones y reglas de reescritura -
$_SERVER[''REQUEST_SCHEME'']
en mi código PHP
No tengo que hacer comprobaciones condicionales adicionales desordenadas en todas partes, y mi código PHP es compatible con versiones anteriores. Cuando se actualiza Apache, puedo cambiar mi archivo .htaccess.
No sé cómo aplicarías esto a un entorno de Windows. Probablemente esta no sea una buena solución para código distribuido, pero funciona bien para mis necesidades.
Mejorando la sugerencia de toxalot para los usuarios 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]
Yo tampoco pude encontrar una referencia a REQUEST_SCHEME
, pero si está buscando determinar si una solicitud fue hecha por http:
o https:
entonces puede usar $_SERVER[''HTTPS'']
, que está configurado como no -valor vacío si https:
hizo una solicitud https:
Está documentado en el sitio PHP here