2009-07-05 14 views
14

Lo que quiero preguntar es si hay una forma de averiguar si una instancia del servidor web tiene habilitada la reescritura de URL. Necesito esto para poder crear una instancia del tipo correcto de controlador de URL.Cómo averiguar mediante programación si una instancia del servidor web admite la reescritura url

En teoría, usted sabe de antemano si lo tiene habilitado o no y puede usar algo para configurarlo. Me gustaría, sin embargo, poder detectar esta configuración automáticamente en tiempo de ejecución. regla de reescritura

La URL sería algo muy simple como:

^/(.*)$ => /bootstrap.php 

Esto garantiza que la cadena correspondiente está presente en el REQUEST_URI, pero no contamina la matriz _GET.

Cuando hice mi investigación me llevó hasta el momento:

  1. Apache.
    En mi opinión, Apache tiene un enfoque muy peculiar, ya que establece el encabezado REDIRECT_SCRIPT_URI para reescribir las URL, pero no para las que no se reescriben.
    P. ej.

    http://host/ana/are/mere
    se volvería a escribir en index.php por lo que el encabezado antes mencionado estaría presente, pero
    http://host/
    no se volvería a escribir.

  2. Lighttpd.
    Lighttpd con fast-cgi se comporta bien, configurando el encabezado REDIRECT_URI si la reescritura de URL está habilitada para el host actual. Esto es confiable.

  3. Cherokee.
    Bueno, para Cherokee no hay un método que descubrí, ya que utiliza (en mi opinión) un método más complicado para obtener la reescritura de URL. (Es decir, se llama redirección interna – y el proceso fcgi no sabe que la solicitud fue redirigido)

otros servidores HTTP también que no he probado, como Nginx, así que si alguien tiene alguna entrada en este Importa, me encantaría escucharlo.

Respuesta

14

No es la solución más elegante, pero se podría crear un directorio, inserte un .htaccess y un pequeño archivo PHP y tratar de abrirlo con el enrollamiento/file_get_contents() de su código real:

.htaccess

RewriteEngine on 
RewriteRule ^(.*?)$ index.php?myparam=$1 

index.php

<?php 
//open with file_get_contents("http://yoursite/directory/test") 
if($_GET['myparam']){die("active");} 
?> 

Aunque esto puede ser aceptable durante una instalación, por razones de rendimiento esto no debería ser utilizado para cada solicitud ¡en tu sitio! Guarde la información en algún lugar (sqlite/textfile).

actualización

específica de Apache, pero apache_get_modules()/phpinfo() en combinación con array_search/strpos es tal vez útil para usted.

6

PHP tiene server-specific functions para servidores Apache, IIS y NSAPI.Sólo tengo Apache, sino como Merkuro sugirió esto funciona como se esperaba:

<?php 
    if (in_array('mod_rewrite',@apache_get_modules())) 
    echo 'mod_rewrite enabled'; 
    else 
    echo 'mod_rewrite not enabled'; 
?> 

Como funciones específicas del servidor PHP no cubren todos los servidores que le gustaría probar en este probablemente no es la mejor solución.

Recomendaría la primera respuesta de merkuro: implementarla y luego probarla en script. Creo que es la única forma de obtener un buen resultado.

Espero que ayude!

+0

Sí, gracias por la respuesta. Me olvidé por completo de las funciones específicas de Apache. –

+0

Gran solución para Apache. Estaba pensando en la misma línea. –

9

Ya está refirió a continuación, pero creo que la siguiente receta es una solución bastante impermeable a este problema:

  1. Configurar la redirección

  2. Solicitud de una página a través de su URL reescrito

  3. Si la solicitud devuelve la página en cuestión, tiene la redirección configurada correctamente, si obtiene la respuesta HTTP 404, entonces no está funcionando.

La idea es básicamente que esto funciona con casi cualquier método de redirección. Ya se ha mencionado, pero se reitera, tales trucos agregan bastante sobrecarga y se realizan mejor solo una vez (instalación o desde el panel de configuración) y luego se guardan en la configuración.


algunos detalles de implementación, opciones para hacer y un poco en cómo llegué a esta solución:

recordé Drupal hizo un control de este tipo durante el proceso de instalación, por lo que miraron cómo lo hicieron. Tuvieron que javascript en la página de instalación hacer una solicitud ajax (sincrónicamente, para evitar problemas de concurrencia con la base de datos). Esto requiere que el usuario que instale el software tenga javascript activado, pero no creo que sea un requisito poco razonable.

Sin embargo, creo que usar php para solicitar la página podría ser una solución más limpia. Además de no molestarse con un requisito de JavaScript, también necesita menos datos para enviar y recibir y simplemente no requiere que la lógica de la acción se distribuya en varios archivos. No sé si hay otra (des) ventaja para cualquiera de los métodos, pero esto debería ayudarlo y le permitirá explorar las opciones alternativas usted mismo.

Hay otra opción que hacer: probar en un entorno de prueba o en el sitio normal. Lo que Drupal hace es tener la redirección siempre activada (como en el caso de Apache, tener el archivo .htaccess que redirige solo para ser parte de la descarga de Drupal), pero solo escribir las direcciones de fantasía si la redirección está activada en el configuraciones. Esto tiene la desventaja de que requiere más trabajo detectar qué tipo de redirección se utiliza, pero aún es posible (puede, por ejemplo, agregar una variable GET que muestre el motor de redirección en una página de prueba específica o incluso en cada página, o puede redirigir a una página que establece $redirectionEngine y luego incluye el índice real). Aunque no tengo mucha experiencia con la redirección que no sea con mod_rewrite en apache, creo que esto debería funcionar con casi todos los motores de redirección.

La otra opción aquí es utilizar un entorno de prueba. Básicamente, la idea es crear una carpeta y configurar una redirección para ella, o eliminar la necesidad de acceso de escritura del sistema de archivos y en su lugar tener una carpeta (o una carpeta para cada motor de redirección).Esto tiene algunas desventajas: todavía necesita acceso de escritura para configurar el redireccionamiento para el sitio principal (aunque tal vez no para todo el motor de redirección, realmente no sé cómo se configuran correctamente, pero para apache necesitará acceso de escritura si va a activar la redirección), podría ser más fácil para un bot detectar qué software y qué versión de él está utilizando al acceder a las pruebas (a menos que elimine las carpetas de prueba después de las pruebas) y necesita poder reescriba solo una parte del sitio (lo cual tiene sentido para cualquier motor de redirección, pero no voy a asumir esta funcionalidad). Sin embargo, esto viene con la ventaja de que es más fácil averiguar qué motor de reescritura se está utilizando o, básicamente, cualquier otro aspecto de la redirección. También podría haber otras ventajas que no conozco, así que simplemente le doy las opciones y le dejo elegir su método usted mismo.

Con algunas opciones para el usuario, creo que esto debería ayudarlo a configurar el sistema de la manera que desee.

+0

Buena solución. Si esto se implementó correctamente, sería independiente del servidor web que se estaba utilizando. –

2

Puede programación comprobar la existencia de mod_rewrite si el servidor es Apache mediante el uso de la función apache_get_modules() en PHP:

$modules = apache_get_modules(); 
echo in_array('mod_rewrite', $modules) ? 'mod_rewrite detected' : 'mod_rewrite not detected'; 

Esto podría ser utilizado como un primer paso, pero no es un método de prueba completa por cualquier medio. El hecho de que mod_rewrite esté cargado no significa que esté disponible para su entorno. Esto tampoco ayuda si está en un servidor que no es Apache.

No hay muchos métodos consistentes que funcionen en todas las combinaciones de plataforma. Pero dado que el resultado es constante, puede probarlo. Configure un redireccionamiento especial y haga que un script use PHP cURL o file_get_contents() para verificar una URL de prueba. Si la redirección fue exitosa, obtendrá el contenido esperado y puede realizar pruebas fácilmente para esto.

Esta es una preparación básica que .htaccess para redireccionar ajax a ajax.php:

RewriteEngine On 
RewriteRule ajax ajax.php [L] 

El siguiente script PHP intentará obtener el contenido de ajax. El nombre real del guión es ajax.php. Si la redirección falla, no obtendrá los contenidos esperados.

error_reporting(E_ALL | E_STRICT); 

$url = 'http://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['REQUEST_URI']).'/ajax'; 
$result = json_decode(@file_get_contents($url)); 

echo ($result === "foobar") ? 'mod_rewrite test was successful' : 'mod_rewrite test failed'; 

Por último, aquí es la última pieza de la escritura, ajax.php. Esto devuelve una la respuesta esperada cuando la redirección tiene éxito:

echo json_encode('foobar'); 

He fijado un live example of this test, y también me han puesto a disposición del full sources.

+0

_apache_get_modules() no funciona si está utilizando PHP como CGI_. –

1

Como todos los comentarios ya mencionan, en realidad probarlo es la única forma de estar seguro de que funciona. Pero en lugar de redireccionar a una página real y esperar a que se cargue, simplemente verificaría el encabezado. En mi opinión, esto es lo suficientemente rápido como para ser utilizado incluso en tiempo de ejecución en un sitio normal. Si realmente necesita ser de alto rendimiento, entonces, por supuesto, el almacenamiento en caché es mejor.

sólo hay que poner algo como lo siguiente en su archivo .htaccess

RewriteEngine on 
RewriteRule ^/redir/My/Super/Special/Hidden/Url/To/Test/$ /redir/longload.php [L,R=307] 

y luego se puede utilizar el siguiente código php para comprobar si está activado el mod_rewrite.

<?php 
function HasModRewrite() { 
    $s = empty($_SERVER["HTTPS"]) ? '' : ($_SERVER["HTTPS"] == "on") ? "s" : ""; 
    $sp = strtolower($_SERVER["SERVER_PROTOCOL"]); 
    $protocol = substr($sp, 0, strpos($sp, "/")) . $s; 
    $port = ($_SERVER["SERVER_PORT"] == "80") ? "" : (":".$_SERVER["SERVER_PORT"]); 


    $options['http'] = array(
    'method' => "HEAD", 
    'follow_location' => 0, 
    'ignore_errors' => 1, 
    'timeout' => 0.2 
); 

    $context = stream_context_create($options); 

    $body = file_get_contents($protocol . "://" . $_SERVER['SERVER_NAME'] . $port .'/redir/My/Super/Special/Hidden/Url/To/Test/', NULL, $context); 
    if (!empty($http_response_header)) 
    { 
    return substr_count($http_response_header[0], ' 307')>0; 
    } 

    return false;  
} 


$st = microtime(); 
$x = HasModRewrite(); 
$t = microtime()-$st; 

echo 'Loaded in: '.$t.'<hr>'; 

var_dump($x); 
?> 

de salida:

Loaded in: 0.002657 
--------------------- 
bool(true) 
+0

También haga una solicitud HEAD. http://hakre.wordpress.com/2011/09/17/head-first-with-php-streams/, preguntas relacionadas con los enlaces, también – hakre

+0

Actualizado. No estoy seguro de si sscanf es más rápido/mejor, así que no lo alteré. –

Cuestiones relacionadas