En-têtes HTTP personnalisés: conventions de dénomination

1115

Plusieurs de nos utilisateurs nous ont demandé d'inclure des données relatives à leur compte dans les en-têtes HTTP des demandes que nous leur envoyons, voire des réponses qu'ils obtiennent de notre API. Quelle est la convention générale pour ajouter des en-têtes HTTP personnalisés, en termes de dénomination , de format ... etc.

Aussi, n'hésitez pas à publier toute utilisation intelligente de ceux-ci que vous êtes tombé sur le Web; Nous essayons de l'implémenter en utilisant ce qui est le mieux comme cible :)

Julien Genestoux
la source
25
Sachez que les pare-feu peuvent supprimer les champs d'en-tête de réponse. Certains suppriment tout ce qui n'est pas mentionné dans la RFC 2616 (juin 1999, HTTP 1.1). Le côté client devrait toujours être utilisable sans les nouveaux champs.
stesch
5
Notez que le commentaire par @stesch ne s'applique pas lorsque vous utilisez HTTP S .
code_dredd
1
Notez que le commentaire de @code_dredd est une légende urbaine. Les pare-feu peuvent filtrer le contenu HTTPS. Voir howtoforge.com/filtering-https-traffic-with-squid et watchguard.com/help/docs/wsm/xtm_11/en-us/content/en-us/…
stesch
@stesch Étant donné que votre article transforme essentiellement le proxy en quelque chose de similaire à un MiTM (il prend une connexion client cryptée puis en crée une nouvelle), alors vous pouvez faire presque n'importe quoi, mais ce fait annule le cryptage à partir du PoV b / du proxy c il décrypte le contenu du client lui-même. Dans ce cas, à partir du PoV du proxy, c'est essentiellement comme si vous n'utilisiez pas HTTPS à la 1ère place ...
code_dredd

Réponses:

1172

La recommandation est était de commencer leur nom par « X- ». Par exemple X-Forwarded-For, X-Requested-With. Ceci est également mentionné dans la section 5 de la RFC 2047 .


Mise à jour 1 : en juin 2011, le premier projet de l'IETF a été publié pour déprécier la recommandation d'utiliser le préfixe «X-» pour les en-têtes non standard. La raison en est que lorsque les en-têtes non standard préfixés avec "X-" deviennent standard, la suppression du préfixe "X-" rompt la compatibilité en arrière, forçant les protocoles d'application à prendre en charge les deux noms (par exemple, x-gzipet gzipsont désormais équivalents). Donc, la recommandation officielle est de simplement les nommer de manière raisonnable sans le préfixe "X-".


Mise à jour 2 : en juin 2012, la dépréciation de la recommandation d'utiliser le préfixe "X-" est devenue officielle comme RFC 6648 . Voici des citations pertinentes:

3. Recommandations pour les créateurs de nouveaux paramètres

...

  1. NE DEVRAIT PAS préfixer leurs noms de paramètres avec "X-" ou des constructions similaires.

4. Recommandations pour les concepteurs de protocoles

...

  1. NE DEVRAIT PAS interdire l'enregistrement de paramètres avec un préfixe "X" ou des constructions similaires.

  2. NE DOIT PAS stipuler qu'un paramètre avec un préfixe "X" ou des constructions similaires doit être compris comme non normalisé.

  3. NE DOIT PAS stipuler qu'un paramètre sans préfixe "X" ou constructions similaires doit être compris comme normalisé.

Notez que "NE DEVRAIT PAS" ("découragé") n'est pas la même chose que "NE DOIT PAS" ("interdit"), voir aussi RFC 2119 pour une autre spécification sur ces mots clés. En d'autres termes, vous pouvez continuer à utiliser des en-têtes préfixés "X-", mais ce n'est plus officiellement recommandé et vous ne pouvez certainement pas les documenter comme s'ils étaient de norme publique.


Résumé :

  • la recommandation officielle est de simplement les nommer sensiblement sans le préfixe "X-"
  • vous pouvez continuer à utiliser des en-têtes préfixés "X-", mais ce n'est plus officiellement recommandé et vous ne pouvez certainement pas les documenter comme s'ils étaient de norme publique
BalusC
la source
306
Tout comme il y a beaucoup d'enfants qui ne finiront jamais comme des athlètes professionnels, de nombreux en-têtes personnalisés ne finiront jamais comme des normes. Je suis enclin à garder le "X-" là-dessus.
G-Mac
19
@ G-Mac d'accord. Il y a tellement d'en-têtes personnalisés qui ne finiront jamais par être standardisés. Les rares qui le font, il est facile de simplement modifier votre code de if (header == "x-gzip")à if (header == "x-gzip" || header == "gzip"). Quant à votre analogie, en voici une autre: c'est comme les militaires qui disent "Oh, c'est gênant de changer quelqu'un de soldat en général. Donc, à partir de maintenant, vous êtes tous des généraux. Maintenant, nous n'avons plus besoin de faire autant de travail"
Cole Johnson
24
@ColeJohnson Je ne sais pas si cette analogie fonctionne. Le problème ici est qu'il n'y a pas de point central pour changer le nom. Chaque extrait de code qui attend x-gzip doit maintenant être modifié, ou l'ancien en-tête doit continuer à être utilisé en plus du nouveau. Il est préférable d'utiliser la RFC 6648.
vinod
4
@Vinod oui. Cela a du sens, mais il y a tellement de normes proposées qui ne verront jamais le jour. Pour les types de fichiers, bien sûr; déposez le X-préfixe. Je suis contre, mais allez-y et faites-le. Pour les en-têtes OTOH, ne le laissez pas tomber. Il est facile de regarder et de dire "oh, ce n'est pas standard; je peux l'ignorer" vs "il y a ces en- X-têtes non standard , et puis il y en a un que je ne reconnais pas; puis-je l'ignorer en toute sécurité?"
Cole Johnson
21
Bien que le ton de la réponse de Cweekly soit inutilement défensif, je pense qu'il a raison, et son argument résout le problème illustré dans ce fil de commentaires. En bref, n'essayez pas d'identifier si un en-tête "obtiendra son diplôme" ou non; déterminez plutôt s'il s'agit d'un en-tête privé ou public (spécifique à l'application ou "générique" / "global"). Pour les en-têtes privés, utilisez facultativement X-pour éviter tout conflit avec les en-têtes publics (grâce à la RFC6648, qui traite des en-têtes publics), et utilisez en outre définitivement un préfixe privé arbitraire. Pour les en-têtes publics, ne les utilisez X-en aucun cas.
TNE
535

La question mérite d'être relue. La véritable question posée n'est pas similaire aux préfixes de fournisseurs dans les propriétés CSS, où la pérennité et la réflexion sur le support des fournisseurs et les normes officielles sont appropriées. La véritable question posée est plus proche du choix des noms de paramètres de requête d'URL. Personne ne devrait se soucier de ce qu'ils sont. Mais l'espacement des noms des noms personnalisés est une chose parfaitement valide - et courante et correcte - à faire.

Justification:
Il s'agit de conventions entre développeurs pour des en-têtes personnalisés et spécifiques à l'application - « données pertinentes pour leur compte » - qui n'ont rien à voir avec les fournisseurs, les organismes de normalisation ou les protocoles à mettre en œuvre par des tiers, sauf que le développeur en question doit simplement éviter les noms d'en-tête qui peuvent avoir une autre utilisation prévue par les serveurs, les mandataires ou les clients. Pour cette raison, les exemples "X-Gzip / Gzip" et "X-Forwarded-For / Forwarded-For" sont sans objet. La question posée concerne les conventions dans le contexte d'une API privée, semblable aux conventions de dénomination des paramètres de requête URL. C'est une question de préférence et d'espacement des noms; préoccupations concernant le fait que "X-ClientDataFoo" soit pris en charge par tout proxy ou fournisseur sans le "X"

Il n'y a rien de spécial ou de magique dans le préfixe "X-", mais cela aide à préciser qu'il s'agit d'un en-tête personnalisé. En fait, la RFC-6648 et al aident à renforcer le cas de l'utilisation d'un préfixe "X-", car - comme les fournisseurs de clients et de serveurs HTTP abandonnent le préfixe - votre application privée, API privée, données personnelles- le mécanisme de passage est de plus en plus isolé contre les collisions d'espace de nom avec le petit nombre de noms d'en-tête réservés officiels. Cela dit, ma préférence et ma recommandation personnelles sont d'aller plus loin et de faire par exemple "X-ACME-ClientDataFoo" (si votre société de widgets est "ACME").

À mon humble avis, la spécification IETF n'est pas suffisamment spécifique pour répondre à la question du PO, car elle ne fait pas la distinction entre des cas d'utilisation complètement différents: (A) les fournisseurs introduisant de nouvelles fonctionnalités applicables à l'échelle mondiale comme "Forwarded-For" d'une part, par rapport à (B) les développeurs d'applications transmettant des chaînes spécifiques à l'application vers / depuis le client et le serveur. La spécification ne concerne que le premier (A). La question ici est de savoir s'il existe des conventions pour (B). Il y a. Ils impliquent de regrouper les paramètres par ordre alphabétique et de les séparer des nombreux en-têtes de type (A) pertinents pour les normes. L'utilisation du préfixe "X-" ou "X-ACME-" est pratique et légitime pour (B), et n'entre pas en conflit avec (A). Plus les fournisseurs cesseront d'utiliser "X-" pour (A), plus les (B) deviendront distincts.

Exemple:
Google (qui a un peu de poids dans les différents organismes de normalisation) utilise - à ce jour, 20141102 dans cette légère modification de ma réponse - actuellement "X-Mod-Pagespeed" pour indiquer la version de son module Apache impliqués dans la transformation d'une réponse donnée. Quelqu'un suggère-t-il vraiment que Google devrait utiliser "Mod-Pagespeed", sans le "X-", et / ou demander à l'IETF de bénir son utilisation?

Résumé:
si vous utilisez des en-têtes HTTP personnalisés (comme alternative parfois appropriée aux cookies) dans votre application pour transmettre des données vers / depuis votre serveur, et ces en-têtes ne sont explicitement PAS destinés à être utilisés en dehors du contexte de votre application, les espacer avec un préfixe "X-" ou "X-FOO-" est une convention raisonnable et courante.

chaque semaine
la source
52
Je vous serais reconnaissant si des downvoters de mon commentaire pourraient expliquer quelle partie de ma réponse ils trouvent répréhensible. Je ne me soucie pas beaucoup de mon score de réputation, mais je suis vraiment curieux. Où se situe le désaccord? Merci.
hebdomadaire
56
Je suis entièrement d'accord avec votre réponse et c'est la seule réponse ici qui répond à la question réelle posée. Nous parlons ici d'en-têtes personnalisés et spécifiques à l'application, qui ne doivent jamais être normalisés dans les normes HTTP. Existe-t-il une convention commune pour ceux que les gens ont tendance à utiliser? (comme les préfixant avec "_" peut - être à savoir: ( "_ClientDataFoo")?
Marchy
14
Merci Marchy, oui, la réponse acceptée ne répond pas à la question posée. La dépréciation par l'IETF du préfixe "X-" pour les en-têtes non standard (mais génériques) n'est pas pertinente pour les en-têtes spécifiques à une application personnalisée qui ne seront jamais standardisés. Pour répondre à votre question, selon mon expérience et mon expérience (16 ans de webdev), la meilleure convention est d'utiliser les "X-ACME-ClientData" précités. "X-" bc ce n'est pas standard (ce ne sera jamais le cas, c'est pourquoi la dépréciation de l'IETF est discutable ici), "ACME-" pour le nommer dans votre entreprise "ACME" ou application spécifique, et "ClientData" peut être n'importe quoi nom sémantique que vous aimez. :)
semaines le
5
@DarrelMiller ... d'où la recommandation d'utiliser X-ACMECO-WIDGET-FOO. J'insiste sur le fait que, pour la question du PO telle que posée, l'utilisation de X- n'est tout simplement pas contre-indiquée par la RFC-6648 et similaires. Si vous êtes un fournisseur fournissant un cadre, une bibliothèque ou un module à utiliser dans les projets d'autres personnes, c'est une autre histoire, et suivez certainement cette RFC à un T. Mais c'est juste théorique pour les applications individuelles individuelles, où la personnalisation Les conventions de dénomination des en-têtes spécifiques à l'application sont en fait des API complètement privées. Comment pourraient-ils entrer en conflit avec les noms de "tout le monde"? À qui seraient-ils?
semaines
11
Honnêtement, j'ai un peu de mal à comprendre le raisonnement RFC. Certes, si et quand le paramètre est normalisé, il y aura à la fois des versions x et non x. Ce n'est un problème que si le comportement des versions x et non x est identique. J'ai trébuché ici parce que je cherche à ajouter un en-tête "au nom de" à mon API. Il pourrait devenir public un jour (car il s'agit d'un type d'utilisation courant). Si j'ai utilisé "On-Behalf-Of" et qu'un jour ils ajoutent cela en tant qu'en-tête standard, quelles sont les chances que ma sémantique soit identique à celle normalisée?
fool4jesus
62

Le format des en-têtes HTTP est défini dans la spécification HTTP. Je vais parler de HTTP 1.1, dont la spécification est RFC 2616 . Dans la section 4.2, «En-têtes de message», la structure générale d'un en-tête est définie:

   message-header = field-name ":" [ field-value ]
   field-name     = token
   field-value    = *( field-content | LWS )
   field-content  = <the OCTETs making up the field-value
                    and consisting of either *TEXT or combinations
                    of token, separators, and quoted-string>

Cette définition repose sur deux piliers principaux, le jeton et le TEXTE. Les deux sont définis dans la section 2.2, «Règles de base». Le jeton est:

   token          = 1*<any CHAR except CTLs or separators>

À son tour reposant sur CHAR, CTL et séparateurs:

   CHAR           = <any US-ASCII character (octets 0 - 127)>

   CTL            = <any US-ASCII control character
                    (octets 0 - 31) and DEL (127)>

   separators     = "(" | ")" | "<" | ">" | "@"
                  | "," | ";" | ":" | "\" | <">
                  | "/" | "[" | "]" | "?" | "="
                  | "{" | "}" | SP | HT

TEXT c'est:

   TEXT           = <any OCTET except CTLs,
                    but including LWS>

Où LWS est un espace blanc linéaire, dont je ne reproduirai pas la définition, et OCTET est:

   OCTET          = <any 8-bit sequence of data>

Une note accompagne la définition:

The TEXT rule is only used for descriptive field contents and values
that are not intended to be interpreted by the message parser. Words
of *TEXT MAY contain characters from character sets other than ISO-
8859-1 [22] only when encoded according to the rules of RFC 2047
[14].

Donc, deux conclusions. Tout d'abord, il est clair que le nom de l'en-tête doit être composé d'un sous-ensemble de caractères ASCII - alphanumériques, une certaine ponctuation, pas beaucoup d'autre. Deuxièmement, rien dans la définition d'une valeur d'en- tête ne la restreint à ASCII ou exclut les caractères 8 bits: elle est explicitement composée d'octets, avec uniquement des caractères de contrôle interdits (notez que CR et LF sont considérés comme des contrôles). En outre, le commentaire sur la production TEXT implique que les octets doivent être interprétés comme étant en ISO-8859-1, et qu'il existe un mécanisme de codage (ce qui est horrible, d'ailleurs) pour représenter les caractères en dehors de ce codage.

Donc, pour répondre à @BalusC en particulier, il est assez clair que selon la spécification, les valeurs d'en-tête sont en ISO-8859-1. J'ai envoyé des caractères haut 8859-1 (en particulier, certaines voyelles accentuées utilisées en français) dans un en-tête à partir de Tomcat, et les ai fait interpréter correctement par Firefox, donc dans une certaine mesure, cela fonctionne dans la pratique ainsi qu'en théorie (bien qu'il s'agisse d'un en-tête Emplacement, qui contient une URL, et que ces caractères ne sont pas autorisés dans les URL, c'était en fait illégal, mais sous une règle différente!).

Cela dit, je ne compterais pas sur ISO-8859-1 pour tous les serveurs, proxys et clients, je m'en tiendrai donc à l'ASCII pour une programmation défensive.

Tom Anderson
la source
3
La nouvelle spécification HTTP RFC7230 indique que "les champs d'en-tête nouvellement définis DEVRAIENT limiter leurs valeurs de champ aux octets US-ASCII."
Robert Tupelo-Schneck
23

La RFC6648 vous recommande de supposer que votre en-tête personnalisé "pourrait devenir standardisé, public, couramment déployé ou utilisable sur plusieurs implémentations". Par conséquent, il recommande de ne pas le préfixer avec "X-" ou des constructions similaires.

Cependant, il existe une exception "lorsqu'il est extrêmement improbable que [votre en-tête] soit un jour normalisé". Pour ces en-têtes "spécifiques à l'implémentation et à usage privé", la RFC indique qu'un espace de noms tel qu'un préfixe de fournisseur est justifié.

Edward Brey
la source
6
"RFC6648 vous recommande de supposer que votre en-tête personnalisé" pourrait devenir standardisé, public, couramment déployé ou utilisable sur plusieurs implémentations. "Je pense que cela donne une raison d'utiliser le X-préfixe car il est plus probable que quelque chose sans aucun préfixe devienne standardisé.
Konrad
@Konrad Si vous supposez que l'en- tête similaire de quelqu'un d'autre (et non votre en-tête) pourrait devenir standardisé, vous pourriez éviter un conflit avec X-, mais c'est une hypothèse différente de celle de la RFC6648. L'exception de la RFC tient compte des conflits potentiels entre un futur en-tête standard et un en-tête d'un autre fournisseur dont la technologie peut s'intégrer à la vôtre par le biais d'une fusion d'entreprise, etc. C'est pourquoi l'exception appelle un préfixe de fournisseur.
Edward Brey
17

La modification, ou plus correctement, l' ajout d' en-têtes HTTP supplémentaires est un excellent outil de débogage de code si rien d'autre.

Lorsqu'une demande d'URL renvoie une redirection ou une image, il n'y a pas de "page" html pour écrire temporairement les résultats du code de débogage - du moins pas celui qui est visible dans un navigateur.

Une approche consiste à écrire les données dans un fichier journal local et à afficher ce fichier ultérieurement. Une autre consiste à ajouter temporairement des en-têtes HTTP reflétant les données et les variables en cours de débogage.

J'ajoute régulièrement des en-têtes HTTP supplémentaires comme X-fubar-somevar: ou X-testing-someresult: pour tester les choses - et j'ai trouvé beaucoup de bugs qui auraient autrement été très difficiles à retracer.

g1smd
la source
2
Pourquoi devrait-il utiliser ce "standard"? Les en-têtes fonctionnent de la même manière. Même avec un préfixe "WHO_EVER_READS_THIS_IS_DUMB_" ...
L'incroyable
16

Le registre des noms de champ d'en-tête est défini dans RFC3864 , et il n'y a rien de spécial avec "X-".

Pour autant que je sache, il n'y a pas de directives pour les en-têtes privés; dans le doute, évitez-les. Ou jetez un œil à la structure d'extension HTTP ( RFC 2774 ).

Il serait intéressant de mieux comprendre le cas d'utilisation; pourquoi les informations ne peuvent-elles pas être ajoutées au corps du message?

Julian Reschke
la source
13
La principale raison pour laquelle je considère certains en-têtes personnalisés est pour que je puisse prendre des décisions de routage sans avoir à analyser le corps ...
Rozwel