Mon site Web utilise Cloudflare pour activer SSL (le SSL gratuit n'est pas disponible sur mon hôte, Hostgator). Tout semble bien fonctionner, sauf lorsque je retourne une page 404. Cela se traduit par
Ce site est inaccessible
La page Web située sous https://example.com/example-url est peut-être temporairement indisponible ou a définitivement été déplacée vers une nouvelle adresse Web.
ERR_INVALID_RESPONSE
Si j'envoie un code de réponse HTTP 200 au lieu de 404, tout fonctionne normalement, même pour la même URL. J'ai aussi essayé d'envoyer HTTP 500, et ça marche aussi! Donc, c'est certainement quelque chose à propos du code de réponse 404 qui cause le problème.
La raison pour laquelle je crois que le problème a à voir avec Cloudflare est que
curl https://example.com/example-url
_, je récupère la bonne page 404 et le statut HTTP est 404 comme prévu.J'ai également d'autres sites utilisant Cloudflare, mais ils ne semblent pas avoir de problème pour renvoyer une réponse 404, ce qui me laisse penser que c'est un problème de configuration sur Cloudflare pour ce site.
Des idées?
Il s’est avéré que le problème était de savoir comment je générais les en-têtes de réponse.
J'utilise le framework Slim PHP et un middleware de gestionnaire d'erreur personnalisé. Cela ressemblait à ceci:
class ErrorResponseHandler {
protected $view = null;
function __construct(\Slim\Views\Twig $view) {
$this->view = $view;
}
public function __invoke(Request $request, Response $response, $next) {
$response = $next($request, $response);
if (404 === $response->getStatusCode() ) {
// Pass an empty response to the 404-handler in MainController
return (new MainController($this->view))->notFound404($request, new Response());
}
// Any other request, pass on current response
return $response;
}
}
Je crée un nouvel objet Response
afin d'obtenir un corps vide sans le code HTML 404 par défaut généré par Slim. Cependant, créer un nouvel objet Response
va apparemment mettre l'en-tête Content-Type
sur application/x-httpd-php5
, qui n'est pas compris par les navigateurs (j'aurais dû voir cela en utilisant curl --head
, mais je raté ça).
La solution consiste à définir le bon en-tête Content-Type
, comme ceci:
if (404 === $response->getStatusCode() ) {
// Pass an empty response to the 404-handler in MainController
$new_response = (new Response())->withHeader('Content-Type', 'text/html');
return (new MainController($this->view))->notFound404($request, $new_response);
}