Encabezados HTTP personalizados: convenciones de nomenclatura

1115

Varios de nuestros usuarios nos han pedido que incluyamos datos relativos a su cuenta en los encabezados HTTP de las solicitudes que les enviamos, o incluso las respuestas que obtienen de nuestra API. ¿Cuál es la convención general para agregar encabezados HTTP personalizados, en términos de nomenclatura , formato ... etc.

Además, siéntase libre de publicar cualquier uso inteligente de estos que haya encontrado en la web; Estamos tratando de implementar esto usando lo mejor que hay como objetivo :)

Julien Genestoux
fuente
25
Tenga en cuenta que los firewalls pueden eliminar los campos de encabezado de respuesta. Algunos eliminan todo lo que no se menciona en RFC 2616 (junio de 1999, HTTP 1.1). El lado del cliente aún debe ser utilizable sin los nuevos campos.
stesch
55
Tenga en cuenta que el comentario de @stesch no se aplica cuando se utiliza HTTP S .
code_dredd
1
Tenga en cuenta que el comentario de @code_dredd es una leyenda urbana. Los firewalls pueden filtrar el contenido HTTPS. Vea howtoforge.com/filtering-https-traffic-with-squid y watchguard.com/help/docs/wsm/xtm_11/en-us/content/en-us/…
stesch el
@stesch Dado que su artículo básicamente convierte el proxy en algo similar a un MiTM (toma una conexión de cliente cifrada y luego crea una nueva), entonces seguro, puede hacer casi cualquier cosa, pero ese hecho niega el cifrado del PoV del proxy b / c está descifrando el contenido del cliente en sí. En ese caso, desde el PoV del proxy, es básicamente como si no estuvieras usando HTTPS en primer lugar ...
code_dredd

Respuestas:

1172

La recomendación se fue para iniciar su nombre con "X". Por ejemplo X-Forwarded-For, X-Requested-With. Esto también se menciona en la sección 5 de RFC 2047 .


Actualización 1 : en junio de 2011, se publicó el primer borrador de IETF para desaprobar la recomendación de usar el prefijo "X-" para encabezados no estándar. La razón es que cuando los encabezados no estándar con el prefijo "X-" se convierten en estándar, la eliminación del prefijo "X-" rompe la compatibilidad con versiones anteriores, lo que obliga a los protocolos de aplicación a admitir ambos nombres (por ejemplo, x-gzipy gzipahora son equivalentes). Por lo tanto, la recomendación oficial es nombrarlos con sensatez sin el prefijo "X-".


Actualización 2 : en junio de 2012, la depreciación de la recomendación de usar el prefijo "X-" se hizo oficial como RFC 6648 . A continuación hay citas de relevancia:

3. Recomendaciones para creadores de nuevos parámetros

...

  1. NO DEBE prefijar sus nombres de parámetros con "X-" o construcciones similares.

4. Recomendaciones para diseñadores de protocolos

...

  1. NO DEBE prohibir el registro de parámetros con un prefijo "X-" o construcciones similares.

  2. NO DEBE estipular que un parámetro con un prefijo "X-" o construcciones similares deba entenderse como no estandarizado.

  3. NO DEBE estipular que un parámetro sin un prefijo "X-" o construcciones similares debe entenderse como estandarizado.

Tenga en cuenta que "NO DEBE" ("desaconsejado") no es lo mismo que "NO DEBE" ("prohibido"), consulte también RFC 2119 para otra especificación sobre esas palabras clave. En otras palabras, puede seguir usando encabezados con el prefijo "X-", pero ya no se recomienda oficialmente y definitivamente no puede documentarlos como si fueran estándares públicos.


Resumen :

  • la recomendación oficial es simplemente nombrarlos con sensatez sin el prefijo "X-"
  • puede seguir usando encabezados con prefijo "X-", pero ya no se recomienda oficialmente y definitivamente no puede documentarlos como si fueran estándares públicos
BalusC
fuente
306
Así como hay muchos niños que nunca terminarán como atletas profesionales, muchos encabezados personalizados nunca terminarán como estándares. Me inclino a mantener la "X-" en esos.
G-Mac
19
@ G-Mac estuvo de acuerdo. Hay así que muchos jefes de encargo que nunca se va a terminar estandarizada. De los pocos que lo hacen, es fácil editar su código de if (header == "x-gzip")a if (header == "x-gzip" || header == "gzip"). En cuanto a su analogía, aquí hay otra: es como el ejército diciendo "Oh, es problemático cambiar a alguien de Privado a General. Entonces, de ahora en adelante, todos ustedes son Generales. Ahora no necesitamos hacer tanto trabajo".
Cole Johnson
24
@ColeJohnson No estoy seguro si esa analogía funciona. El problema aquí es que no hay un punto central en el que pueda cambiar el nombre. Cada fragmento de código que espera que x-gzip ahora tenga que cambiarse, o el encabezado anterior debe continuar utilizándose además del nuevo. Es preferible ir con RFC 6648.
Vinod
44
@Vinod sí. Tiene sentido, pero hay tantos estándares propuestos que nunca verán la luz del día. Para tipos de archivo, seguro; Suelta el X-prefijo. Estoy en contra, pero adelante y hazlo. Para encabezados OTOH, no lo suelte. Hace que sea fácil mirar y decir: "oh, no es estándar; puedo ignorarlo" frente a "están esos X-encabezados no estándar , y luego está este que no reconozco; ¿puedo ignorarlo de manera segura?"
Cole Johnson
21
Aunque el tono de la respuesta semanal es innecesariamente defensivo, creo que tiene razón, y su punto resuelve el problema ilustrado en este hilo de comentarios. En resumen, no intente identificar si un encabezado se "graduará" o no; en su lugar, determine si es un encabezado privado o público (específico de la aplicación o "genérico" / "global"). Para encabezados privados, opcionalmente use X-para asegurar que no haya conflicto con los encabezados públicos (gracias a RFC6648, que trata con encabezados públicos), y además definitivamente use un prefijo privado arbitrario. Para encabezados públicos, no lo use X-bajo ninguna circunstancia.
TNE
535

La pregunta merece ser releída. La pregunta real que se hace no es similar a los prefijos de proveedor en las propiedades de CSS, donde es apropiado tener en cuenta el futuro y pensar en el soporte del proveedor y los estándares oficiales. La pregunta real es más parecida a elegir nombres de parámetros de consulta de URL. A nadie debería importarle lo que son. Pero el espaciado de nombres de los personalizados es una cosa perfectamente válida, común y correcta.

Justificación:
Se trata de convenciones entre desarrolladores para encabezados personalizados específicos de la aplicación - " datos relevantes para su cuenta " - que no tienen nada que ver con proveedores, organismos de estándares o protocolos que sean implementados por terceros, excepto que el desarrollador en cuestión simplemente necesita evitar los nombres de encabezado que pueden tener otro uso previsto por servidores, servidores proxy o clientes. Por esta razón, los ejemplos "X-Gzip / Gzip" y "X-Fordered-For / Forwards-For" dados son discutibles. La pregunta planteada es acerca de las convenciones en el contexto de una API privada, similar a las convenciones de nomenclatura de parámetros de consulta de URL. Es una cuestión de preferencia y espacio entre nombres; Preocupaciones acerca de que "X-ClientDataFoo" sea compatible con cualquier proxy o proveedor sin la "X"

No hay nada especial o mágico sobre el prefijo "X-", pero ayuda a dejar en claro que es un encabezado personalizado. De hecho, RFC-6648 y otros ayudan a reforzar el caso para el uso de un prefijo "X-", porque - como los proveedores de clientes y servidores HTTP abandonan el prefijo - su aplicación específica, API privada, datos personales- el mecanismo de paso se está aislando aún mejor contra las colisiones de espacio de nombres con el pequeño número de nombres de encabezados reservados oficiales. Dicho esto, mi preferencia personal y recomendación es ir un paso más allá y hacer, por ejemplo, "X-ACME-ClientDataFoo" (si su empresa de widgets es "ACME").

En mi humilde opinión, la especificación IETF es insuficientemente específica para responder la pregunta del OP, ya que no distingue entre casos de uso completamente diferentes: (A) proveedores que introducen nuevas características aplicables globalmente como "Reenviado para" por un lado, vs. (B) desarrolladores de aplicaciones que pasan cadenas específicas de la aplicación a / desde el cliente y el servidor. La especificación solo se refiere a la primera, (A). La pregunta aquí es si hay convenciones para (B). Existen. Implican agrupar los parámetros alfabéticamente y separarlos de los muchos encabezados relevantes para estándares del tipo (A). Usar el prefijo "X-" o "X-ACME-" es conveniente y legítimo para (B), y no entra en conflicto con (A). Mientras más vendedores dejen de usar "X-" para (A), más claramente se diferenciarán los (B).

Ejemplo:
Google (que tiene un poco de peso en los diferentes organismos de estándares) está, a partir de hoy, 20141102 en esta pequeña edición a mi respuesta, actualmente está usando "X-Mod-Pagespeed" para indicar la versión de su módulo Apache involucrado en la transformación de una respuesta dada. ¿Alguien realmente sugiere que Google debería usar "Mod-Pagespeed", sin la "X-", y / o pedirle al IETF que bendiga su uso?

Resumen:
si está utilizando encabezados HTTP personalizados (como una alternativa a veces apropiada para las cookies) dentro de su aplicación para pasar datos a / desde su servidor, y estos encabezados, explícitamente, NO están destinados a ser utilizados fuera del contexto de su aplicación, espaciarlos con un prefijo "X-" o "X-FOO-" es una convención razonable y común.

cada dos semanas
fuente
52
Agradecería que cualquier votante negativo de mi comentario pudiera explicar qué parte de mi respuesta encuentran objetable. No me importa mucho mi puntaje de reputación, pero tengo curiosidad genuina. ¿Dónde se encuentra el desacuerdo? Gracias.
cada
56
Estoy completamente de acuerdo con su respuesta y es la única respuesta aquí que responde a la pregunta real. Aquí estamos hablando de encabezados personalizados específicos de la aplicación, que nunca se estandarizarán en los estándares HTTP. ¿Existe una convención común para estos que las personas tienden a usar? (como prefijarlos con "_" quizás? es decir: ("_ClientDataFoo")
Marchy
14
Gracias Marchy, sí, la respuesta aceptada no responde a la pregunta formulada. El desuso de IETF del prefijo "X-" para encabezados no estándar (pero genéricos) es irrelevante para los encabezados personalizados específicos de la aplicación que nunca se estandarizarán. Para responder a su pregunta, en mi opinión y experiencia (16 años de webdev), la mejor convención es utilizar el "X-ACME-ClientData" mencionado anteriormente. "X-" bc no es estándar (ni lo será nunca, por lo que la desaprobación de IETF es discutible aquí), "ACME-" para asignarle un espacio de nombres a su compañía "ACME" o aplicación específica, y "ClientData" puede ser lo que sea Nombre semántico que te gusta. :)
cada
55
@DarrelMiller ... de ahí la recomendación de usar X-ACMECO-WIDGET-FOO. Insisto en que, para la pregunta del OP según lo solicitado, el uso de X- simplemente no está contraindicado por RFC-6648 y similares. Si usted es un proveedor que proporciona un marco, una biblioteca o un módulo para su uso en proyectos de otras personas, esa es una historia diferente, y de todos modos siga esa RFC a una T. Pero es discutible para aplicaciones individuales únicas, donde personalizadas las convenciones de nomenclatura de encabezado específicas de la aplicación son, de hecho, API completamente privadas. ¿Cómo chocarían con los nombres de "todos los demás"? ¿De quién serían esos?
cweekly
11
Sinceramente, me cuesta un poco entender el razonamiento de RFC. De acuerdo con esto, si el parámetro está estandarizado y siempre, habrá versiones x y no x. Eso es solo un problema si el comportamiento de las versiones x y no x es idéntico. Me tropecé aquí porque estoy buscando agregar un encabezado "en nombre de" a mi API. Podría hacerse público algún día (ya que es un tipo de caso de uso común). Si usé "On-Behalf-Of" y algún día lo agregan como un encabezado estándar, ¿cuáles son las probabilidades de que mi semántica sea idéntica a la estandarizada?
fool4jesus
62

El formato para los encabezados HTTP se define en la especificación HTTP. Voy a hablar sobre HTTP 1.1, cuya especificación es RFC 2616 . En la sección 4.2, 'Encabezados de mensajes', se define la estructura general de un encabezado:

   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>

Esta definición se basa en dos pilares principales, token y TEXT. Ambos se definen en la sección 2.2, 'Reglas básicas'. Token es:

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

A su vez descansa sobre CHAR, CTL y separadores:

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

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

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

TEXTO es:

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

Donde LWS es un espacio en blanco lineal, cuya definición no reproduciré, y OCTET es:

   OCTET          = <any 8-bit sequence of data>

Hay una nota que acompaña a la definición:

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].

Entonces, dos conclusiones. En primer lugar, está claro que el nombre del encabezado debe estar compuesto de un subconjunto de caracteres ASCII: alfanuméricos, algunos signos de puntuación, no mucho más. En segundo lugar, no hay nada en la definición de un valor de encabezado que lo restrinja a ASCII o excluya caracteres de 8 bits: está compuesto explícitamente de octetos, con solo caracteres de control excluidos (tenga en cuenta que CR y LF se consideran controles). Además, el comentario sobre la producción de TEXT implica que los octetos deben interpretarse como si estuvieran en ISO-8859-1, y que existe un mecanismo de codificación (que es horrible, por cierto) para representar caracteres fuera de esa codificación.

Entonces, para responder a @BalusC en particular, está bastante claro que de acuerdo con la especificación, los valores de encabezado están en ISO-8859-1. Envié caracteres de alto 8859-1 (específicamente, algunas vocales acentuadas como se usan en francés) en un encabezado de Tomcat, y Firefox las interpretó correctamente, por lo que, en cierta medida, esto funciona tanto en la práctica como en la teoría. (aunque este era un encabezado de ubicación, que contiene una URL, y estos caracteres no son legales en las URL, por lo que en realidad era ilegal, ¡pero bajo una regla diferente!).

Dicho esto, no confiaría en que ISO-8859-1 funcione en todos los servidores, servidores proxy y clientes, por lo que me apegaría a ASCII como una cuestión de programación defensiva.

Tom Anderson
fuente
3
La nueva especificación HTTP RFC7230 dice "Los campos de encabezado recientemente definidos DEBERÍAN limitar sus valores de campo a octetos US-ASCII".
Robert Tupelo-Schneck
23

RFC6648 recomienda que asuma que su encabezado personalizado "podría ser estandarizado, público, comúnmente implementado o utilizable en múltiples implementaciones". Por lo tanto, recomienda no prefijarlo con "X-" o construcciones similares.

Sin embargo, hay una excepción "cuando es extremadamente improbable que [su encabezado] alguna vez se estandarice". Para tales encabezados "específicos de implementación y de uso privado", el RFC dice que un espacio de nombres como un prefijo de proveedor está justificado.

Edward Brey
fuente
66
"RFC6648 recomienda que asuma que su encabezado personalizado" podría ser estandarizado, público, comúnmente implementado o utilizable en múltiples implementaciones ". Creo que esto da una razón para usar el X-prefijo porque es más probable que algo sin ningún prefijo se estandarice."
Konrad
@Konrad Si asume que el encabezado similar de otra persona (no el encabezado) podría estandarizarse, podría evitar un conflicto X-, pero esa es una suposición diferente a la que RFC6648 toma principalmente. La excepción de RFC explica posibles conflictos entre un encabezado estándar futuro y un encabezado de otro proveedor cuya tecnología puede integrarse con la suya a través de la fusión de la compañía, etc. Es por eso que la excepción requiere un prefijo de proveedor.
Edward Brey
17

Modificar, o más correctamente, agregar encabezados HTTP adicionales es una gran herramienta de depuración de código, si nada más.

Cuando una solicitud de URL devuelve una redirección o una imagen, no hay una "página" html para escribir temporalmente los resultados del código de depuración, al menos no uno que sea visible en un navegador.

Un enfoque es escribir los datos en un archivo de registro local y ver ese archivo más tarde. Otra es agregar temporalmente encabezados HTTP que reflejen los datos y las variables que se están depurando.

Regularmente agrego encabezados HTTP adicionales como X-fubar-somevar: o X-testing-someresult: para probar cosas, y he encontrado muchos errores que de otro modo habrían sido muy difíciles de rastrear.

g1smd
fuente
2
¿Por qué debería usar este "estándar"? Los encabezados funcionan igual. Incluso con el prefijo "WHO_EVER_READS_THIS_IS_DUMB_" ...
El increíble Jan
16

El registro de nombre de campo de encabezado se define en RFC3864 y no hay nada especial con "X-".

Por lo que puedo decir, no hay pautas para los encabezados privados; en caso de duda, evítelos. O eche un vistazo al Marco de extensión HTTP ( RFC 2774 ).

Sería interesante entender más del caso de uso; ¿Por qué no se puede agregar la información al cuerpo del mensaje?

Julian Reschke
fuente
13
La razón principal por la que estoy considerando algunos encabezados personalizados es para poder tomar decisiones de enrutamiento sin tener que analizar el cuerpo ...
Rozwel