Comprensión de REST: verbos, códigos de error y autenticación
Frecuentes
Visto 135,298 veces
617
Estoy buscando una manera de ajustar las API a las funciones predeterminadas en mis aplicaciones web, bases de datos y CMS basados en PHP.
He mirado a mi alrededor y he encontrado varios marcos "esqueléticos". Además de las respuestas a mi pregunta, hay Tónico, un framework REST que me gusta porque es muy ligero.
Me gusta REST por su simplicidad y me gustaría crear una arquitectura API basada en él. Estoy tratando de entender los principios básicos y aún no los he entendido completamente. Por tanto, una serie de preguntas.
1. ¿Lo estoy entendiendo bien?
Digamos que tengo un recurso "usuarios". Podría configurar una serie de URI como este:
/api/users when called with GET, lists users
/api/users when called with POST, creates user record
/api/users/1 when called with GET, shows user record
when called with PUT, updates user record
when called with DELETE, deletes user record
¿Es esta una representación correcta de una arquitectura RESTful hasta ahora?
2. Necesito más verbos
Crear, Actualizar y Eliminar puede ser suficiente en teoría, pero en la práctica necesitaré muchos más verbos. Me doy cuenta de que estas son cosas que podría estar incrustado en una solicitud de actualización, pero son acciones específicas que pueden tener códigos de retorno específicos y no quisiera incluirlos todos en una sola acción.
Algunos que me vienen a la mente en el ejemplo de usuario son:
activate_login
deactivate_login
change_password
add_credit
¿Cómo expresaría acciones como las de una arquitectura de URL RESTful?
Mi instinto sería hacer una llamada GET a una URL como
/api/users/1/activate_login
y espere un código de estado de vuelta.
Sin embargo, eso se desvía de la idea de usar verbos HTTP. ¿Qué piensas?
3. Cómo devolver códigos y mensajes de error
Una gran parte de la belleza de REST proviene de su uso de métodos HTTP estándar. En caso de error, emito un encabezado con un código de estado de error 3xx, 4xx o 5xx. Para obtener una descripción detallada del error, puedo usar el cuerpo (¿verdad?). Hasta aquí todo bien. Pero, ¿cuál sería la forma de transmitir un código de error propietario que es más detallado en la descripción de lo que salió mal (por ejemplo, "no se pudo conectar a la base de datos" o "inicio de sesión incorrecto en la base de datos")? Si lo coloco en el cuerpo junto con el mensaje, tengo que analizarlo después. ¿Existe un encabezado estándar para este tipo de cosas?
4. Cómo realizar la autenticación
- ¿Cómo sería una autenticación basada en claves API siguiendo los principios REST?
- ¿Hay puntos fuertes en contra del uso de sesiones al autenticar un cliente REST, además de que es una violación flagrante del principio REST? :) (solo bromeo a medias aquí, la autenticación basada en sesiones funcionaría bien con mi infraestructura existente).
10 Respuestas
631
Me di cuenta de esta pregunta un par de días tarde, pero creo que puedo agregar algo de información. Espero que esto pueda ser útil para su empresa RESTful.
Punto 1: ¿Lo estoy entendiendo bien?
Entendiste bien. Esa es una representación correcta de una arquitectura RESTful. Puede encontrar la siguiente matriz de Wikipedia muy útil para definir sus sustantivos y verbos:
Cuando se trata de un Collection URI como: http://example.com/resources/
: Enumera los miembros de la colección, completa con sus URI de miembro para una mayor navegación. Por ejemplo, enumere todos los autos a la venta.
PUT: Significado definido como "reemplazar toda la colección por otra colección".
PUBLICAR: Crea una nueva entrada en la colección donde la colección asigna automáticamente el ID. El ID creado generalmente se incluye como parte de los datos devueltos por esta operación.
BORRAR: Significado definido como "eliminar toda la colección".
Cuando se trata de un Miembro URI como: http://example.com/resources/7HOU57Y
: Recupera una representación del miembro direccionado de la colección expresada en un tipo MIME apropiado.
PUT: Actualice el miembro de la colección al que se dirige o créelo con el ID especificado.
PUBLICAR: Trata al miembro al que se dirige como una colección por derecho propio y crea un nuevo subordinado del mismo.
BORRAR: Elimina el miembro de la colección al que se dirige.
Punto 2: necesito más verbos
En general, cuando crea que necesita más verbos, en realidad puede significar que es necesario volver a identificar sus recursos. Recuerde que en REST siempre está actuando sobre un recurso o sobre una colección de recursos. Lo que elija como recurso es bastante importante para la definición de su API.
Activar / Desactivar inicio de sesión: Si está creando una nueva sesión, es posible que desee considerar "la sesión" como el recurso. Para crear una nueva sesión, use POST para http://example.com/sessions/
con las credenciales en el cuerpo. Para caducar, use PUT o DELETE (tal vez dependiendo de si tiene la intención de mantener un historial de sesión) para http://example.com/sessions/SESSION_ID
.
Cambia la contraseña: Esta vez el recurso es "el usuario". Necesitarías un PUT para http://example.com/users/USER_ID
con las contraseñas nuevas y antiguas en el cuerpo. Estás actuando sobre el recurso "del usuario" y un cambio de contraseña es simplemente una solicitud de actualización. Es bastante similar a la declaración UPDATE en una base de datos relacional.
Mi instinto sería hacer una llamada GET a una URL como
/api/users/1/activate_login
Esto va en contra de un principio REST muy básico: el uso correcto de los verbos HTTP. Cualquier solicitud GET nunca debe dejar ningún efecto secundario.
Por ejemplo, una solicitud GET nunca debe crear una sesión en la base de datos, devolver una cookie con un nuevo ID de sesión ni dejar ningún residuo en el servidor. El verbo GET es como la instrucción SELECT en un motor de base de datos. Recuerde que la respuesta a cualquier solicitud con el verbo GET debe poder almacenarse en caché cuando se solicite con los mismos parámetros, al igual que cuando solicita una página web estática.
Punto 3: Cómo devolver mensajes y códigos de error
Considere los códigos de estado HTTP 4xx o 5xx como categorías de error. Puedes elaborar el error en el cuerpo.
Error al conectarse a la base de datos: / Inicio de sesión incorrecto en la base de datos: En general, debería utilizar un error 500 para este tipo de errores. Este es un error del lado del servidor. El cliente no hizo nada malo. 500 errores normalmente se consideran "reintegrables". es decir, el cliente puede volver a intentar exactamente la misma solicitud y esperar que tenga éxito una vez que se resuelvan los problemas del servidor. Especifique los detalles en el cuerpo, para que el cliente pueda brindarnos algún contexto a los humanos.
La otra categoría de errores sería la familia 4xx, que en general indican que el cliente hizo algo mal. En particular, esta categoría de errores normalmente le indica al cliente que no es necesario volver a intentar la solicitud tal como está, porque seguirá fallando permanentemente. es decir, el cliente necesita cambiar algo antes de volver a intentar esta solicitud. Por ejemplo, los errores "Recurso no encontrado" (HTTP 404) o "Solicitud con formato incorrecto" (HTTP 400) se incluirían en esta categoría.
Punto 4: Cómo realizar la autenticación
Como se señaló en el punto 1, en lugar de autenticar a un usuario, es posible que desee pensar en crear una sesión. Se le devolverá un nuevo "ID de sesión", junto con el código de estado HTTP correspondiente (200: Acceso concedido o 403: Acceso denegado).
A continuación, le preguntará a su servidor RESTful: "¿Puede OBTENER el recurso para este ID de sesión?".
No hay un modo autenticado; REST no tiene estado: usted crea una sesión, le pide al servidor que le proporcione recursos utilizando este ID de sesión como parámetro y, al cerrar la sesión, cancela o caduca la sesión.
Respondido 14 ago 16, 02:08
Muy bien, sin embargo su uso de PUT
cambiar una contraseña probablemente sea incorrecto; PUT
requiere todo el recurso, por lo que tendría que enviar todos los atributos de usuario para cumplir con HTTP (y por lo tanto con HATEOAS REST). Más bien, para simplemente cambiar la contraseña se debe usar PATCH
or POST
. - lorenzo dol
Creo que esta publicación sería perfecta si expandieras más lo que "POST: trata al miembro al que se dirige como una colección por derecho propio y crea un nuevo subordinado". medio. - Encontré lo que significa buscar en Google: es una excepción a su excelente respuesta. - Martín Konecny
No estoy de acuerdo con la última frase. Estás explicando cómo REST es apátrida. Iniciar sesión para crear una sesión y luego cerrar la sesión para finalizar la sesión después de trabajar un poco es el mejor ejemplo de una API con estado. - Brandon
"Esto va en contra de un principio REST muy básico: el uso correcto de los verbos HTTP. Cualquier solicitud GET nunca debe dejar ningún efecto secundario". - ¿Qué sucede si desea mantener un recuento de visitas para el recurso? - bobbyalex
Este artículo debería responder a sus preguntas. saipraveenblog.wordpress.com/2014/09/29/rest-api-best-practices - java_geek
80
En pocas palabras, está haciendo esto completamente al revés.
No debería abordar esto desde las URL que debería usar. Las URL vendrán efectivamente "gratis" una vez que haya decidido qué recursos son necesarios para su sistema Y cómo los representará, y las interacciones entre los recursos y el estado de la aplicación.
Para citar roy campo
Una API REST debería dedicar casi todo su esfuerzo descriptivo a definir los tipos de medios utilizados para representar recursos y controlar el estado de la aplicación, o definir nombres de relaciones extendidas y / o marcas habilitadas para hipertexto para los tipos de medios estándar existentes. Cualquier esfuerzo dedicado a describir qué métodos usar en qué URI de interés debe definirse completamente dentro del alcance de las reglas de procesamiento para un tipo de medio (y, en la mayoría de los casos, ya definido por los tipos de medios existentes). [El fracaso aquí implica que la información fuera de banda está impulsando la interacción en lugar del hipertexto].
La gente siempre comienza con los URI y piensa que esta es la solución, y luego tiende a perder un concepto clave en la arquitectura REST, en particular, como se citó anteriormente, "El fracaso aquí implica que la información fuera de banda impulsa la interacción en lugar del hipertexto. "
Para ser honesto, muchos ven un montón de URI y algunos GET, PUT y POST y piensan que REST es fácil. DESCANSAR no es fácil. RPC sobre HTTP es fácil, mover blobs de datos de ida y vuelta enviados mediante proxy a través de cargas útiles HTTP es fácil. REST, sin embargo, va más allá de eso. REST es independiente del protocolo. HTTP es muy popular y apto para sistemas REST.
REST vive en los tipos de medios, sus definiciones y cómo la aplicación impulsa las acciones disponibles para esos recursos a través del hipertexto (enlaces, de manera efectiva).
Hay diferentes puntos de vista sobre los tipos de medios en los sistemas REST. Algunos prefieren cargas útiles específicas de la aplicación, mientras que a otros les gusta elevar los tipos de medios existentes a roles que son apropiados para la aplicación. Por ejemplo, por un lado, tiene esquemas XML específicos diseñados para su aplicación en lugar de usar algo como XHTML como su representación, tal vez a través de microformatos y otros mecanismos.
Ambos enfoques tienen su lugar, creo, el XHTML funciona muy bien en escenarios que se superponen tanto a la web impulsada por humanos como a la impulsada por máquinas, mientras que el primero, tipos de datos más específicos, creo que facilitan mejor las interacciones máquina a máquina. Encuentro que la mejora de los formatos básicos puede hacer que la negociación de contenido sea potencialmente difícil. "application / xml + yourresource" es mucho más específico como tipo de medio que "application / xhtml + xml", ya que este último puede aplicarse a muchas cargas útiles que pueden o no ser algo en lo que un cliente de máquina esté realmente interesado, ni tampoco determinar sin introspección.
Sin embargo, XHTML funciona muy bien (obviamente) en la web humana, donde los navegadores web y el renderizado son muy importantes.
Su aplicación lo guiará en ese tipo de decisiones.
Parte del proceso de diseño de un sistema REST es descubrir los recursos de primera clase en su sistema, junto con los recursos de soporte derivados necesarios para respaldar las operaciones en los recursos primarios. Una vez que se descubren los recursos, entonces la representación de esos recursos, así como los diagramas de estado que muestran el flujo de recursos a través del hipertexto dentro de las representaciones son el siguiente desafío.
Recuerde que cada representación de un recurso, en un sistema de hipertexto, combina tanto la representación real del recurso como las transiciones de estado disponibles para el recurso. Considere cada recurso como un nodo en un gráfico, y los enlaces son las líneas que dejan ese nodo a otros estados. Estos enlaces informan a los clientes no solo lo que se puede hacer, sino también lo que se requiere para que se hagan (ya que un buen enlace combina el URI y el tipo de medio requerido).
Por ejemplo, puede tener:
<link href="http://example.com/users" rel="users" type="application/xml+usercollection"/>
<link href="http://example.com/users?search" rel="search" type="application/xml+usersearchcriteria"/>
Su documentación hablará sobre el campo rel llamado "usuarios" y el tipo de medio de "aplicación / xml + suusuario".
Estos enlaces pueden parecer redundantes, todos están hablando con el mismo URI, prácticamente. Pero no lo son.
Esto se debe a que para la relación de "usuarios", ese enlace se refiere a la colección de usuarios, y puede usar la interfaz uniforme para trabajar con la colección (GET para recuperarlos todos, DELETE para eliminarlos todos, etc.)
Si realiza una PUBLICACIÓN en esta URL, deberá pasar un documento "application / xml + usercollection", que probablemente solo contendrá una única instancia de usuario dentro del documento para que pueda agregar el usuario, o no, quizás, para agregar varios en una vez. Quizás su documentación sugiera que simplemente puede pasar un solo tipo de usuario, en lugar de la colección.
Puede ver lo que la aplicación requiere para realizar una búsqueda, según lo definido por el enlace "buscar" y su tipo de medio. La documentación para el tipo de medio de búsqueda le dirá cómo se comporta y qué esperar como resultado.
La conclusión aquí, sin embargo, es que los URI en sí mismos no son básicamente importantes. La aplicación controla los URI, no los clientes. Más allá de unos pocos 'puntos de entrada', sus clientes deben confiar en los URI proporcionados por la aplicación para su trabajo.
El cliente necesita saber cómo manipular e interpretar los tipos de medios, pero no necesita preocuparse mucho hacia dónde van.
Estos dos enlaces son semánticamente idénticos a los ojos de un cliente:
<link href="http://example.com/users?search" rel="search" type="application/xml+usersearchcriteria"/>
<link href="http://example.com/AW163FH87SGV" rel="search" type="application/xml+usersearchcriteria"/>
Por lo tanto, concéntrese en sus recursos. Concéntrese en sus transiciones de estado en la aplicación y en la mejor manera de lograrlo.
respondido 18 mar '14, 01:03
Gracias Will por esta respuesta tan profunda. Varios puntos tomados. Me doy cuenta de que planificar a partir de "cómo se ve la URL" es al revés, y también lo hago desde el lado de los recursos. Tener URL para jugar me facilita la comprensión del concepto. Eso podría sea que mis requisitos se pueden cumplir con un sistema que no sigue al 100% los principios REST como usted lo define aquí. Dibujaré una lista completa de requisitos para cada tipo de recurso, supongo que podré decidir entonces. Salud. - Pekka
31
re 1: Esto se ve bien hasta ahora. Recuerde devolver el URI del usuario recién creado en un encabezado "Ubicación:" como parte de la respuesta a la POST, junto con un código de estado "201 Creado".
re 2: La activación a través de GET es una mala idea, e incluir el verbo en la URI es un olor a diseño. Es posible que desee considerar devolver un formulario en un GET. En una aplicación web, sería un formulario HTML con un botón de envío; en el caso de uso de la API, es posible que desee devolver una representación que contenga un URI a PUT para activar la cuenta. Por supuesto, también puede incluir este URI en la respuesta de POST a / users. El uso de PUT asegurará que su solicitud sea idempotente, es decir, que se pueda enviar de nuevo de forma segura si el cliente no está seguro del éxito. En general, piensa en qué recursos puedes convertir tus verbos (una especie de "sustantificación de verbos"). Pregúntese con qué método está más alineada su acción específica. Por ejemplo, change_password -> PUT; desactivar -> probablemente BORRAR; add_credit -> posiblemente POST o PUT. Apunte al cliente a los URI apropiados incluyéndolos en sus representaciones.
re 3. No invente nuevos códigos de estado, a menos que crea que son tan genéricos que merecen ser estandarizados a nivel mundial. Intente utilizar el código de estado más apropiado disponible (lea sobre todos ellos en RFC 2616). Incluya información adicional en el cuerpo de la respuesta. Si realmente está seguro de que quiere inventar un nuevo código de estado, piénselo de nuevo; si aún lo cree, asegúrese de elegir al menos la categoría correcta (1xx -> OK, 2xx -> informativo, 3xx -> redirección; 4xx-> error del cliente, 5xx -> error del servidor). ¿Mencioné que inventar nuevos códigos de estado es una mala idea?
re 4. Si es posible, utilice el marco de autenticación integrado en HTTP. Vea la forma en que Google realiza la autenticación en GData. En general, no coloque claves de API en sus URI. Intente evitar sesiones para mejorar la escalabilidad y admitir el almacenamiento en caché: si la respuesta a una solicitud difiere debido a algo que ha sucedido antes, generalmente se ha vinculado a una instancia de proceso de servidor específica. Es mucho mejor convertir el estado de la sesión en un estado de cliente (por ejemplo, hacerlo parte de las solicitudes posteriores) o hacerlo explícito convirtiéndolo en un estado de recurso (servidor), es decir, darle su propio URI.
respondido 23 mar '12, 15:03
¿Puede discutir por qué no poner claves API en URL? ¿Es porque son visibles en los registros de proxy? ¿Qué pasa si las claves son transitorias, basadas en el tiempo? ¿Qué pasa si se usa HTTPS? - Mike Schinkel
Además de violar el espíritu (los URI deberían identificar cosas), la principal consecuencia es que arruina el almacenamiento en caché. - Stefan Tilkov
23
1. Tiene la idea correcta sobre cómo diseñar sus recursos, en mi humilde opinión. No cambiaría nada.
2. En lugar de intentar extender HTTP con más verbos, considere a qué se pueden reducir los verbos propuestos en términos de los métodos y recursos HTTP básicos. Por ejemplo, en lugar de activate_login
verbo, puede configurar recursos como: /api/users/1/login/active
que es un booleano simple. Para activar un inicio de sesión, simplemente PUT
un documento que dice "verdadero" o 1 o lo que sea. Para desactivar, PUT
un documento que está vacío o dice 0 o falso.
Del mismo modo, para cambiar o establecer contraseñas, simplemente haga PUT
para /api/users/1/password
.
Siempre que necesite agregar algo (como un crédito), piense en términos de POST
s. Por ejemplo, podrías hacer un POST
a un recurso como /api/users/1/credits
con un cuerpo que contenga el número de créditos a agregar. A PUT
en el mismo recurso podría usarse para sobrescribir el valor en lugar de agregarlo. A POST
con un número negativo en el cuerpo restaría, y así sucesivamente.
3. Recomiendo encarecidamente no extender los códigos de estado HTTP básicos. Si no puede encontrar uno que coincida exactamente con su situación, elija el más cercano y coloque los detalles del error en el cuerpo de la respuesta. Además, recuerde que los encabezados HTTP son extensibles; su aplicación puede definir todos los encabezados personalizados que desee. Una aplicación en la que trabajé, por ejemplo, podría devolver un 404 Not Found
bajo múltiples circunstancias. En lugar de hacer que el cliente analice el cuerpo de la respuesta por el motivo, simplemente agregamos un nuevo encabezado, X-Status-Extended
, que contenía nuestras extensiones de código de estado patentadas. Entonces, es posible que vea una respuesta como:
HTTP/1.1 404 Not Found
X-Status-Extended: 404.3 More Specific Error Here
De esa forma, un cliente HTTP como un navegador web aún sabrá qué hacer con el código 404 normal, y un cliente HTTP más sofisticado puede elegir mirar el X-Status-Extended
encabezado para obtener información más específica.
4. Para la autenticación, recomiendo usar la autenticación HTTP si puede. Pero en mi humilde opinión, no hay nada de malo en usar la autenticación basada en cookies si eso es más fácil para usted.
Respondido el 04 de enero de 10 a las 21:01
Buena idea de usar recursos "extendidos" para hacer cosas en porciones más pequeñas de un recurso más grande. - tambalearse
Las cookies son válidas en HTTP / REST, pero el servidor no debe almacenar la cookie como estado (por lo tanto, no como una sesión). Sin embargo, la cookie puede almacenar un valor como un HMAC, que se puede desmontar sin buscar el estado en otro lugar. - bruce alderson
15
Conceptos básicos de REST
REST tiene una restricción de interfaz uniforme, que establece que el cliente REST debe depender de los estándares en lugar de los detalles específicos de la aplicación del servicio REST real, por lo que el cliente REST no se romperá con cambios menores y probablemente será reutilizable.
Entonces hay un contrato entre el cliente REST y el servicio REST. Si utiliza HTTP como protocolo subyacente, los siguientes estándares forman parte del contrato:
- HTTP 1.1
- definiciones de métodos
- definiciones de códigos de estado
- encabezados de control de caché
- aceptar y encabezados de tipo de contenido
- encabezados de autenticación
- IRI (utf8 URI)
- cuerpo (elige uno)
- tipo MIME específico de la aplicación registrada, p. ej. laberinto + xml
- tipo MIME específico del proveedor, p. ej. vnd.github + json
- tipo MIME genérico con
- vocabulario RDF específico de la aplicación, p. ej. ld + json & hidra, schema.org
- perfil específico de la aplicación, p. ej. hal + json & parámetro de enlace de perfil (supongo)
- hipervínculos
- qué debe contenerlos (elige uno)
- enviando en encabezados de enlace
- enviando una respuesta hipermedia, por ejemplo, html, atom + xml, hal + json, ld + json & hydra, etc.
- semántica
- utilizar relaciones de enlace de IANA y probablemente relaciones de enlace personalizadas
- utilizar un vocabulario RDF específico de la aplicación
- qué debe contenerlos (elige uno)
REST tiene una restricción sin estado, que declara que la comunicación entre el servicio REST y el cliente debe ser sin estado. Esto significa que el servicio REST no puede mantener los estados del cliente, por lo que no puede tener un almacenamiento de sesión del lado del servidor. Tienes que autenticar cada una de las solicitudes. Entonces, por ejemplo, la autenticación básica HTTP (parte del estándar HTTP) está bien, porque envía el nombre de usuario y la contraseña con cada solicitud.
Para responder tus preguntas
Si puede ser.
Solo para mencionar, a los clientes no les importa la estructura de IRI, les importa la semántica, porque siguen enlaces que tienen relaciones de enlace o atributos de datos enlazados (RDF).
Lo único importante acerca de los IRI es que un solo IRI debe identificar un solo recurso. Se permite que un solo recurso, como un usuario, tenga muchos IRI diferentes.
Es bastante simple por qué usamos buenos IRI como
/users/123/password
; Es mucho más fácil escribir la lógica de enrutamiento en el servidor cuando comprende el IRI simplemente leyéndolo.Tienes más verbos, como PUT, PATCH, OPTIONS, e incluso más, pero no necesitas más de ellos ... En lugar de agregar nuevos verbos tienes que aprender a agregar nuevos recursos.
activate_login -> PUT /login/active true deactivate_login -> PUT /login/active false change_password -> PUT /user/xy/password "newpass" add_credit -> POST /credit/raise {details: {}}
(El inicio de sesión no tiene sentido desde la perspectiva REST, debido a la restricción sin estado).
A sus usuarios no les importa por qué existe el problema. Solo quieren saber si hay éxito o error, y probablemente un mensaje de error que puedan entender, por ejemplo: "Lo sentimos, pero no pudimos guardar tu publicación", etc.
Los encabezados de estado HTTP son sus encabezados estándar. Todo lo demás debería estar en el cuerpo, creo. Un solo encabezado no es suficiente para describir, por ejemplo, mensajes de error multilingües detallados.
La restricción sin estado (junto con la caché y las restricciones del sistema en capas) asegura que el servicio se escala bien. Seguramente no querrás mantener millones de sesiones en el servidor, cuando puedes hacer lo mismo en los clientes ...
El cliente de terceros obtiene un token de acceso si el usuario le otorga acceso mediante el cliente principal. Después de eso, el cliente de terceros envía el token de acceso con cada solicitud. Hay soluciones más complicadas, por ejemplo, puede firmar todas las solicitudes, etc. Para obtener más detalles, consulte el manual de OAuth.
Literatura relacionada
- Estilos arquitectónicos y diseño de arquitecturas de software basadas en red
Disertación de Roy Thomas Fielding (autor de REST)
2000, Universidad de California, Irvine - API web de tercera generación: superando la brecha entre REST y datos vinculados
Disertación de Markus Lanthaler (coautor de JSON-LD y autor de Hydra)
2014, Universidad Tecnológica de Graz, Austria
Respondido el 17 de Septiembre de 14 a las 23:09
12
Para los ejemplos que dijiste, usaría lo siguiente:
active_login
POST /users/1/activation
desactivar_login
DELETE /users/1/activation
Cambia la contraseña
PUT /passwords
(esto supone que el usuario está autenticado)
añadir crédito
POST /credits
(esto supone que el usuario está autenticado)
Para errores, devolvería el error en el cuerpo en el formato en el que recibió la solicitud, por lo que si recibe:
DELETE /users/1.xml
Enviaría la respuesta de vuelta en XML, lo mismo sería cierto para JSON, etc.
Para la autenticación, debe utilizar la autenticación http.
Respondido el 04 de enero de 10 a las 21:01
Yo no usaría create
como parte del URI (recuerde que los URI deben ser sustantivos y los métodos HTTP deben ser verbos que operen con esos sustantivos). En su lugar, tendría un recurso como /users/1/active
que puede ser un booleano simple, y se puede establecer poniendo un 1 o un 0 a ese recurso. - Friedo
Tienes razón, saqué el / create. Debería ser solo una publicación en el recurso singleton. - Jonnii
Yo no usaría activation
en el URI, a menos que manipule y administre explícitamente un recurso con el nombre de /users/1/activation
. ¿Qué hace un GET en eso? ¿Qué hace un PUT? Seguro que me parece que estás verificando el URI. Además, en cuanto a la negociación del tipo de contenido, es mejor dejarlo fuera del URI e insertarlo en los encabezados, como Accept
. - queso
6
- Use la publicación cuando no sepa cómo se vería el nuevo URI del recurso (usted crea un nuevo usuario, la aplicación le asignará al nuevo usuario su identificación), PUT para actualizar o crear recursos que sepa cómo se van a representar (ejemplo : PUT /myfiles/thisismynewfile.txt)
- devolver la descripción del error en el cuerpo del mensaje
- Puede utilizar la autenticación HTTP (si es suficiente) Los servicios web deben ser estatales
Respondido el 04 de enero de 10 a las 20:01
5
Sugeriría (como primer paso) que PUT
solo debe usarse para actualizar entidades existentes. POST
debe usarse para crear otros nuevos. es decir
/api/users when called with PUT, creates user record
no me parece bien. Sin embargo, el resto de su primera sección (re. Uso del verbo) parece lógico.
Respondido el 04 de enero de 10 a las 20:01
probablemente alguien pensó que esto no era realmente una respuesta a su pregunta - lubos hasko
Mi opinión sobre PUT versus POST para crear nuevas entidades es usar PUT cuando la persona que llama controla el nombre del recurso, por lo que puede PUT al recurso exacto y POST cuando la persona que llama controla el nuevo nombre del recurso (como en el ejemplo aquí). - steved
5
Detallado, pero copiado de la especificación del método HTTP 1.1 en http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
9.3 OBTENER
El método GET significa recuperar cualquier información (en forma de entidad) identificada por el Request-URI. Si el Request-URI se refiere a un proceso de producción de datos, son los datos producidos los que se devolverán como la entidad en la respuesta y no como el texto fuente del proceso, a menos que ese texto sea el resultado del proceso.
La semántica del método GET cambia a un "GET condicional" si el mensaje de solicitud incluye un campo de encabezado If-Modified-Since, If-Unmodified-Since, If-Match, If-None-Match o If-Range. Un método GET condicional solicita que la entidad se transfiera solo en las circunstancias descritas por los campos de encabezado condicional. El método GET condicional está destinado a reducir el uso innecesario de la red al permitir que las entidades almacenadas en caché se actualicen sin requerir múltiples solicitudes o transferir datos que ya tiene el cliente.
La semántica del método GET cambia a "GET parcial" si el mensaje de solicitud incluye un campo de encabezado de rango. Un GET parcial solicita que solo se transfiera una parte de la entidad, como se describe en la sección 14.35. El método GET parcial tiene como objetivo reducir el uso innecesario de la red al permitir que las entidades recuperadas parcialmente se completen sin transferir los datos que ya tiene el cliente.
La respuesta a una solicitud GET se puede almacenar en caché si y solo si cumple con los requisitos para el almacenamiento en caché HTTP descritos en la sección 13.
Consulte la sección 15.1.3 para conocer las consideraciones de seguridad cuando se utiliza para formularios.
9.5 POSTE
El método POST se utiliza para solicitar que el servidor de origen acepte la entidad incluida en la solicitud como un nuevo subordinado del recurso identificado por el Request-URI en la Request-Line. POST está diseñado para permitir un método uniforme para cubrir las siguientes funciones:
- Annotation of existing resources;
- Posting a message to a bulletin board, newsgroup, mailing list,
or similar group of articles;
- Providing a block of data, such as the result of submitting a
form, to a data-handling process;
- Extending a database through an append operation.
La función real realizada por el método POST la determina el servidor y generalmente depende del Request-URI. La entidad publicada está subordinada a ese URI de la misma manera que un archivo está subordinado a un directorio que lo contiene, un artículo de noticias está subordinado a un grupo de noticias en el que está publicado o un registro está subordinado a una base de datos.
Es posible que la acción realizada por el método POST no genere un recurso que pueda identificarse mediante un URI. En este caso, 200 (OK) o 204 (Sin contenido) es el estado de respuesta apropiado, dependiendo de si la respuesta incluye o no una entidad que describe el resultado.
Si se ha creado un recurso en el servidor de origen, la respuesta DEBERÍA ser 201 (Creado) y contener una entidad que describa el estado de la solicitud y se refiera al nuevo recurso, y un encabezado de Ubicación (consulte la sección 14.30).
Las respuestas a este método no se pueden almacenar en caché, a menos que la respuesta incluya los campos de encabezado Cache-Control o Expires apropiados. Sin embargo, la respuesta 303 (Ver otros) se puede utilizar para indicar al agente de usuario que recupere un recurso almacenable en caché.
Las solicitudes POST DEBEN obedecer los requisitos de transmisión de mensajes establecidos en la sección 8.2.
Consulte la sección 15.1.3 para conocer las consideraciones de seguridad.
9.6 PONER
El método PUT solicita que la entidad adjunta se almacene bajo el Request-URI proporcionado. Si el Request-URI se refiere a un recurso ya existente, la entidad adjunta DEBERÍA considerarse como una versión modificada de la que reside en el servidor de origen. Si el Request-URI no apunta a un recurso existente, y ese URI puede ser definido como un nuevo recurso por el agente de usuario solicitante, el servidor de origen puede crear el recurso con ese URI. Si se crea un nuevo recurso, el servidor de origen DEBE informar al agente de usuario a través de la respuesta 201 (Creado). Si se modifica un recurso existente, DEBERÍAN enviarse los códigos de respuesta 200 (OK) o 204 (Sin contenido) para indicar que la solicitud se completó con éxito. Si el recurso no se pudo crear o modificar con el Request-URI, se DEBE dar una respuesta de error apropiada que refleje la naturaleza del problema. El destinatario de la entidad NO DEBE ignorar ningún encabezado Content- * (por ejemplo, Content-Range) que no comprenda o implemente y DEBE devolver una respuesta 501 (No implementada) en tales casos.
Si la solicitud pasa a través de un caché y el Request-URI identifica una o más entidades almacenadas en caché actualmente, esas entradas DEBERÍAN tratarse como obsoletas. Las respuestas a este método no se pueden almacenar en caché.
La diferencia fundamental entre las solicitudes POST y PUT se refleja en el significado diferente del Request-URI. El URI en una solicitud POST identifica el recurso que manejará la entidad adjunta. Ese recurso puede ser un proceso de aceptación de datos, una puerta de entrada a algún otro protocolo o una entidad separada que acepta anotaciones. Por el contrario, el URI en una solicitud PUT identifica la entidad adjunta a la solicitud: el agente de usuario sabe qué URI se pretende y el servidor NO DEBE intentar aplicar la solicitud a algún otro recurso. Si el servidor desea que la solicitud se aplique a un URI diferente,
DEBE enviar una respuesta 301 (Movido permanentemente); el agente de usuario PUEDE entonces tomar su propia decisión sobre si redirigir o no la solicitud.
Un solo recurso PUEDE ser identificado por muchos URI diferentes. Por ejemplo, un artículo puede tener un URI para identificar "la versión actual" que es independiente del URI que identifica cada versión en particular. En este caso, una solicitud PUT en un URI general puede resultar en que el servidor de origen defina varios otros URI.
HTTP / 1.1 no define cómo un método PUT afecta el estado de un servidor de origen.
Las solicitudes PUT DEBEN obedecer los requisitos de transmisión de mensajes establecidos en la sección 8.2.
A menos que se especifique lo contrario para un encabezado de entidad en particular, los encabezados de entidad en la solicitud PUT DEBERÍAN aplicarse al recurso creado o modificado por el PUT.
9.7 BORRAR
El método DELETE solicita que el servidor de origen elimine el recurso identificado por el Request-URI. Este método PUEDE ser anulado por la intervención humana (u otros medios) en el servidor de origen. No se puede garantizar al cliente que la operación se ha llevado a cabo, incluso si el código de estado devuelto por el servidor de origen indica que la acción se ha completado con éxito. Sin embargo, el servidor NO DEBE indicar éxito a menos que, en el momento en que se dé la respuesta, tenga la intención de eliminar el recurso o moverlo a una ubicación inaccesible.
Una respuesta exitosa DEBERÍA ser 200 (OK) si la respuesta incluye una entidad que describe el estado, 202 (Aceptada) si la acción aún no se ha promulgado, o 204 (Sin contenido) si la acción se ha promulgado pero la respuesta no incluye una entidad.
Si la solicitud pasa a través de un caché y el Request-URI identifica una o más entidades almacenadas en caché actualmente, esas entradas DEBERÍAN tratarse como obsoletas. Las respuestas a este método no se pueden almacenar en caché.
Respondido el 04 de enero de 10 a las 20:01
2
Acerca de los códigos de retorno REST: es Mal para mezclar códigos de protocolo HTTP y resultados REST.
Sin embargo, vi muchas implementaciones mezclándolos y muchos desarrolladores pueden no estar de acuerdo conmigo.
Los códigos de retorno HTTP están relacionados con HTTP Request
sí mismo. Una llamada REST se realiza mediante una solicitud de Protocolo de transferencia de hipertexto y funciona a un nivel inferior al del método REST invocado. REST es un concepto / enfoque, y su resultado es un negocios / lógico resultado, mientras que el código de resultado HTTP es un transporte uno.
Por ejemplo, devolver "404 Not found" cuando llamas a / users / es confuso, porque puede significar:
- El URI es incorrecto (HTTP)
- No se encuentran usuarios (REST)
"403 Prohibido / Acceso denegado" puede significar:
- Se necesita un permiso especial. Los navegadores pueden manejarlo preguntando al usuario / contraseña. (HTTP)
- Permisos de acceso incorrectos configurados en el servidor. (HTTP)
- Necesitas estar autenticado (REST)
Y la lista puede continuar con '500 Server error "(un error de Apache / Nginx HTTP arrojado o un error de restricción comercial en REST) u otros errores HTTP, etc.
A partir del código, es difícil entender cuál fue el motivo de la falla, una falla HTTP (transporte) o una falla REST (lógica).
Si la solicitud HTTP se realizó físicamente con éxito, debería siempre devuelve el código 200, independientemente de si se han encontrado o no los registros. Porque el recurso URI es encontrado y fue manejado por el servidor http. Sí, puede devolver un conjunto vacío. ¿Es posible recibir una página web vacía con 200 como resultado http, verdad?
En lugar de esto, puede devolver el código HTTP 200 y simplemente un JSON con una matriz / objeto vacío, o utilizar un indicador de resultado / éxito bool para informar sobre el estado de la operación realizada.
Además, algunos proveedores de Internet pueden interceptar sus solicitudes y devolverle un código http 404. Esto no significa que no se encuentren sus datos, pero es algo incorrecto a nivel de transporte.
Desde wiki:
En julio de 2004, el proveedor de telecomunicaciones del Reino Unido BT Group implementó el sistema de bloqueo de contenido Cleanfeed, que devuelve un error 404 a cualquier solicitud de contenido identificado como potencialmente ilegal por Internet Watch Foundation. Otros ISP devuelven un error HTTP 403 "prohibido" en las mismas circunstancias. También se ha informado en Tailandia y Túnez de la práctica de emplear errores 404 falsos como medio para ocultar la censura. En Túnez, donde la censura era severa antes de la revolución de 2011, la gente se dio cuenta de la naturaleza de los falsos errores 404 y creó un personaje imaginario llamado "Ammar 404" que representa "el censor invisible".
Respondido el 23 de Septiembre de 17 a las 13:09
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas web-services rest or haz tu propia pregunta.
@Daniel, gracias por editar. "Yo más verbos" fue un juego de palabras intencional, pero lo dejo como está, es más fácil de leer ahora. :) - Pekka
Por cierto, sobre la descripción del error. Terminé poniendo la descripción del error en el encabezado de la respuesta. Simplemente agregue el encabezado llamado 'Descripción de error'. - Andrii Muzychuk
Esto se parece más a preguntas de seguridad de la aplicación. La seguridad de las aplicaciones no es de lo que se trata REST. - Nazar Merza
@NazarMerza ¿cómo son las preguntas de seguridad de la aplicación 1., 2. y 3.? - Pekka