2015-08-10 1 views
10

J'ai parcouru accidental usage de Status en-tête pour FastCGI. Y at-il des avantages/inconvénients de l'utiliser dans des scripts indépendants de l'environnement?Redirection 301/302 indépendante de l'environnement avec PHP

header('Location: ' . $url, true, 301); 

seule cause aucun problème pour moi sur Apache 2.2 (selon phpinfo(), le serveur utilise FastCGI).

Le script est destiné à Apache et nginx (mod_php et FastCGI). À quoi ressemblerait une solution infaillible?

+1

Bonne question. Je pencherais vers 'header ('HTTP/1.1 301'. $ Url, true, 301);' Peut-être redondant? Aimerait voir le code sous-jacent maintenant. Comment est-ce que tout cela tient compte de l'utilisation de ['http_response_code'] (http://php.net/http_response_code)? – ficuscr

Répondre

4

Le code d'état HTTP est émis en tant que partie de la première ligne de la réponse HTTP. Selon Fast CGI FAQ l'en-tête de statut est un en-tête spécial reconnu par le serveur qui contrôle cette ligne et il n'est pas envoyé au client. Toutefois, s'il est utilisé avec un adaptateur de serveur non FastCGI, la valeur est ignorée par le serveur et l'en-tête peut être envoyé.

La solution que vous avez déjà est la manière la plus indépendante possible de l'environnement. Le seul ajout serait une instruction exit immédiatement après la redirection pour s'assurer que le script se termine.

Regardons de plus près ce qui se passe sous le capot.

Le code redirection PHP suivant

header('Location: ' . $url, true, 301); 
exit; 

appellera le code C dans ext/standard/head.c

PHP_FUNCTION(header) 
{ 
    [ code that just parses the arguments omitted ] 

    sapi_header_op(rep ? SAPI_HEADER_REPLACE:SAPI_HEADER_ADD, &ctr); 
} 

qui à son tour appeler la fonction sapi_header_op dans main/SAPI.c

[ ... ] 

switch (op) { 

    [ ... ] 

    case SAPI_HEADER_ADD: 
    case SAPI_HEADER_REPLACE: 
    case SAPI_HEADER_DELETE: { 
      sapi_header_line *p = arg; 

      if (!p->line || !p->line_len) { 
       return FAILURE; 
      } 
      header_line = p->line; 
      header_line_len = p->line_len; 
      http_response_code = p->response_code; 
      break; 
     } 

[ code that splits header line by colon, trims whitespace etc ] 

[ special headers handling code, including setting 302 if Location ] 

if (http_response_code) { 
    sapi_update_response_code(http_response_code); 
} 

sapi_header_add_op(op, &sapi_header); 
return SUCCESS; 

Si FastCGI retour -end est utilisé, les en-têtes ajoutés seront eventua lly être envoyé par la fonction sapi_cgi_send_headers dans sapi/cgi/cgi_main.c

[ ... ] 
if (CGIG(nph) || SG(sapi_headers).http_response_code != 200) 
{ 
    [ emit status line if cgi.rfc2616-headers is set ] 

    [ Handle a case where there is a user supplied status line ] 

    [ Handle a case where there is already a user supplied status header ] 

    [ if none of the above ] 

     if (err->str) { 
      len = slprintf(buf, sizeof(buf), "Status: %d %s\r\n", SG(sapi_headers).http_response_code, err->str); 
     } else { 
      len = slprintf(buf, sizeof(buf), "Status: %d\r\n", SG(sapi_headers).http_response_code); 
     } 
    [ ... ] 
} 
[ ... ] 

Notez que la fonction php_apache_sapi_send_headers dans sapi/apache2handler/sapi_apache2.c n'a pas de traitement spécial de l'en-tête Status parce qu'il n'est pas utilisé pour la communication du module.

Donc, en exécutant le code PHP ci-dessus

  1. Code de réponse dans la ligne d'état HTTP est forcé de 301
  2. tête Emplacement est soit ajouté ou l'existant est remplacé
  3. Le script sort donc pas le code suivant peut changer l'état ou les en-têtes

Toutes les manipulations sont effectuées dans la couche SAPI qui est une couche d'abstraction au-dessus des adaptateurs de serveur HTTP (FastCGI, Apa module de che etc.). C'est aussi inter-environnement et fiable qu'il obtient.

Historiquement, il y a eu des bogues dans FastCGI qui empêchaient 301 réponses de fonctionner correctement, cependant c'était dans l'implémentation du serveur web et il n'y avait rien à faire du code PHP pour contourner le problème.

Voir aussi:

+0

C'est l'explication qui me manquait. Merci pour une réponse complète supportée par des références sources. – estus