Protocolo de transferencia de hipertexto (HTTP) es la vida de la web. Se utiliza cada vez que se transfiere un documento o se realiza una solicitud AJAX
. Pero HTTP es sorprendentemente un relativo desconocido entre algunos desarrolladores web.
Esta introducción demostrará cómo el conjunto de principios de diseño, conocido como REST, respaldada por HTTP, y le permite abrazar su máxima potencia mediante la creación de interfaces, que pueden utilizarse desde casi cualquier dispositivo o sistema operativo.
¿Por qué REST?
REST es una forma sencilla de organizar interacciones entre sistemas independientes. Ha estado creciendo en popularidad desde 2005, e inspira el diseño de servicios, como la API de Twitter. Esto se debe al hecho de que REST le permite interactuar con un mínimo de gastos generales con clientes tan diversos como teléfonos móviles y otros sitios web. En teoría, REST no está vinculado a la web, pero casi siempre se implementa como tal, y se inspiró en HTTP. Como resultado, REST puede usarse dondequiera que HTTP pueda.
La alternativa es la construcción de convenciones relativamente complejas por encima de HTTP. A menudo, esto toma la forma de nuevos enteros lenguajes basados en XML. El ejemplo más ilustre es SOAP. Tienes que aprender un conjunto completamente nuevo de convenciones, pero nunca usas HTTP a su máxima potencia. Debido a que REST se ha inspirado en HTTP y juega a sus fortalezas, es la mejor manera de aprender cómo funciona HTTP.
Después de una descripción inicial, examinaremos cada uno de los bloques de construcción HTTP: URL, verbos HTTP y códigos de respuesta. También revisaremos cómo usarlos de una manera REST. A lo largo del camino, ilustraremos la teoría con una aplicación de ejemplo, que simula el proceso de seguimiento de datos relacionados con los clientes de una empresa a través de una interfaz web.
HTTP
HTTP es el protocolo que permite enviar documentos de un lado a otro en la web. Un protocolo es un conjunto de reglas que determina qué mensajes se pueden intercambiar y qué mensajes son respuestas apropiadas a otros. Otro protocolo común es POP3, que puede utilizar para buscar correo electrónico en su disco duro.
En HTTP, hay dos funciones diferentes: servidor y cliente. En general, el cliente siempre inicia la conversación; El servidor responde. HTTP está basado en texto; Es decir, los mensajes son esencialmente bits de texto, aunque el cuerpo del mensaje también puede contener otros medios. El uso del texto facilita el monitoreo de un intercambio HTTP.
Los mensajes HTTP se hacen de un encabezado y un cuerpo. El cuerpo a menudo puede permanecer vacío; Contiene los datos que desea transmitir a través de la red, con el fin de utilizarlo de acuerdo con las instrucciones en el encabezado. El encabezado contiene metadatos, como la información de codificación; Pero, en el caso de una solicitud, también contiene los métodos HTTP importantes. En el estilo REST, encontrará que los datos de cabecera suelen ser más significativos que el cuerpo.
Espiando a HTTP trabajando
Si
utiliza las Herramientas para desarrolladores de Chrome o Firefox con
la extensión Firebug instalada, haga clic en el panel Red
y establézcala
en activada
. A continuación, tendrá la posibilidad de ver los detalles de las solicitudes HTTP mientras navega. Por ejemplo:

Otra forma útil de familiarizarse con HTTP es utilizar un cliente dedicado, como cURL.
CURL es una herramienta de línea de comandos que está disponible en todos los principales sistemas operativos.
Una vez que tenga cURL instalado, escriba:
curl -v google.com
Esto mostrará la conversación HTTP completa. Las peticiones están precedidas por >
, mientras que las respuestas están precedidas por <
.
URLs
Las URL son para identificar las cosas en las que desea operar. Decimos que cada URL identifica un recurso. Estas son exactamente las mismas URL que se asignan a las páginas web. De hecho, una página web es un tipo de recurso. Tomemos un ejemplo más exótico y consideremos nuestra aplicación de ejemplo, que gestiona la lista de clientes de una empresa:
/clients
Identificará a todos los clientes, mientras
/clients/jim
Identificará al cliente, llamado 'Jim', asumiendo que él es el único con ese nombre.
En estos ejemplos, generalmente no incluimos el nombre del host en la URL, ya que es irrelevante desde el punto de vista de cómo se organiza la interfaz. Sin embargo, el nombre de host es importante para asegurar que el identificador de recurso sea único en toda la web. A menudo decimos que envía la solicitud de un recurso a un host. El host se incluye en el encabezado por separado de la ruta de recursos, que viene justo encima del encabezado de la solicitud:
GET /clients/jim HTTP/1.1 Host: example.com
Los recursos se consideran mejor como sustantivos. Por ejemplo, lo siguiente no es RESTful:
/clients/add
Esto se debe a que utiliza una URL para describir una acción. Este es un punto bastante fundamental para distinguir los sistemas RESTful de no-RESTful.
Por último, las URL deben ser tan precisas como sea necesario; Todo lo necesario para identificar de forma exclusiva un recurso debe estar en la URL. No es necesario incluir datos que identifiquen el recurso en la solicitud. De esta manera, las URL actúan como un mapa completo de todos los datos que maneja su aplicación.
Pero, ¿cómo se especifica una acción? Por ejemplo, ¿cómo dices que quieres crear un nuevo registro de cliente en lugar de recuperarlo? Aquí es donde entran en juego los verbos HTTP.
Verbos HTTP
Cada solicitud especifica un cierto verbo o método HTTP, en el encabezado de la solicitud. Esta es la primera palabra de todos las mayúsculas en el encabezado de la solicitud. Por ejemplo,
GET / HTTP/1.1
Significa que se está utilizando el método GET, mientras
DELETE /clients/anne HTTP/1.1
significa que se utiliza el método DELETE
.
Los verbos HTTP le indican al servidor qué hacer con los datos identificados por la URL.
La
solicitud puede contener opcionalmente información adicional en su
cuerpo, que podría ser necesaria para realizar la operación, por
ejemplo, los datos que desea almacenar con el recurso. Puede proporcionar estos datos en cURL con la opción -d
.
Si alguna vez has creado formularios HTML, estarás familiarizado con dos de los verbos HTTP más importantes: GET
y POST
. Pero hay muchos más verbos HTTP disponibles. Los más importantes para la creación de RESTful API son GET
, POST
, PUT
y DELETE
. Otros
métodos están disponibles, como HEAD
y OPTIONS
, pero son más raros (si
quieres saber sobre todos los demás métodos HTTP, la fuente oficial es
IETF).
GET
GET
es el tipo más simple de método de solicitud HTTP; La que usan los navegadores cada vez que hace clic en un enlace o escribe una URL en la barra de direcciones. Indica al servidor que transmita los datos identificados por la URL al cliente. Los datos nunca deben ser modificados en el lado del servidor como resultado de una solicitud GET
. En este
sentido, una petición GET
es de sólo lectura, pero por supuesto, una vez
que el cliente recibe los datos, es libre de hacer cualquier operación
con ella por su cuenta, por ejemplo, formatearla para su visualización.
PUT
Una petición PUT
se utiliza cuando se desea crear o actualizar el recurso identificado por la URL. Por ejemplo,
PUT /clients/robin
Podría crear un cliente, llamado Robin
en el servidor. Usted notará que REST
es completamente agnóstico de servidor; No hay nada en la solicitud que informe al servidor cómo deben crearse los datos, sólo que debería. Esto le permite intercambiar fácilmente la tecnología del servidor si la necesidad surge. Las peticiones PUT
contienen los datos que se utilizarán para actualizar o crear el recurso en el cuerpo. En cURL, puede agregar datos a la solicitud con el modificador -d
.
curl -v -X PUT -d "some text"
DELETE
DELETE
debe realizar lo contrario de PUT
; Debe utilizarse cuando desee eliminar el recurso identificado por la URL de la solicitud.
curl -v -X DELETE /clients/anne
Esto eliminará todos los datos asociados con el recurso, identificados por /clients/anne
.
POST
POST
se
utiliza cuando el procesamiento que desea que suceda en el servidor debe
repetirse, si la solicitud POST
se repite (es decir, no son idempotent,
más de esto a continuación). Además,
las solicitudes POST
deben causar el procesamiento del cuerpo de la
solicitud como un subordinado de la URL que está publicando.
En palabras claras:
POST /clients/
No debe causar que el recurso en /clients/
, se modifique, sino un recurso cuya URL comience con /clients/
. Por ejemplo, podría agregar un nuevo cliente a la lista, con un ID
generado por el servidor.
/clients/some-unique-id
PUT
solicitudes se utilizan fácilmente en lugar de solicitudes POST
, y viceversa. Algunos
sistemas utilizan sólo uno, algunos utilizan POST
para crear
operaciones y PUT
para operaciones de actualización (ya que con una
solicitud PUT
siempre proporcionan la URL completa), algunos incluso
utilizan POST
para actualizaciones y PUT
para crear.
A
menudo, las solicitudes POST
se utilizan para activar las operaciones
en el servidor, que no encajan en el paradigma Crear / Actualizar / Eliminar
; Pero esto, sin embargo, está más allá del alcance de REST
. En nuestro ejemplo, nos quedaremos con PUT
todo el camino.
Clasificación de métodos HTTP
GET
. Los otros son inseguros, porque pueden resultar en una modificación de los recursos. GET
, PUT
y DELETE
. El único método no idempotente es POST
. PUT
y DELETE
ser considerado idempotente podría ser sorprendente, sin
embargo, de hecho, es bastante fácil de explicar: repetir un método PUT
con exactamente el mismo cuerpo debería modificar un recurso de tal
forma que siga siendo idéntico al descrito en el anterior Solicitud PUT
: ¡nada cambiará! Del mismo modo, no tiene sentido eliminar un recurso dos veces. Se
sigue que no importa cuántas veces se repite una solicitud PUT
o
DELETE
, el resultado debe ser el mismo que si se hubiera hecho sólo una
vez.Recuerde: es usted, el programador, quien decide en última instancia qué sucede cuando se utiliza un determinado método HTTP. No hay nada inherente a las implementaciones de HTTP que automáticamente hará que los recursos se crean, se enumeran, se eliminan o se actualizan. Debe tener cuidado de aplicar el protocolo HTTP correctamente y aplicar esta semántica usted mismo.
Representaciones
El cliente HTTP y el servidor HTTP intercambian información sobre los recursos identificados por las URL.
Podemos resumir lo que hemos aprendido hasta ahora de la siguiente manera: el cliente HTTP y el servidor HTTP intercambian información sobre los recursos identificados por las URL.
Decimos que la solicitud y la respuesta contienen una representación del recurso. Por representación, nos referimos a la información, en un cierto formato, sobre el estado del recurso o cómo debería ser ese estado en el futuro. Tanto la cabecera como el cuerpo son piezas de la representación.
Los encabezados HTTP, que contienen metadatos, están firmemente definidos por la especificación HTTP; Sólo pueden contener texto sin formato y deben estar formateados de una manera determinada.
El cuerpo puede contener datos en cualquier formato, y aquí es donde el poder de HTTP realmente brilla. Usted sabe que puede enviar texto sin formato, imágenes, HTML y XML en cualquier idioma humano. A través de metadatos de la solicitud o URL diferentes, puede elegir entre diferentes representaciones para el mismo recurso. Por ejemplo, puede enviar una página web a los navegadores y JSON a las aplicaciones.
La respuesta HTTP debe especificar el tipo de contenido del cuerpo. Esto se hace en el encabezado, en el campo Content-Type; por ejemplo:
Content/Type: application/json
Para simplificar, nuestra aplicación de ejemplo sólo envía JSON de un lado a otro, pero la aplicación debe estar diseñada de tal manera que pueda cambiar fácilmente el formato de los datos, adaptarlos a diferentes clientes o preferencias de usuario.
Bibliotecas de clientes HTTP
CURL es, más a menudo que no, la solución de cliente HTTP de elección para los desarrolladores de PHP.
Para experimentar con los diferentes métodos de solicitud, necesita un cliente, que le permite especificar qué método utilizar. Desafortunadamente, los formularios HTML no se ajustan a la factura, ya que sólo permiten hacer solicitudes GET y POST. En la vida real, las API se acceden mediante programación a través de una aplicación cliente independiente o mediante JavaScript en el navegador.
Esta es la razón por la cual, además del servidor, es esencial contar con buenas capacidades de cliente HTTP disponibles en su lenguaje de programación de elección.
Una biblioteca de cliente HTTP muy popular es, de nuevo, cURL. Ya se ha familiarizado con el comando cURL desde este tutorial. CURL incluye tanto un programa de línea de comandos independiente como una biblioteca que puede ser utilizada por varios lenguajes de programación. En particular, cURL es, la mayoría de las veces, la solución de cliente HTTP de elección para los desarrolladores de PHP. Otros idiomas, como Python, ofrecen bibliotecas de cliente HTTP más nativas.
Configuración de la aplicación de ejemplo
Quiero exponer la funcionalidad de bajo nivel tanto como sea posible.
Nuestro ejemplo de aplicación PHP es muy escueta. Quiero exponer la funcionalidad de bajo nivel tanto como sea posible, sin ninguna magia de marco. Tampoco quería usar una API real, como la de Twitter, porque están sujetas a cambios inesperados, es necesario configurar la autenticación, lo que puede ser una molestia y, obviamente, no se puede estudiar la implementación.
Para ejecutar la aplicación de ejemplo, tendrá que instalar PHP5 y un servidor web, con algún mecanismo para ejecutar PHP. La versión actual debe tener al menos la versión 5.2 para tener acceso a las funciones json_encode()
y json_decode()
.
En cuanto a los servidores, la opción más común sigue siendo Apache con mod_php, pero eres libre de usar cualquier alternativa que te resulte cómoda. Hay una configuración de ejemplo de Apache, que contiene reglas de reescritura para ayudarle a configurar la aplicación rápidamente. Todas las peticiones a cualquier URL, comenzando con /clients/, deben ser encaminadas a nuestro archivo server.php.
En Apache, debes habilitar mod_rewrite y poner la configuración mod_rewrite suministrada en algún lugar de tu configuración de Apache, o tu archivo .htacess. De esta forma, server.php responderá a todas las solicitudes procedentes del servidor. Lo mismo se debe lograr con Nginx, o cualquier otro servidor que decida utilizar.
Cómo funciona la aplicacion de ejemplo
Hay dos claves para procesar las peticiones de la manera REST. La primera clave es iniciar un procesamiento diferente, dependiendo del método HTTP - incluso cuando los URL son iguales. En PHP, hay una variable en la array global $_SERVER, que determina qué método se ha utilizado para realizar la solicitud:
$_SERVER['REQUEST_METHOD']
Esta variable contiene el nombre del método como una cadena, por ejemplo 'GET
', 'PUT
', y así sucesivamente.
La otra clave es saber qué URL se ha solicitado. Para ello, utilizamos otra variable estándar de PHP:
$_SERVER['REQUEST_URI']
Esta variable contiene la URL a partir de la primera barra diagonal. Por ejemplo, si el nombre de host es 'example.com
', 'http://example.com/
' Devolvería '/
', mientras que 'http://example.com/test/
' Devolvería '/test/
'.
Primero intente determinar qué URL ha sido llamada. Sólo consideramos las URL que comienzan con 'clients
'. Todas las demás son inválidos.
$resource = array_shift($paths); if ($resource == 'clients') { $name = array_shift($paths); if (empty($name)) { $this->handle_base($method); } else { $this->handle_name($method, $name); } } else { // We only handle resources under 'clients' header('HTTP/1.1 404 Not Found'); }
Tenemos dos resultados posibles:
- El recurso son los clientes, en cuyo caso, devolvemos una lista completa
- Existe otro identificador
Si
hay otro identificador, asumimos que es el nombre del cliente y, de
nuevo, lo reenvío a una función diferente, dependiendo del método
. Utilizamos una sentencia switch
, que se debe evitar en una aplicación real:
switch($method) { case 'PUT': $this->create_contact($name); break; case 'DELETE': $this->delete_contact($name); break; case 'GET': $this->display_contact($name); break; default: header('HTTP/1.1 405 Method Not Allowed'); header('Allow: GET, PUT, DELETE'); break; }
Códigos de respuesta
Los códigos de respuesta HTTP estandarizan una forma de informar al cliente sobre el resultado de su solicitud.
Usted
puede ser que haya notado que la aplicación del ejemplo utiliza PHP header()
, pasando algunas secuencias que miran extrañas como
argumentos. La función header() imprime los headers
HTTP y asegura que estén formateados apropiadamente. Headers debe ser la primera cosa en la respuesta, por lo que no debe salir nada más antes de terminar con los encabezados. A veces, su servidor HTTP puede estar configurado para agregar otros encabezados, además de los que especifique en su código.
Los encabezados contienen todo tipo de información meta; Por ejemplo, la codificación de texto utilizada en el cuerpo del mensaje o el tipo MIME del contenido del cuerpo. En este caso, especificamos explícitamente los códigos de respuesta HTTP. Los códigos de respuesta HTTP estandarizan una forma de informar al cliente sobre el resultado de su solicitud. De forma predeterminada, PHP devuelve un código de respuesta de 200
, lo que significa que la respuesta es correcta.
El servidor debe devolver el código de respuesta HTTP más apropiado; De esta manera, el cliente puede intentar reparar sus errores, asumiendo que hay alguno. La mayoría de las personas están familiarizadas con el código de respuesta 404 No encontrado, sin embargo, hay mucho más disponible para adaptarse a una amplia variedad de situaciones.
Tenga en cuenta que el significado de un código de respuesta HTTP no es muy preciso; Esto es una consecuencia de HTTP mismo que es bastante genérico. Debe intentar utilizar el código de respuesta que más se aproxima a la situación actual. Dicho esto, no te preocupes demasiado si no puedes encontrar uno que sea exacto.
Estos son algunos códigos de respuesta HTTP, que a menudo se utilizan con REST:
200 OK
Este código de respuesta indica que la solicitud se ha realizado correctamente.
201 Created
Esto indica que la solicitud tuvo éxito y se creó un recurso. Se utiliza para confirmar el éxito de una solicitud PUT
o POST
.
400 Bad Request
La solicitud fue malformada. Esto
sucede especialmente con las solicitudes POST
y PUT
, cuando los datos
no pasan la validación o están en el formato incorrecto.
404 Not Found
Esta respuesta indica que no se pudo encontrar el recurso necesario. Esto generalmente se devuelve a todas las solicitudes que apuntan a una URL sin recurso correspondiente.
401 Unauthorized
Este error indica que debe realizar la autenticación antes de acceder al recurso.
405 Method Not Allowed
El método HTTP utilizado no es compatible con el de este recurso.
409 Conflict
Esto indica un conflicto. Por ejemplo, está utilizando una solicitud PUT
para crear el mismo recurso dos veces.
500 Internal Server Error
Cuando todo lo demás falla; En general, se utiliza una respuesta 500 cuando el procesamiento falla debido a circunstancias imprevistas en el lado del servidor, lo que provoca el error del servidor.
Ejercicio de la aplicación de ejemplo
Empecemos simplemente por obtener información de la aplicación. Queremos los detalles del cliente, 'jim
', así que enviemos una simple solicitud GET
a la URL de este recurso:
curl -v http://localhost:80/clients/jim
Esto mostrará los encabezados completos. La última línea en la respuesta será el cuerpo del mensaje; En
este caso, será JSON que contiene la dirección de Jim (recuerde que
omitir un nombre de método resultará en una petición GET
, también
reemplazará localhost:80
con el nombre del servidor y el puerto que
este usando).
A continuación, podemos obtener la información para todos los clientes a la vez:
curl -v http://localhost:80/clients/
Para crear un nuevo cliente, llamado Paul...
curl -v -X PUT http://localhost:80/clients/paul -d '{"address":"Sunset Boulevard" }
Y usted recibirá la lista de todos los clientes que ahora contienen Paul como una confirmación.
Por último, para eliminar un cliente:
curl -v -X DELETE http://localhost:80/clients/anne
Usted encontrará que el JSON devuelto ya no contiene ningún dato sobre Anne.
Si intenta recuperar un cliente no existente, por ejemplo:
curl -v http://localhost:80/clients/jerry
Obtendrá un error 404, mientras que si intenta crear un cliente que ya existe:
curl -v -X PUT http://localhost:80/clients/anne
En su lugar, recibirá un error 409.
Conclusion
En general, cuantas menos suposiciones más allá de HTTP haces, mejor.
Es importante recordar que el HTTP fue concebido para comunicarse entre sistemas, que comparten nada más que una comprensión del protocolo. En general, cuanto menos suposiciones más allá de HTTP haces, mejor: esto permite que la más amplia gama de programas y dispositivos acceda a tu API.
Utilicé PHP en este tutorial, porque es muy probable que sea el idioma más familiar para los lectores de Tuts+. Dicho
esto, PHP, aunque diseñado para la web, probablemente no es el mejor
lenguaje para usar cuando se trabaja de una manera REST, ya que maneja
PUT
peticiones de una manera completamente diferente a GET
y POST
.
Más allá de PHP, puede considerar lo siguiente:
- Los diversos marcos de Ruby (Rails y Sinatra)
- Hay excelente soporte REST en Python. Plain Django y WebOb, o Werkzeug debería funcionar
- Node.js tiene un excelente soporte para REST
Entre las aplicaciones que intentan adherirse a los principios de REST, el ejemplo clásico es el Protocolo de Publicación de Atom, aunque con honestidad no se usa con demasiada frecuencia en la práctica. Para una aplicación moderna, basada en la filosofía de utilizar HTTP al máximo, consulte Apache CouchDB.
¡Que te diviertas!