Skip to content

Instantly share code, notes, and snippets.

@brunopk
Last active December 5, 2018 00:29
Show Gist options
  • Save brunopk/bd662f5e99f7149ba20030ac97628c16 to your computer and use it in GitHub Desktop.
Save brunopk/bd662f5e99f7149ba20030ac97628c16 to your computer and use it in GitHub Desktop.
Resumen del protocolo HTTP

Protocolo HTTP

Introducción

El RFC que define el protocolo en su versión 1.1 es el 2616 [1]. Los mensajes se pueden clasificar en dos tipos:

Requests

Sintaxis:

<linea de request>
<headers>
CRLF
<body>
  • <linea de request>: se compone de tres partes: <metodo> <URI> <version de HTTP>:
    • <metodo> debe ser alguno de los siguientes :
      • OPTIONS
      • GET
      • HEAD
      • POST
      • PUT
      • TRACE
      • CONNECT
    • <version de HTTP> : puede ser por ejemplo HTTP/1.1 o HTTP/1.0.
  • <headers>: es una lista en donde cada línea (header) se forma con un par <clave>: <valor> y se finaliza con CRLF. Alguno de los headers mas comunes son : Host, Accept y Connection.
  • <body> : es el cuerpo del mensaje (por ejemplo los datos enviados al completar un formulario en una página web).

Cada linea se separa con los caracteres CRLF, o sea la concatenación del caracter de carriage-return y end-of-line (ver https://tools.ietf.org/html/rfc2616#page-35).

Ejemplo: request simple

  1. Establecer una connección TCP con telnet a home.mcom.com: home.mcom.com: telnet home.mcom.com 80.
  2. Pegar el siguiente mensaje en la consola:
GET / HTTP/1.1
Host: home.mcom.com

Responses

Sintaxis:

<linea de status>
<headers>
CRLF
<body>

El status se representa por un valor numérico de tres dígitos. Se pueden clasificar por su primer dígito en alguna de las siguientes categorías:

  • 1xx : se utiliza con motivo de información, por ejemplo indicando que la request fue recibida o que continua siendo procesada.
  • 2xx : se utiliza cuando la request fue correctamente recibida, entendida y aceptada.
  • 3xx : se utiliza para indicar algún tipo de redirección por la cual alguna acción tiene que ser tomada posteriormente.
  • 4xx : se utiliza para indicar que la request contiene algun error de sintaxis o le faltan datos.
  • 5xx : se utliza para indicar que el servidor falló siendo aparentemente la request válida.

Ejemplo: respuesta de éxito

HTTP/1.1 200 OK
Date: Sun, 02 Dec 2018 16:07:22 GMT
Server: Apache
Last-Modified: Fri, 21 Oct 1994 19:00:00 GMT
ETag: "2f80859-f1-2c7ebe95f4c00"
Accept-Ranges: bytes
Content-Length: 241
Cache-Control: max-age=31536000
Expires: Mon, 02 Dec 2019 16:07:22 GMT
Content-Type: text/html

<TITLE>Welcome to Mosaic Communications Corporation!</TITLE>
<CENTER>
<A HREF="MCOM/index2.html"><IMG SRC="MCOM/images/mcomwelcome1.gif" BORDER=1></A>
<H3>
<A HREF="MCOM/index2.html">Click on the Image or here to advance</A>
</H3>
</CENTER>

Conecciones persistentes y no-persistentes

Normalmente los servidores asumen que la conección TCP debe quedar abierta [2]:

A significant difference between HTTP/1.1 and earlier versions of HTTP is that persistent connections are the default behavior of any HTTP connection. That is, unless otherwise indicated, the client SHOULD assume that the server will maintain a persistent connection, even after error responses from the server.

Esto se puede ver en el ejemplo anterior. Para hacer que la conección sea persistente se debe agregar el header Connection: keep-alive y para que sea no-persistente Connection: close [3].

Ejemplo: request con conección no-persistente

GET /home/welcome.html HTTP/1.1
Host: home.mcom.com
Connection: close

Ejemplo: conección persistente que se cierra abruptamente

A veces las requests mal formadas (en este caso le falta el header Host: tools.ietf.org) provocan que la conección se cierre incluso teniendo el header Connection: keep-alive.

GET /html/rfc2616 HTTP/1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: es,en-US;q=0.9,en;q=0.8
Connection: keep-alive

HTTP/1.0 400 Bad request
Cache-Control: no-cache
Connection: close
Content-Type: text/html

<html><body><h1>400 Bad request</h1>
Your browser sent an invalid request.
</body></html>

Notar que el servidor devuelve close en el header Connection de la respuesta.

Implementación de un servidor simple con nc

Con el comando nc (Linux/MacOS) es posible abrir un puerto TCP de escucha para recibir y responder mensajes HTTP.

En MacOS :

nc -l localhost 80
  • Los parámetros para ncen Linux no son los mismos
  • Puede ser necesario invocarlo con sudo

Luego, abrir cualquier navegador en la dirección localhost y volver a la consola para ver la request recibida.

Ejemplo: respuesta con cuerpo HTML

  1. Ejecutar nc : nc -l localhost 80
  2. Ir a http://localhost en cualquier navegador.
  3. Pegar el siguiente mensaje de respuesta en la terminal donde se invocó nc:
HTTP/1.1 200 OK
Content-Length: 51

<html>
<body>
<h1>Hola Mundo!</h1>
</body>
</html>
  1. Volver al navegador.

Aclaraciones:

  • Luego de la línea con el último header y antes de comenzar el cuerpo de la response debe haber un CRLF.
  • La respuesta finaliza con un CRLF.
  • Al ser la conección persistente por defecto, se debe cerrar mediante Ctrl+C en la consola donde fue invocado nc
  • El header Content-Length indica el tamaño en bytes del cuerpo de la response. Cuando no se define, el navegador mantendrá la conección abierta a la espera de recibir mas datos.

Request con SSL

Para recibir request encriptadas mediante SSL se puede seguir un procedimiento similar utilizando el puerto 443 como puerto TCP de escucha :

nc -l localhost 443

Luego, en el navegador, en lugar de ingresar simplemente a localhost, se debe ingresar mediante HTTPS a la URL https://localhost

Redireccionamiento permanente

Para hacer un redireccionamiento permanente se deben cumplir dos reglas en la respuesta :

  1. Devolver el status 301 (Moved Permanently)
  2. Colocar el header Location para indicar la URL a seguir

Esto se detalla en la sección 10.3.2 del RFC.

Ejemplo: redireccionamiento permanente

  1. Ejecutar nc : nc -l localhost 80
  2. Ir a http://localhost en cualquier navegador.
  3. Pegar el siguiente mensaje de respuesta en la terminal donde se invocó nc:
HTTP/1.1 301 Moved Permanently
Location: https://www.google.com
  1. Volver al navegador

Aclaraciones:

  • La respuesta finaliza con un CRLF.
  • Los navegadores normalmente cachearan la request por lo que es recomendable ingresar en modo incógnito.

Caching

El objetivo del caching en HTTP/1.1, es eliminar la necesidad de enviar request en muchos casos y eliminar la necesidad de enviar respuestas completas en muchos otros. Para lo primero se propone un mecanismo de expiración y para lo segundo uno de validación. La idea es que los servidores HTTP respondan con la versión mas reciente y apropiada que se mantiene en el cache [4].

Generalmente los navegadores proveen mecanismos de caching pero también se pueden implementar en un servidor de proxy. Para hacer que un navegador o un servidor de caching guarde un recurso, se debe agregar el header Cache-Control o Expires [4][5].

Ejemplo: caching durante un tiempo determinado

  1. Ejecutar nc : nc -l localhost 80
  2. Ir a http://localhost en cualquier navegador.
  3. Pegar el siguiente mensaje de respuesta en la terminal donde se invocó nc:
HTTP/1.1 200 OK
Content-Length: 77
Cache-Control: max-age=10
Content-Type: text/html; charset=UTF-8

<html>
<body>
<a href="http://localhost">Recargar página</a>
</body>
</html>
  1. Ir al enlace "Recargar página"

Aclaraciones:

  • Puede que en Google Chrome, al recargar la página con F5 o algún atajo de teclado, se genere otra request ignorando el header Cache-Control. Para eso, se agregó un anchor en el cuerpo HTML de la respuesta con un enlace hacia http://localhost.
  • El header Content-Type: text/html; charset=UTF-8 permite utilizar tildes y otros caracteres incluidos en el charset UTF-8

Referencias

[1]: RFC 2116, https://tools.ietf.org/html/rfc2616#section-13

[2]: Funcionamiento general de conecciones persistentes, https://tools.ietf.org/html/rfc2616#section-8.1.2

[3]: Negociación de conecciones persistentes, https://tools.ietf.org/html/rfc2616#section-8.1.2.1

[4]: Caching, https://tools.ietf.org/html/rfc2616#section-13

[5]: Caching, https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment