Carte de conformité aux RFC

Cette page recense les standards qui comptent pour OxPHP en tant que serveur d'origine : HTTP, TLS, les fichiers statiques et la passerelle vers PHP. Elle décrit OxPHP 0.13.0. WebDAV, le rôle de proxy et les caches partagés n'entrent pas dans son périmètre.

Un standard compte comme implémenté lorsque le comportement est présent. Une partie de ce travail est propre à OxPHP, une autre vient des bibliothèques HTTP, TLS et de compression sur lesquelles OxPHP est construit et qu'il configure.

Entièrement implémentés

  • RFC 9112, HTTP/1.1 : keep-alive, corps en chunks, Expect: 100-continue et pipelining. Un délai d'expiration limite le temps qu'un client peut mettre à envoyer ses en-têtes.
  • RFC 9113, HTTP/2 : sur TLS, et sur TCP en clair pour les clients qui se connectent avec connaissance préalable. Le nombre de flux concurrents et la taille des en-têtes sont plafonnés, les attaques Rapid Reset et MadeYouReset sont bloquées, et un serveur en cours de drainage l'annonce par GOAWAY.
  • RFC 7541, HPACK : la compression des en-têtes HTTP/2, avec une limite sur la taille des en-têtes décodés qui arrête les requêtes de type « bombe HPACK ».
  • RFC 8446 et RFC 5246, TLS 1.3 et 1.2 : les deux versions, avec une version minimale que vous pouvez relever à 1.3. Les données précoces 0-RTT sont désactivées : une requête précoce ne peut donc pas être rejouée.
  • RFC 7301, ALPN : la poignée de main TLS choisit h2 ou http/1.1.
  • RFC 9110, requêtes Range : une seule plage d'octets sur GET et HEAD, avec une réponse 206 ou 416. Une requête qui demande plusieurs plages reçoit le fichier entier avec 200, ce que le standard autorise. Les plages sont désactivées lorsque la réponse est compressée.
  • RFC 9110, If-Range : honoré uniquement avec un validateur fort, comme l'exige le standard.
  • RFC 9110, codage de contenu : Brotli, gzip et Zstandard. Les valeurs de qualité indiquées dans Accept-Encoding sont respectées, et q=0 signifie que le client refuse cet encodage. Les réponses compressées portent Vary: Accept-Encoding et un ETag faible. Les flux d'événements ne sont jamais compressés.
  • RFC 9110, Retry-After : envoyé avec 429 (le temps restant dans la fenêtre de limitation de débit), avec 503 pendant le drainage ou l'arrêt du serveur, et avec 529 en cas de surcharge.
  • RFC 6585, 429 Too Many Requests : la limitation de débit par IP répond 429 avec Retry-After.
  • RFC 9110, dates HTTP : les dates des en-têtes sont lues et écrites au format standard.
  • RFC 10008, la méthode QUERY : acceptée avec son corps, que PHP lit de la même façon que le corps d'un POST. Elle a sa propre limite de taille de corps. Une requête QUERY sans Content-Type reçoit 400.
  • RFC 7578, multipart/form-data : l'upload de fichiers fonctionne comme dans n'importe quelle configuration PHP.
  • RFC 9113 et RFC 6265, en-têtes Cookie fractionnés : lorsqu'un client envoie Cookie sur plusieurs lignes d'en-tête, ce que font souvent les clients HTTP/2, OxPHP les réunit en une seule avant que PHP ne les voie.
  • RFC 8615, URI « well-known » : les chemins sous /.well-known/ sont servis, alors même que les autres chemins commençant par un point sont bloqués. Les fichiers PHP de ce répertoire ne sont jamais exécutés.
  • RFC 1918, RFC 4193 et RFC 3927, réseaux privés : le mot-clé private de la liste des proxys de confiance couvre toutes ces plages. Le NAT de niveau opérateur (RFC 6598) n'en fait pas partie et doit être ajouté à la main.
  • RFC 7034, X-Frame-Options : SAMEORIGIN par défaut, envoyé avec une directive CSP frame-ancestors assortie et X-Content-Type-Options: nosniff. Les en-têtes définis par votre application ont la priorité.

Quelques standards extérieurs à la série des RFC sont aussi couverts :

Partiellement implémentés

  • RFC 3875, CGI/1.1 : les variables CGI standard sont dans $_SERVER, et chaque en-tête de requête arrive sous la forme HTTP_*. Lacunes : un en-tête envoyé sur plusieurs lignes n'est pas réuni en une seule valeur, ce que le standard exige. $_SERVER garde la dernière ligne et l'API de requête la première. REMOTE_HOST n'est pas défini.
  • RFC 7239, Forwarded : OxPHP lit Forwarded et X-Forwarded-* venant des proxys de confiance, et CF-Connecting-IP derrière Cloudflare. Lacunes : une valeur entre guillemets qui contient une virgule ou un point-virgule est coupée au mauvais endroit. X-Real-IP n'est pas pris en charge.
  • RFC 9110, requêtes conditionnelles : les fichiers statiques prennent en charge If-None-Match et If-Modified-Since et répondent 304. Lacunes : If-Match, If-Unmodified-Since et 412 Precondition Failed.
  • RFC 9111, cache HTTP : les fichiers statiques reçoivent un Cache-Control avec un max-age configurable, ainsi que ETag, Last-Modified et Vary. Lacunes : immutable est absent, et chaque fichier reçoit la même politique, quels que soient son type ou son chemin.
  • RFC 9110, méthodes de requête : les corps sont lus pour POST, PUT, PATCH, DELETE et QUERY, et un corps trop volumineux est refusé avec 413 avant d'être lu. Lacunes : un fichier statique répond à toutes les méthodes, POST et DELETE compris, avec 200 et son contenu, là où nginx répond 405 avec un en-tête Allow.
  • RFC 7617, authentification Basic : l'en-tête Authorization parvient à PHP sous la forme HTTP_AUTHORIZATION. Lacunes : PHP_AUTH_USER, PHP_AUTH_PW et AUTH_TYPE ne sont pas renseignés.
  • RFC 3986, URI : le décodage des pourcentages et l'analyse de l'hôte fonctionnent, adresses IPv6 comprises, et les chemins contenant des segments . ou .. reçoivent 404. Lacunes : la barre oblique finale est supprimée avant le routage, si bien que /dir sert l'index du répertoire sans rediriger vers /dir/, et qu'un fichier répond aussi à /file/.
  • RFC 6265, cookies : les cookies que les plugins d'OxPHP posent pour eux-mêmes portent SameSite, HttpOnly, Secure et Max-Age. Les cookies de votre application passent comme d'habitude par setcookie() de PHP. Lacunes : pour une paire de cookie mal formée, cookie() de l'API de requête et $_COOKIE peuvent renvoyer des valeurs différentes.

Feuille de route

Ce sont des propositions, classées par priorité. Aucune n'est prévue pour une version précise.

Priorité haute

  • RFC 3875 : réunir un en-tête arrivé sur plusieurs lignes en une seule valeur séparée par des virgules, pour que PHP voie toute la chaîne X-Forwarded-For laissée par une série de proxys.
  • RFC 7617 : renseigner PHP_AUTH_USER et PHP_AUTH_PW à partir de l'authentification Basic. Les applications qui les lisent obtiennent aujourd'hui des valeurs vides, sans aucune erreur.
  • RFC 6797, HSTS : envoyer Strict-Transport-Security sur chaque réponse HTTPS, fichiers statiques et pages d'erreur compris. PHP ne peut pas l'ajouter aux fichiers statiques, car il ne voit jamais ces requêtes.

Priorité moyenne

  • RFC 7239 : analyser correctement les valeurs entre guillemets dans Forwarded.
  • RFC 9110 : répondre 405 avec Allow: GET, HEAD lorsqu'un fichier statique reçoit une autre méthode, comme le fait nginx.
  • RFC 3986 : rediriger /dir vers /dir/ avec 301 en mode Traditionnel, pour que les liens relatifs des applications anciennes se résolvent.
  • Champs d'en-tête RateLimit (un draft de l'IETF) : envoyer RateLimit et RateLimit-Policy, pour qu'un client voie sa limite avant de l'atteindre. Aujourd'hui, les en-têtes X-RateLimit-* n'apparaissent que sur une 429.
  • W3C Server-Timing : indiquer l'attente en file et le temps d'exécution PHP dans un en-tête Server-Timing. OxPHP mesure déjà les deux pour les métriques et les traces.

Priorité basse

  • RFC 9110 : If-Match, If-Unmodified-Since et 412 pour les fichiers statiques. Les fichiers statiques sont en lecture seule, cela compterait donc rarement.
  • RFC 6455 et RFC 8441, WebSocket : WebSocket sur HTTP/1.1 et HTTP/2. La conception est encore à l'étude.
  • RFC 8297, Early Hints : 103 Early Hints, pour que les navigateurs puissent commencer à précharger les ressources avant que la réponse soit prête.
  • RFC 8446, certificats client : TLS mutuel pour les environnements zero trust.
  • RFC 9114, HTTP/3, avec RFC 7838, Alt-Svc : un chantier important, et il n'est pas certain qu'il soit rentable.

Envisagés puis écartés

La frontière passe entre la gestion de HTTP, qui est le travail du serveur, et le contenu propre à un site donné, qui ne l'est pas.

  • RFC 9116, security.txt : le fichier liste les contacts de sécurité de l'exploitant du site, et le serveur ne les connaît pas. Un fichier par défaut intégré serait vide, ou désignerait à tort les mainteneurs d'OxPHP. Placez le fichier dans la racine du document et OxPHP le sert comme n'importe quel autre fichier statique. nginx, Apache et FrankenPHP n'en génèrent pas non plus.
  • RFC 3875, PATH_TRANSLATED : le standard la recommande lorsque PATH_INFO est défini. Elle sert aux scripts CGI qui traitent un autre fichier. Dans OxPHP, le script exécuté est toujours SCRIPT_FILENAME, et ni la configuration habituelle nginx avec PHP-FPM ni php -S ne définissent cette variable. Sa valeur serait construite à partir du PATH_INFO envoyé par le client, si bien qu'un code ancien qui inclut $_SERVER['PATH_TRANSLATED'] chargerait un fichier choisi par le client.
  • RFC 7540, mise à niveau h2c : la RFC 9113 a abandonné la poignée de main Upgrade: h2c. OxPHP sert HTTP/2 sans TLS aux clients avec connaissance préalable, et cela suffit.

Voir aussi

Une erreur ? Signalez-la →