¿Qué es exactamente la programación RESTful?

Resuelto hasen asked hace 15 años • 35 respuestas

¿Qué es exactamente la programación RESTful?

hasen avatar Mar 22 '09 21:03 hasen
Aceptado

REST es el principio arquitectónico subyacente de la web. Lo sorprendente de la web es el hecho de que los clientes (navegadores) y los servidores pueden interactuar de maneras complejas sin que el cliente sepa nada de antemano sobre el servidor y los recursos que aloja. La restricción clave es que el servidor y el cliente deben estar de acuerdo sobre el medio utilizado, que en el caso de la web es HTML .

Una API que se adhiere a los principios de REST no requiere que el cliente sepa nada sobre la estructura de la API. Más bien, el servidor debe proporcionar cualquier información que el cliente necesite para interactuar con el servicio. Un formulario HTML es un ejemplo de esto: el servidor especifica la ubicación del recurso y los campos obligatorios. El navegador no sabe de antemano dónde enviar la información y no sabe de antemano qué información enviar. Ambas formas de información son suministradas íntegramente por el servidor. (Este principio se llama HATEOAS : hipermedia como motor del estado de la aplicación ).

Entonces, ¿cómo se aplica esto a HTTP y cómo se puede implementar en la práctica? HTTP está orientado alrededor de verbos y recursos. Los dos verbos de uso generalizado son GETy POST, que creo que todos reconocerán. Sin embargo, el estándar HTTP define varios otros, como PUTy DELETE. Luego, estos verbos se aplican a los recursos, según las instrucciones proporcionadas por el servidor.

Por ejemplo, imaginemos que tenemos una base de datos de usuarios administrada por un servicio web. Nuestro servicio utiliza un hipermedio personalizado basado en JSON, para el cual asignamos el tipo MIME application/json+userdb(también puede haber un application/xml+userdby application/whatever+userdb; es posible que se admitan muchos tipos de medios). Tanto el cliente como el servidor han sido programados para comprender este formato, pero no saben nada el uno del otro. Como señala Roy Fielding :

Una API REST debería dedicar casi todo su esfuerzo descriptivo a definir los tipos de medios utilizados para representar los recursos e impulsar el estado de la aplicación, o a definir nombres de relaciones extendidas y/o marcas habilitadas para hipertexto para los tipos de medios estándar existentes.

Una solicitud del recurso base /podría devolver algo como esto:

Pedido

GET /
Accept: application/json+userdb

Respuesta

200 OK
Content-Type: application/json+userdb

{
    "version": "1.0",
    "links": [
        {
            "href": "/user",
            "rel": "list",
            "method": "GET"
        },
        {
            "href": "/user",
            "rel": "create",
            "method": "POST"
        }
    ]
}

Sabemos por la descripción de nuestros medios que podemos encontrar información sobre recursos relacionados en secciones llamadas "enlaces". Esto se llama controles hipermedia . En este caso, podemos saber en dicha sección que podemos encontrar una lista de usuarios realizando otra solicitud para /user:

Pedido

GET /user
Accept: application/json+userdb

Respuesta

200 OK
Content-Type: application/json+userdb

{
    "users": [
        {
            "id": 1,
            "name": "Emil",
            "country: "Sweden",
            "links": [
                {
                    "href": "/user/1",
                    "rel": "self",
                    "method": "GET"
                },
                {
                    "href": "/user/1",
                    "rel": "edit",
                    "method": "PUT"
                },
                {
                    "href": "/user/1",
                    "rel": "delete",
                    "method": "DELETE"
                }
            ]
        },
        {
            "id": 2,
            "name": "Adam",
            "country: "Scotland",
            "links": [
                {
                    "href": "/user/2",
                    "rel": "self",
                    "method": "GET"
                },
                {
                    "href": "/user/2",
                    "rel": "edit",
                    "method": "PUT"
                },
                {
                    "href": "/user/2",
                    "rel": "delete",
                    "method": "DELETE"
                }
            ]
        }
    ],
    "links": [
        {
            "href": "/user",
            "rel": "create",
            "method": "POST"
        }
    ]
}

Podemos decir mucho de esta respuesta. Por ejemplo, ahora sabemos que podemos crear un nuevo usuario ingresando POSTa /user:

Pedido

POST /user
Accept: application/json+userdb
Content-Type: application/json+userdb

{
    "name": "Karl",
    "country": "Austria"
}

Respuesta

201 Created
Content-Type: application/json+userdb

{
    "user": {
        "id": 3,
        "name": "Karl",
        "country": "Austria",
        "links": [
            {
                "href": "/user/3",
                "rel": "self",
                "method": "GET"
            },
            {
                "href": "/user/3",
                "rel": "edit",
                "method": "PUT"
            },
            {
                "href": "/user/3",
                "rel": "delete",
                "method": "DELETE"
            }
        ]
    },
    "links": {
       "href": "/user",
       "rel": "list",
       "method": "GET"
    }
}

También sabemos que podemos cambiar los datos existentes:

Pedido

PUT /user/1
Accept: application/json+userdb
Content-Type: application/json+userdb

{
    "name": "Emil",
    "country": "Bhutan"
}

Respuesta

200 OK
Content-Type: application/json+userdb

{
    "user": {
        "id": 1,
        "name": "Emil",
        "country": "Bhutan",
        "links": [
            {
                "href": "/user/1",
                "rel": "self",
                "method": "GET"
            },
            {
                "href": "/user/1",
                "rel": "edit",
                "method": "PUT"
            },
            {
                "href": "/user/1",
                "rel": "delete",
                "method": "DELETE"
            }
        ]
    },
    "links": {
       "href": "/user",
       "rel": "list",
       "method": "GET"
    }
}

Observe que estamos usando diferentes verbos HTTP ( GET,,, etc.) para manipular estos recursos, y que el único conocimiento que presumimos por parte del cliente es nuestra definición de medios.PUTPOSTDELETE

Otras lecturas:

  • Las muchas respuestas mucho mejores en esta misma página.
  • Cómo le expliqué REST a mi esposa .
  • Cómo le expliqué REST a mi esposa .
  • Los pensamientos de Martin Fowler
  • La API de PayPal tiene controles hipermedia

(Esta respuesta ha sido objeto de bastantes críticas por no entender el punto. En su mayor parte, ha sido una crítica justa. Lo que describí originalmente estaba más en línea con cómo se implementaba REST hace unos años cuando Primero escribí esto, en lugar de su verdadero significado. He revisado la respuesta para representar mejor el significado real.)

Emil H avatar Mar 22 '2009 14:03 Emil H

Un estilo arquitectónico llamado REST (Representational State Transfer) aboga por que las aplicaciones web utilicen HTTP tal como se concibió originalmente . Las búsquedas deben utilizar GETsolicitudes. PUT, POSTy DELETElas solicitudes deben usarse para mutación , creación y eliminación respectivamente.

Los defensores de REST tienden a favorecer las URL, como

http://myserver.com/catalog/item/1729

pero la arquitectura REST no requiere estas "bonitas URL". Una solicitud GET con un parámetro

http://myserver.com/catalog?item=1729

es igual de RESTful.

Tenga en cuenta que las solicitudes GET nunca deben utilizarse para actualizar información. Por ejemplo, una solicitud GET para agregar un artículo a un carrito

http://myserver.com/addToCart?cart=314159&item=1729

no sería apropiado. Las solicitudes GET deben ser idempotentes . Es decir, emitir una solicitud dos veces no debería ser diferente de emitirla una vez. Eso es lo que hace que las solicitudes se puedan almacenar en caché. Una solicitud de "agregar al carrito" no es idempotente: emitirla dos veces agrega dos copias del artículo al carrito. Una solicitud POST es claramente apropiada en este contexto. Por lo tanto, incluso una aplicación web RESTful necesita su parte de solicitudes POST.

Esto está tomado del excelente libro Core JavaServer faces de David M. Geary.

La programación RESTful se trata de:

  • Los recursos se identifican mediante un identificador persistente: los URI son la opción omnipresente de identificador en estos días.
  • Los recursos se manipulan utilizando un conjunto común de verbos: los métodos HTTP son el caso más común: el venerable Create, Retrieve, Update, Deletese convierte en POST, GET, PUTy DELETE. Pero REST no se limita a HTTP, es simplemente el transporte más utilizado en este momento.
  • la representación real recuperada para un recurso depende de la solicitud y no del identificador: use los encabezados Aceptar para controlar si desea XML, HTTP o incluso un objeto Java que represente el recurso.
  • mantener el estado en el objeto y representar el estado en la representación
  • representar las relaciones entre recursos en la representación del recurso: los vínculos entre objetos están incrustados directamente en la representación
  • Las representaciones de recursos describen cómo se puede usar la representación y bajo qué circunstancias se debe descartar/recuperar de manera consistente: uso de encabezados HTTP Cache-Control

Este último es probablemente el más importante en términos de consecuencias y efectividad general de REST. En general, la mayoría de las discusiones sobre RESTful parecen centrarse en HTTP y su uso desde un navegador y demás. Tengo entendido que R. Fielding acuñó el término cuando describió la arquitectura y las decisiones que conducen a HTTP. Su tesis trata más sobre la arquitectura y la capacidad de caché de los recursos que sobre HTTP.

Si está realmente interesado en qué es una arquitectura RESTful y por qué funciona, lea su tesis varias veces y lea todo , no solo el Capítulo 5. A continuación, analice por qué funciona el DNS . Lea sobre la organización jerárquica del DNS y cómo funcionan las referencias. Luego lea y considere cómo funciona el almacenamiento en caché de DNS. Finalmente, lea las especificaciones HTTP ( RFC2616 y RFC3040 en particular) y considere cómo y por qué el almacenamiento en caché funciona de la forma en que lo hace. Al final, simplemente hará clic. La revelación final para mí fue cuando vi la similitud entre DNS y HTTP. Después de esto, comienza a comprender por qué SOA y las interfaces de paso de mensajes son escalables.

Creo que el truco más importante para comprender la importancia arquitectónica y las implicaciones de rendimiento de las arquitecturas RESTful y Shared Nothing es evitar obsesionarse con la tecnología y los detalles de implementación. Concéntrese en quién posee los recursos, quién es responsable de crearlos/mantenerlos, etc. Luego piense en las representaciones, protocolos y tecnologías.

D.Shawley avatar Mar 22 '2009 19:03 D.Shawley

Esto es lo que podría parecer.

Crea un usuario con tres propiedades:

POST /user
fname=John&lname=Doe&age=25

El servidor responde:

200 OK
Location: /user/123

En el futuro, podrá recuperar la información del usuario:

GET /user/123

El servidor responde:

200 OK
<fname>John</fname><lname>Doe</lname><age>25</age>

Para modificar el registro ( lnamey agepermanecerá sin cambios):

PATCH /user/123
fname=Johnny

Para actualizar el registro (y en consecuencia lnameserá ageNULL):

PUT /user/123
fname=Johnny
pbreitenbach avatar Jul 04 '2009 05:07 pbreitenbach