web-dev-qa-db-fra.com

"Réponse invalide" lors du retour d'une page HTTP 404 via Cloudflare

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

  1. Cela fonctionne bien sur mon environnement de développement local (sans utiliser SSL).
  2. Si je lance _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?

1
Magnus W

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);
    }
1
Magnus W