Resumen

  • En RFC 2068, el número HTTP describía el formato del mensaje y el máximo nivel que el emisor podía sostener para comunicaciones posteriores, no las funciones usadas en ese intercambio.
  • Un intermediario que interpretaba y reenviaba pasaba a ser un emisor nuevo: tenía que usar su propia versión y no podía apropiarse de la anunciada por el cliente o el origen.
  • La evolución menor era viable sólo si el mensaje nuevo seguía siendo válido para un receptor antiguo después de retirar los campos que éste desconocía.

Hay dos maneras de leer HTTP/1.1 al final de una línea de petición. La primera lo trata como una pegatina: “este mensaje contiene las novedades de HTTP/1.1”. La segunda lo trata como una afirmación del programa que acaba de enviar la línea: “éste es el formato que empleo y éste es el nivel de comunicación HTTP que puedo asumir”. RFC 2068 eligió la segunda.

La diferencia no es semántica menor. Una pegatina describe el objeto presente. Una afirmación de capacidad prepara una decisión futura. El receptor puede usarla para decidir qué respuesta o qué petición posterior podría enviar, pero no puede convertirla en prueba de que una función concreta ya se ejecutó.

El problema existía antes de HTTP/1.1

RFC 1945 documentó HTTP/1.0 en mayo de 1996 como práctica común, no como estándar de Internet. El documento separaba las funciones que solían estar implementadas de forma coherente de aquellas que aparecían poco o de manera desigual. Aun así, ya formulaba la política de versiones que heredó RFC 2068: el número debía expresar el formato del mensaje y la capacidad del emisor para entender futuras comunicaciones, no lo que se hubiera obtenido en esa comunicación concreta.

Ese contexto impide confundir una denominación con una medición. RFC 2068 observó que abundaban las aplicaciones incompletas que se llamaban HTTP/1.0. Dos interlocutores no podían deducir una capacidad real sólo a partir del nombre del producto. Necesitaban una señal en el mensaje y reglas que limitaran lo que podía afirmar quien la emitía.

La parte mayor del número se reservaba para un cambio de formato. La parte menor podía crecer cuando se añadían significados o capacidades sin cambiar el algoritmo general de análisis. Añadir valores a un campo ya extensible, si no alteraba el comportamiento de comunicación, tampoco obligaba a crear otra versión.

La arquitectura tenía una condición: el núcleo común debía ser bastante preciso para que un participante antiguo siguiera analizando el mensaje. La novedad no podía apropiarse de la misma sintaxis y cambiar silenciosamente el significado de lo ya existente.

Capacidad, uso y resultado eran tres pruebas diferentes

RFC 2068 exigía que las aplicaciones que enviaran las peticiones o respuestas definidas por la especificación incluyeran HTTP/1.1 en la primera línea. Utilizar ese número significaba que la aplicación emisora cumplía al menos de forma condicional. La versión de una aplicación era la más alta para la que podía sostener ese grado de conformidad.

La afirmación tenía alcance real, pero limitado. Indicaba cómo debía analizarse el mensaje de ese salto. Declaraba un techo de capacidad del emisor. No enumeraba el subconjunto exacto de funciones presente en los bytes.

Por eso una petición sin cuerpo segmentado, sin controles de caché y sin negociación visible podía seguir diciendo HTTP/1.1. El emisor quizá no necesitaba esas funciones ahora, pero estaba informando al servidor de lo que entendería después. A la inversa, el número no demostraba que una conexión persistente siguiera abierta, que un campo hubiera atravesado todos los proxies o que la operación de aplicación hubiera terminado.

Tampoco era autenticación. Un emisor defectuoso podía mentir o equivocarse. La regla definía qué significaba una afirmación conforme, no fabricaba una firma criptográfica sobre la implementación. Para comprobar ejecución, entrega o resultado seguían haciendo falta registros distintos.

El proxy debía hablar con voz propia

RFC 2068 dedicó una advertencia expresa a proxies y pasarelas. Un intermediario podía recibir una versión distinta de la que él implementaba, transformar campos y reconstruir el mensaje. No debía emitir un indicador superior a su versión real.

Si recibía una petición demasiado reciente, podía rebajar el número, contestar con un error o abandonar la interpretación y actuar como túnel. Si recibía una petición más antigua, en ciertas condiciones podía elevarla antes de reenviarla. Traducir entre versiones podía requerir añadir o retirar campos.

El hecho decisivo era quién generaba el siguiente mensaje. Un proxy HTTP/1.0 no ganaba capacidad porque su cliente hubiera enviado HTTP/1.1. Copiar el número superior habría atribuido al intermediario obligaciones que no podía cumplir. En el siguiente enlace, el proxy era el emisor y debía responder de su propia declaración.

RFC 2145, publicado pocos meses después para resolver interpretaciones incompatibles, lo expresó como una propiedad de salto a salto. El número HTTP no era extremo a extremo y un proxy no lo “reenviaba” como si fuera una etiqueta inmutable. Via podía dejar constancia separada de los protocolos observados aguas arriba, pero esa constancia no convertía la versión actual en una historia completa de la ruta.

De ahí se desprende una cautela práctica. El HTTP/1.1 que ve el servidor de origen sólo identifica la capacidad declarada por su vecino inmediato. No demuestra que el navegador original, ni todos los intermediarios anteriores, hubieran usado el mismo protocolo en sus respectivas conexiones.

Compatibilidad era conservar un mensaje después de quitar la novedad

RFC 2145 explica que la política había provocado confusión y problemas de interoperabilidad. Su respuesta no consistió en obligar a los receptores antiguos a entender el futuro. Impuso disciplina al emisor nuevo.

Dentro de la misma versión mayor, un número menor no podía cambiar la interpretación de campos ya definidos. El receptor debía ignorar los campos que no conocía, con reglas especiales para los proxies. El número menor describía la capacidad del emisor, no una nueva interpretación secreta de todo el mensaje.

Un emisor de versión superior podía mandar a un receptor antiguo un campo que éste no conociera. Lo que no podía hacer era depender de que lo entendiera. Si HTTP/1.1 hablaba con HTTP/1.0, o con una versión desconocida, al retirar los campos nuevos tenía que quedar un mensaje HTTP/1.0 válido.

Este “ensayo de sustracción” es el centro operativo del diseño. El emisor que adopta la extensión asume el coste de mantener un núcleo compatible. El receptor antiguo no obtiene capacidades por decreto, pero tampoco necesita rechazar todo mensaje que contenga algo nuevo.

No todos los campos desconocidos seguían el mismo camino. Un proxy debía reenviar en general un campo desconocido para permitir que una extensión llegara a un receptor posterior. Si Connection lo marcaba como propio de esa conexión, debía retirarlo. Y una función esencial para delimitar el mensaje no podía tratarse como accesorio. RFC 2145 señalaba que un servidor HTTP/1.1 no podía enviar codificación segmentada como respuesta a una petición HTTP/1.0.

Ignorar lo desconocido sólo funcionaba cuando el resto seguía siendo completo y correcto. La tolerancia no autorizaba a esconder una dependencia obligatoria dentro de una extensión.

La aclaración también fue una señal histórica

RFC 2145 declaró que no estaba cambiando la intención de HTTP/1.0 o HTTP/1.1, sino haciéndola definitiva donde los textos anteriores resultaban ambiguos. Que se necesitara esa aclaración muestra una brecha entre texto, interpretación e implementación. El propio documento no permite cuantificarla ni atribuirla a productos concretos.

También ordenó la elección de números. Un cliente debía usar normalmente la versión más alta para la que cumpliera al menos condicionalmente, sin superar la versión mayor del servidor cuando ésta fuera conocida. Un servidor debía responder con su nivel conforme más alto dentro de una versión mayor compatible con la petición. Ninguno podía anunciar una versión que no cumplía.

La reducción para un interlocutor defectuoso quedaba como excepción tras observar el fallo, no como política predeterminada. Si todos mintieran hacia abajo por precaución, la señal perdería la capacidad de facilitar adopción. Si mintieran hacia arriba, inducirían al otro a usar funciones inexistentes.

RFC 2616 conservó este marco en 1999 y remitió a RFC 2145. RFC 7230 los sustituyó en 2014 y explicitó que la versión menor anunciaba capacidad futura incluso si el mensaje actual usaba sólo un subconjunto retrocompatible. También registró que el paso de RFC 2068 a RFC 2616 no elevó la versión menor: publicar una revisión no equivale por sí mismo a cambiar la señal del protocolo.

RFC 9110 separó después la semántica común de las sintaxis de HTTP/1.1, HTTP/2 y HTTP/3. Las versiones mayores pueden coexistir y no son simples escalones intercambiables. Al reenviar, un intermediario actualiza la versión al protocolo que usa en su salida; Via conserva otra clase de evidencia sobre el camino anterior.

El documento no era la ejecución

La doctrina posterior de Lu Heng sobre especificación inicial mínima, decisión futura localizada y adopción voluntaria sirve como lente editorial. El conjunto común debe contener lo necesario para interoperar. Cada participante que ejecuta código decide localmente qué conjunto compatible acepta. Una novedad sólo se vuelve realidad operativa cuando se implementa, valida y usa.

No es legítimo convertir esa lente de 2026 en una intención histórica de los autores de HTTP ni asociarlos a las propuestas institucionales de Lu Heng. Sí ayuda a mantener separadas seis cosas que suelen comprimirse: el RFC publicado, el número declarado, el código desplegado, el campo usado, el mensaje recibido y la acción completada.

RFC 2068 puso dos cifras en la primera línea, pero no les pidió certificar el mundo. Les pidió algo más pequeño y útil: que cada emisor dijera honestamente qué formato y qué capacidad podía sostener, y que la evolución dejara a los receptores antiguos un mensaje todavía válido.

Fuentes