¿Cómo crear URL REST sin verbos?

283

Me cuesta determinar cómo diseñar URL relajantes. Estoy totalmente de acuerdo con el enfoque tranquilo de usar URL con sustantivos y no verbos, no entiendo cómo hacer esto.

Estamos creando un servicio para implementar una calculadora financiera. La calculadora toma varios parámetros que cargaremos a través de un archivo CSV. Los casos de uso implicarían:

  1. Subir nuevos parámetros
  2. Obtenga los últimos parámetros
  3. Obtener parámetros para una fecha comercial determinada
  4. Hacer un conjunto de parámetros activo
  5. Validar un conjunto de parámetros

Entiendo que el enfoque tranquilo sería tener las siguientes URL de tipo:

/parameters
/parameters/12-23-2009

Puede lograr los primeros tres casos de uso con:

  1. POST donde incluye el archivo de parámetros en la solicitud de publicación
  2. OBTENER la primera URL
  3. OBTENER la segunda URL

Pero, ¿cómo haces el caso de uso cuarto y quinto sin un verbo? ¿No necesitarías URL como:

/parameters/ID/activate
/parameters/ID/validate

??

Marcus Leon
fuente
3
Prefiero PATCH en lugar de POST para una actualización parcial.
user2016971

Respuestas:

71

Quizás algo como:

PUT /parameters/activation HTTP/1.1
Content-Type: application/json; encoding=UTF-8
Content-Length: 18

{ "active": true }
Yfeldblum
fuente
1
POSTestá bien si necesita realizar un "procedimiento" como verificar los parámetros cada vez que envía una solicitud. Pero cuando modifica el estado (aplicación) del recurso, en realidad actualiza el recurso existente, no crea algún recurso nuevo ni publica una solicitud de procesamiento.
Andrey Vlasovskikh
19
PUT es para crear un nuevo recurso o colocar (en su totalidad, no en parte) un nuevo recurso en una URL en particular. No veo cómo PUT encaja en este caso.
Breton
30
En realidad, POSTvs PUTno es exactamente igual insertvs update. PUTactualiza el recurso correspondiente a la ruta dada, o crea un nuevo recurso correspondiente a la ruta dada. POSTcrea un nuevo recurso en alguna parte. Por ejemplo, PUT /blog/posts/3/comments/5actualizará el comentario apropiado, mientras POST /blog/posts/3/commentsque creará un nuevo commentrecurso (y debería devolver la ruta al nuevo recurso en la respuesta).
yfeldblum
23
@Justice @Breton La diferencia más importante es que PUTes idempotente mientras POSTque no lo es. Por lo general, debe poner tantas restricciones sobre lo que proporciona como resultado como sea posible. Seguir con PUTda más información al cliente del servicio.
Andrey Vlasovskikh
3
El recurso también podría haber sido / parámetros / estado y el cuerpo de la solicitud podría haber sido simplemente "activo". De esa manera, de alguna manera, está colocando un recurso completamente nuevo en una URL particular.
Carlos Aguayo
991

Principios generales para un buen diseño de URI:

  • No use parámetros de consulta para alterar el estado
  • No use rutas de mayúsculas y minúsculas si puede evitarlo; minúscula es mejor
  • No use extensiones específicas de implementación en sus URI (.php, .py, .pl, etc.)
  • No caigas en RPC con tus URI
  • No limitar su espacio URI tanto como sea posible
  • ¿Los segmentos de trazado torreón cortos
  • Do prefieren ya sea /resourceo /resource/; crea 301 redirecciones desde la que no usas
  • Hacer parámetros de consulta para uso sub-selección de un recurso; es decir, paginación, consultas de búsqueda
  • Do mover cosas fuera de la URI que debe estar en un cuerpo de cabecera HTTP o una

(Nota: no dije "diseño de URI RESTful"; los URI son esencialmente opacos en REST).

Principios generales para la elección del método HTTP:

  • No utilizar nunca GET a otro alter; esta es una excelente manera de que el robot de Google arruine tu día
  • No use PUT a menos que esté actualizando un recurso completo
  • No use PUT a menos que también pueda legítimamente hacer un GET en el mismo URI
  • No use POST para recuperar información de larga duración o que sea razonable almacenar en caché
  • No realice una operación que no sea idempotente con PUT
  • Use GET tanto como sea posible
  • Hacer uso de POST en la preferencia para poner en caso de duda
  • Hacer uso post cada vez que tenga que hacer algo que se siente como RPC
  • Hacer uso PUT para las clases de recursos que son más grandes o jerárquico
  • No uso BORRAR con preferencia a POST a recursos remove
  • Use GET para cosas como cálculos, a menos que su entrada sea grande, en cuyo caso use POST

Principios generales del diseño de servicios web con HTTP:

  • No ponga metadatos en el cuerpo de una respuesta que debería estar en un encabezado
  • No coloque metadatos en un recurso separado a menos que incluirlo cree una sobrecarga significativa
  • Use el código de estado apropiado
    • 201 Createddespués de crear un recurso; el recurso debe existir en el momento en que se envía la respuesta
    • 202 Accepted después de realizar una operación con éxito o crear un recurso de forma asincrónica
    • 400 Bad Requestcuando alguien realiza una operación sobre datos que son claramente falsos; para su aplicación esto podría ser un error de validación; generalmente reserva 500 para excepciones no capturadas
    • 401 Unauthorizedcuando alguien accede a su API sin proporcionar un Authorizationencabezado necesario o cuando las credenciales dentro de la misma Authorizationno son válidas; no use este código de respuesta si no espera credenciales a través de un Authorizationencabezado.
    • 403 Forbidden cuando alguien accede a su API de una manera que podría ser maliciosa o si no está autorizado
    • 405 Method Not Allowed cuando alguien usa POST cuando debería haber usado PUT, etc.
    • 413 Request Entity Too Large cuando alguien intenta enviarte un archivo inaceptablemente grande
    • 418 I'm a teapot cuando intentas preparar café con una tetera
  • Hacer uso de las cabeceras de caché siempre que pueda
    • ETag los encabezados son buenos cuando puede reducir fácilmente un recurso a un valor hash
    • Last-Modified debería indicarle que mantener una marca de tiempo de cuándo se actualizan los recursos es una buena idea
    • Cache-Controly Expiresdeben recibir valores razonables
  • Haga todo lo posible para honrar los encabezados de almacenamiento en caché en una solicitud ( If-None-Modified, If-Modified-Since)
  • ¿Los redirecciones utilizan cuando tienen sentido, pero éstos deben ser raro para un servicio web

Con respecto a su pregunta específica, POST debe usarse para los números 4 y 5. Estas operaciones caen bajo la directriz "similar a RPC" anterior. Para el n. ° 5, recuerde que POST no necesariamente tiene que usarse Content-Type: application/x-www-form-urlencoded. Esto podría ser fácilmente una carga útil JSON o CSV.

Bob Aman
fuente
11
413 está destinado al tamaño de la solicitud que se le envía para que pueda rechazar cortésmente a alguien que le envíe datos, a menudo junto con 411 para que obligue a las personas a decirle cuánto se envía. Para el ejemplo dado contra 413, creo que 400 sería una respuesta más apropiada.
Garry Shutler
55
+1 ya que este es un gran recurso. Sin embargo, es un recurso general y no responde directamente la pregunta. Idealmente, esto debería incluir un párrafo adicional con una respuesta específica.
Samuel Neff
@GarryShutler Buena captura, tienes toda la razón. Gracias por la edición
Bob Aman
1
Sí, solo usaría PUT en los casos en que sobrescriba todo el objeto. Sin embargo, afirmaría que PATCH o POST son razonables en el caso de una actualización parcial de un recurso. PATCH es más claro en términos de lo que la operación va a hacer, pero debido a que no todos los clientes son capaces de emitir una solicitud de PATCH , es totalmente apropiado permitir una POST , e incluso podría llegar a defender que un POST siempre debe permitirse como alternativa si se usa PATCH .
Bob Aman
1
+1 por 409 errores. Un error 400 es algo que podría resolverse mediante una validación suficiente del lado del cliente. Un 409 aclara que la solicitud en sí misma era aceptable y consistente, pero entra en conflicto con algún aspecto del estado del servidor (generalmente controles de concurrencia, pero teóricamente cualquier restricción que no sea de entrada).
claytond
18

Siempre que parezca que necesitas un nuevo verbo, piensa en convertir ese verbo en un sustantivo. Por ejemplo, convierta 'activar' en 'activación' y 'validar' en 'validación'.

Pero solo por lo que ha escrito, diría que su aplicación tiene problemas mucho mayores.

Cada vez que se propone un recurso llamado 'parámetro', debe enviar señales de alerta en la mente de cada miembro del equipo del proyecto. 'parámetro' puede aplicarse literalmente a cualquier recurso; No es lo suficientemente específico.

¿Qué representa exactamente un 'parámetro'? Probablemente una serie de cosas diferentes, cada una de las cuales debería tener un recurso separado dedicado a ella.

Otra forma de llegar a esto: cuando discute su aplicación con los usuarios finales (aquellos que presumiblemente saben poco sobre programación), ¿cuáles son las palabras que ellos mismos usan repetidamente?

Esas son las palabras con las que debería diseñar su aplicación.

Si aún no ha tenido esta conversión con posibles usuarios, ¡pare todo ahora y no escriba otra línea de código hasta que lo haga! Solo entonces su equipo tendrá una idea de lo que debe construirse.

No sé nada sobre el software financiero, pero si tuviera que adivinar, diría que algunos de los recursos pueden tener nombres como "Informe", "Pago", "Transferencia" y "Moneda".

Hay varios libros buenos sobre esta parte del proceso de diseño de software. Dos que puedo recomendar son los patrones de diseño y análisis basados ​​en dominio .

Rich Apodaca
fuente
1
Este es un muy buen punto. Es fácil pasar por alto si está en el estado de ánimo para procesar la lógica formal y el razonamiento. No importa qué X es, siempre y cuando se ajuste a las otras partes de una manera válida. Los factores humanos simplemente se escapan.
Breton
1
A veces me resulta útil convertir las palabras en un "recurso de procesamiento" como "activador" o "validador". Según RFC 2616 POST se puede utilizar para "Proporcionar un bloque de datos ... a un proceso de manejo de datos"
Darrel Miller,
Entendido. En este caso, los usuarios se refieren a los datos como "parámetros" (o "parámetros de riesgo" o algo similar). La lista de parámetros contiene muchos tipos diferentes de configuraciones, pero los parámetros siempre se cargan como un conjunto completo (en un archivo CSV).
Marcus Leon el
@ Marcus: eso suena como un caso muy inusual. Tal vez si explicara lo que hace su aplicación con más detalle, podríamos ofrecerle mejores sugerencias para identificar recursos.
Rich Apodaca
1
"cuando discute su aplicación con los usuarios finales, ¿cuáles son las palabras que ellos mismos usan repetidamente?" ... ¿y si todos son verbos? XD
Amalgovinus
11

El diseño de sus URL no tiene nada que ver con si su aplicación es RESTful o no. La frase "URL RESTful" no tiene sentido.

Creo que deberías leer un poco más sobre lo que REST es en realidad. REST trata las URLS como opacas, y como tal no sabe qué hay en ellas, si hay verbos o sustantivos o lo que sea. Es posible que aún desee diseñar sus URL, pero eso se trata de la interfaz de usuario, no de REST.

Dicho esto, pasemos a su pregunta: los dos últimos casos no son RESTful y no encajan en ningún tipo de esquema de descanso. Esos son lo que podrías llamar RPC. Si te tomas en serio REST, tendrás que repensar cómo funciona tu aplicación desde cero. O eso, o abandone REST y simplemente haga su aplicación como una aplicación RPC.

Hrmmm tal vez no.

La idea aquí es que debe tratar todo como un recurso, por lo que una vez que un conjunto de parámetros tiene una URL a la que puede referirse, simplemente agrega:

GET [parametersurl]/validationresults

POST [paramatersurl]
body: {command:"activate"}

Pero, de nuevo, esa cosa de activación es RPC, no REST.

Bretón
fuente
Declaras un punto interesante aquí. ¿Puedes explicar un poco más cómo sería el enfoque RESTful para algo como esto?
poezn
He pasado un poco de tiempo leyendo las respuestas aquí, y creo que la justicia podría estar en algo. Él modela las propiedades individuales de su objeto de parámetros como recursos individuales y utiliza el verbo PUT para reemplazar el contenido de esa propiedad en ese recurso. Esto es modelar el estado de cada objeto como una colección de recursos, y modificar el estado como colocar, eliminar o modificar el recurso. En cuanto a la validación: solo necesita un recurso que indique mágicamente si los parámetros son válidos o no, como se indicó anteriormente en mi respuesta. Eso estaría bien, siempre y cuando no tenga efectos secundarios.
Breton
Siempre, por supuesto, que lo que hace "Activar" es simplemente establecer una propiedad única en verdadero. Si tiene que hacer algo más, entonces todavía no es RESTful, y no estoy seguro de cómo modelarlo RESTfully.
Breton
No creo que pueda decir que los dos últimos casos no son RESTful. En efecto, Activar y Validar son solo formas indirectas de decir que el recurso está cambiando a un nuevo estado en una máquina de estados. REST es bastante capaz de modelar esto.
Darrel Miller el
@Darrel, creo que señala una parte de REST que puede ser un desafío para muchas personas que son nuevas en REST. ¿Cómo podría implementar una operación "Validar recurso x"? Creo que lo desafiante es que es una operación que podría resultar en un cambio de estado, pero el nuevo estado es el resultado de la solicitud realizada.
Sean
6

Los requisitos de activación y validación son situaciones en las que está intentando cambiar el estado de un recurso. No es diferente que hacer un pedido "completado", o alguna otra solicitud "enviada". Existen numerosas formas de modelar este tipo de cambio de estado, pero creo que a menudo funciona: crear recursos de recolección para recursos del mismo estado y luego mover el recurso entre las colecciones para afectar el estado.

Por ejemplo, crear algunos recursos como,

/ActiveParameters
/ValidatedParameters

Si desea activar un conjunto de parámetros, agréguelo a la colección ActiveParameters. Puede pasar el conjunto de parámetros como un cuerpo de entidad, o puede pasar una url como parámetro de consulta, de la siguiente manera:

POST /ActiveParameters?parameter=/Parameters/{Id}

Lo mismo se puede hacer con los / ValidatedParameters. Si los parámetros no son válidos, el servidor puede devolver "Solicitud incorrecta" a la solicitud para agregar los parámetros a la colección de parámetros validados.

Darrel Miller
fuente
1

Sugeriría los siguientes recursos y métodos Meta.

Active los parámetros y / o valídelos:

> PUT /parameters/<id>/meta HTTP/1.1
> Host: example.com
> Content-Type: application/json
> Connection: close
>
> {'active': true, 'require-valid': true}
>
< HTTP/1.1 200 OK
< Connection: close
<

Compruebe si los parámetros son activos y válidos:

> GET /parameters/<id>/meta HTTP/1.1
> Host: example.com
> Connection: close
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Connection: close
<
< {
<     'active': true,
<     'require-valid': true,
<     'valid': {'status': false, 'reason': '...'}
< }
<
Andrey Vlasovskikh
fuente
Según tengo entendido, la pregunta es sobre el nombre de las URL relajantes, no sobre la funcionalidad, ¿no?
poezn
2
Una pregunta limitada a "URL RESTful" es una mala pregunta y no debe responderse. En su lugar, la pregunta debe ampliarse para considerar "recursos RESTful, con métodos y URL asociados", y responderse como tal.
yfeldblum
Según lo entendí, la pregunta era sobre las convenciones de nomenclatura de URL y los métodos HTTP a los que el recurso nombrado debería responder.
Andrey Vlasovskikh
1

Me siento un poco triste al ver que después de más de 10 años no hay una respuesta que indique realmente cómo podría diseñarse algo como lo solicitado en el OP en una arquitectura REST, por lo tanto, siento la necesidad de hacerlo ahora.

Primero lo primero, ¿qué es REST? El acrónimo REST o ReST significa "Transferencia de estado de representación" y define el intercambio del estado de un recurso en un determinado formato de representación. El formato de representación es la marea del tipo de medio negociado. En el caso del application/htmlformato de representación, puede ser una secuencia de contenido de texto con formato HTML que se procesa en el navegador, probablemente después de aplicar un formato de hoja de estilo para colocar ciertos elementos en ciertas ubicaciones.

REST es, en principio, una generalización de la Web navegable que todos conocemos, aunque se dirige a todo tipo de aplicaciones y no solo a los navegadores. Por lo tanto, por diseño, los mismos conceptos que se aplican a la Web también se aplican a una arquitectura REST. Una pregunta como cómo lograr algo de una manera "RESTful" se resuelve al responder la pregunta de cómo lograr algo en una página web y luego aplicar los mismos conceptos en la capa de aplicación.

Una calculadora basada en la web generalmente puede comenzar con alguna "página" que le permite ingresar algunos valores para calcular antes de enviar los datos ingresados ​​al servidor. En HTML, esto generalmente se logra a través de <form>elementos HTML que le enseñan al cliente sobre los parámetros disponibles para establecer, la ubicación de destino para enviar la solicitud, así como el formato de representación para aplicar al enviar los datos de entrada. Esto puede ser así:

<html>
  <head>
    ...
  </head>
  <body>
    <form action="/../someResource" method="post" enctype="application/x-www-form-urlencoded">
      <label for="firstNumber">First number:</label>
      <input type="number" id="firstNumber" name="firstNumber"/>

      <label for="secondNumber">Second number:</label>
      <input type="number" id="secondNumber" name="secondNumber"/>

      <input type="submit" value="Add numbers"/>
    </form>
  </body>
</html>

El ejemplo anterior indica que hay dos campos de entrada que puede completar el usuario o algún otro autómata, y que al invocar el elemento de entrada de envío, el navegador se encarga de formatear los datos de entrada en un application/x-www-form-urlencodedformato de representación que se envía a la ubicación de destino mencionada a través del método de solicitud HTTP especificado, POSTen este caso. Si ingresamos 1en el firstNumbercampo de entrada y 2en el secondNumbercampo de entrada, el navegador generará una representación firstNumber=1&secondNumber=2y la enviará como la carga útil del cuerpo de la solicitud real al recurso de destino.

La solicitud HTTP sin procesar emitida al servidor puede verse así:

POST /../someResource
Host: www.acme.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 28
Accept: application/html

firstNumber=1&secondNumber=2

El servidor puede realizar el cálculo y responder con una página HTML adicional que contiene el resultado del cálculo, ya que la solicitud indica que el cliente entiende este formato.

Como Breton ya señaló, no existe una URL o URI "RESTful". Un URI / URL es su propio tipo de cosas y no debe transmitir ningún significado a un cliente / usuario. En la muestra de la calculadora anterior, un usuario simplemente no está interesado a dónde enviarle los datos, solo le interesa que al activar el campo de entrada de envío se envíe la solicitud. El servidor ya debe proporcionar toda la información necesaria para realizar la tarea.

Es posible que un navegador tampoco se dé cuenta de que la solicitud realmente está alimentando una calculadora con algunos parámetros de entrada, también podría ser algún tipo de formulario de pedido que devuelve solo la siguiente representación de formulario para continuar el proceso de pedido o algún tipo totalmente diferente de recurso. Simplemente realiza lo que exige la especificación HTML en tal caso y no podría importarle menos lo que el servidor está haciendo realmente. Este concepto permite que un navegador utilice el mismo formato de representación para hacer todo tipo de cosas, como ordenar algunas cosas de su tienda en línea preferida, chatear con sus mejores amigos, iniciar sesión en una cuenta en línea, etc.

La potencialidad de ciertos elementos, como en el presente caso del campo de entrada que por lo general se representa como botón, define lo que debe para con ella. En el caso de un botón o un enlace, básicamente le dice que haga clic en él. Otros elementos pueden transmitir diferentes posibilidades. Dicha prestación también se puede expresar a través de relaciones de enlace, es decir, con preloadenlaces anotados que básicamente le dicen a un cliente que ya puede cargar el contenido del recurso vinculado en segundo plano, ya que el usuario probablemente tomará este contenido a continuación. Dichas relaciones de enlace deberían, por supuesto, estandarizarse o seguir el mecanismo de extensión para los tipos de relación definidos por el enlace web .

Estos son los conceptos fundamentales que se usan en la Web y que también deberían usarse en una arquitectura REST. Según el "Tío Bob" Robert C. Martin, una arquitectura trata sobre la intención y la intención detrás de la arquitectura REST es el desacoplamiento de los clientes de los servidores para permitir que los servidores evolucionen libremente en el futuro sin tener que temer que rompan clientes. Desafortunadamente, esto requiere mucha disciplina, ya que es muy fácil introducir el acoplamiento o agregar soluciones de solución rápida para hacer el trabajo y seguir adelante. Como Jim Webber señaló en una arquitectura REST, usted, como proveedor de servicios, debe intentar diseñar un protocolo de aplicación de dominio similar a un juego de computadora basado en texto de los años 70 que los clientes seguirán hasta que lleguen al final de un proceso.

Desafortunadamente, lo que muchas de las llamadas API "REST" hacen en realidad es todo menos eso. Verá el intercambio de datos basados ​​principalmente en JSON que se especifican en una documentación externa específica de API que generalmente es difícil de integrar dinámicamente sobre la marcha. El formato de cómo debe verse una solicitud también está codificado en la documentación externa, lo que lleva a una gran cantidad de URI de interpretación de implementación para devolver tipos predefinidosen lugar de usar algún formato de representación común que se negocie por adelantado. Esto evita que los servidores cambien, ya que los clientes ahora esperan recibir un cierto formato de datos (¡no un formato de representación!) Para URI predefinidos. Este intercambio de formato de datos personalizado además evita que los clientes interactúen con otras API, ya que el "formato de datos" suele ser una marea específica. Conocemos este concepto del pasado por las tecnologías RPC como Corba, RMI o SOAP, que condenamos como algo malvado, a pesar de que Peppol se mudó nuevamente al reemplazar AS2 con AS4 como protocolo de transferencia predeterminado recientemente.

En lo que respecta a la pregunta real formulada, el envío de datos como archivo csv no es diferente al uso de application/x-www-form-urlencodedrepresentación o cosas similares. Jim Webber dejó en claro que, después de todo, HTTP es solo un protocolo de transporte cuyo dominio de aplicación es la transferencia de documentos a través de la Web . El cliente y el servidor deben ser compatibles, text/csvcomo mínimo, según se define en RFC 7111 . Este archivo CSV podría generarse como consecuencia del procesamiento de un tipo de medio que define elementos de formulario, un elemento o atributo de destino para enviar la solicitud, así como el método HTTP para realizar la carga de la configuración.

Hay un par de tipos de medios que admiten formularios como HTML , HAL Forms , halform , ion o Hydra . Sin embargo, actualmente no conozco un tipo de medio que pueda codificar automáticamente los datos de entrada text/csvdirectamente, por lo tanto, es posible que sea necesario definirlo y registrarlo en el registro de tipos de medios de la IANA .

Supongo que la carga y descarga del conjunto completo de parámetros no debería ser un problema. Como se mencionó anteriormente, el URI de destino no es relevante ya que un cliente solo usará el URI para recuperar nuevo contenido para procesar. Filtrar por fecha comercial tampoco debería ser difícil. Aquí, sin embargo, el servidor debe ser el cliente con todas las posibilidades que el cliente simplemente puede elegir. En los últimos años, GraphQL y RestQL evolucionaron, lo que introduce un lenguaje similar a SQL que puede orientarse a un determinado punto final para obtener una respuesta filtrada. Sin embargo, en un verdadero sentido REST, esto viola la idea detrás de REST como a) GraphQL, es decir, solo usa un único punto final que de alguna manera evita el uso óptimo del almacenamiento en caché yb) requiere el conocimiento de los campos disponibles en sentido inverso, lo que puede conducir a la introducción de un acoplamiento de clientes al modelo de datos base del recurso.

La activación o desactivación de ciertos parámetros de configuración es simplemente una cuestión de activar los controles hipermedia que proporcionan esta capacidad. En los formularios HTML, esto podría ser una simple casilla de verificación o una selección de varias líneas en una lista o de ese tipo. Dependiendo de la forma y del método que defina, podría enviar toda la configuración PUTo ser inteligente sobre los cambios realizados y solo realizar una actualización parcial a través de PATCH. El último requiere básicamente un cálculo de la representación de cambio al actualizado y alimentar al servidor con los pasos necesarios para transformar la representación actual en la deseada. De acuerdo con la especificación PATH, esto debe hacerse dentro de una transacción para que se apliquen todos o ninguno de los pasos.

HTTP permite y alienta a un servidor a validar una solicitud recibida por adelantado antes de aplicar los cambios. Para PUT los estados de especificación:

Un servidor de origen DEBE verificar que la representación de PUT sea consistente con cualquier restricción que el servidor tenga para el recurso de destino que el PUT no pueda o no cambie. Esto es particularmente importante cuando el servidor de origen usa información de configuración interna relacionada con el URI para establecer los valores para los metadatos de representación en las respuestas GET. Cuando una representación PUT es inconsistente con el recurso de destino, el servidor de origen DEBE hacerlos consistentes, transformando la representación o cambiando la configuración del recurso, o responder con un mensaje de error apropiado que contenga información suficiente para explicar por qué la representación no es adecuada. Se sugieren los códigos de estado 409 (Conflicto) o 415 (Tipo de medio no admitido),

Por ejemplo, si el recurso de destino está configurado para tener siempre un Tipo de contenido de "texto / html" y la representación PUT tiene un Tipo de contenido de "imagen / jpeg", el servidor de origen debe hacer uno de:

a. reconfigurar el recurso objetivo para reflejar el nuevo tipo de medio;

si. transformar la representación PUT a un formato coherente con el del recurso antes de guardarlo como el nuevo estado del recurso; o,

C. rechazar la solicitud con una respuesta 415 (tipo de medio no admitido) que indica que el recurso de destino está limitado a "texto / html", tal vez incluyendo un enlace a un recurso diferente que sería un destino adecuado para la nueva representación.

HTTP no define exactamente cómo un método PUT afecta el estado de un servidor de origen más allá de lo que puede expresarse por la intención de la solicitud del agente de usuario y la semántica de la respuesta del servidor de origen. ...

Para resumir esta publicación, debe usar un tipo de medio existente que le permita enseñarle a un cliente sobre los parámetros de entrada requeridos o admitidos, la ubicación de destino para enviar la solicitud, la operación a usar y el tipo de medio la solicitud debe estar formateada o definir la suya propia que registre con IANA. Esto último puede ser necesario si desea convertir la entrada atext/csvy luego cargue la representación CSV en el servidor. La validación debe ocurrir antes de que los cambios se apliquen al recurso. El URI real no debe ser relevante para los clientes más que para determinar a dónde enviar la solicitud y, como tal, usted puede elegir libremente, el implementador del servicio. Si sigue estos pasos, tendrá la libertad de cambiar el lado del servidor en cualquier momento y, como consecuencia, los clientes no se romperán si admiten los tipos de medios utilizados.

Roman Vottner
fuente
0

Editar: De hecho, el URI habría evitado que las GETsolicitudes se mantuvieran idempotentes.


Sin embargo, para la validación, el uso de códigos de estado HTTP para notificar la validez de una solicitud (para crear un nuevo o modificar un "parámetro" existente) se ajustaría a un modelo Restful.

Informe con un 400 Bad Requestcódigo de estado si los datos enviados no son válidos y la solicitud debe modificarse antes de volver a enviarla ( códigos de estado HTTP / 1.1 ).

Sin embargo, esto se basa en la validación en el momento del envío, en lugar de diferirlo como en su caso de uso. Las otras respuestas tienen soluciones adecuadas para ese escenario.

Derek Mortimer
fuente
El URI está destinado a ser un identificador. El uso de una URL en particular no debería tener efectos secundarios. Imagina lo que haría un proxy con eso.
Breton
2
o google, para el caso. Una vez leí una historia sobre una tienda web que tenía todos sus productos eliminados por google debido a este tipo de idiotez.
Breton
0

En un entorno REST, cada URL es un recurso único. ¿Cuales son tus recursos? Una calculadora financiera realmente no tiene recursos obvios. Necesita profundizar en lo que está llamando parámetros y extraer los recursos. Por ejemplo, un calendario de amortización para un préstamo podría ser un recurso. La URL del calendario puede incluir la fecha de inicio, el plazo (en meses o años), el período (cuando el interés se capitaliza), la tasa de interés y el principio inicial. Con todos esos valores, tiene un calendario de pagos específico:

http://example.com/amort_cal/2009-10-20/30yrsfixed/monthly/5.00/200000

Ahora, no sé lo que está calculando, pero su concepto de una lista de parámetros no parece RESTful. Como alguien más dijo, sus requisitos anteriores suenan más XMLRPC. Si está intentando REST, necesita sustantivos. Los cálculos no son sustantivos, son verbos que actúan sobre sustantivos. Necesitas darle la vuelta para sacar los sustantivos de tus calcs.

jmucchiello
fuente
55
Creo que es un poco tonto usar barras inclinadas aquí, ¿qué estaría mal con amort_cal? Date = 2009-10-20 & type = 30yrsfixed & period = Monthly & rate = 5.0 & initiallamount = 200000? A REST no le importa mientras sea un recurso. Sin embargo, la especificación de URI importa. ¿Cómo imaginas enlaces relativos para trabajar con un esquema como este?
Breton
Sacas un buen punto, no obstante. ¿Estos "parámetros" incluso necesitan ser almacenados en el servidor? Si es solo un cálculo único, ¿por qué no hacer un espacio virtual, donde los parámetros están en la URL? Mientras no esté cambiando el estado interno, debería estar bien.
Breton
1
Y los "parámetros" no se aplican a un "recurso". Un recurso es una entidad única con un identificador único. Mi url identifica un único recurso. Una URL parametrizada indica una colección de recursos que selecciona entre el uso de los parámetros.
jmucchiello
2
REST no se basa en "Recursos CRUDING". Pegar todos sus parámetros de consulta en segmentos de ruta no crea automáticamente una interfaz RESTful porque ahora cree que puede llamar a cada permutación un recurso. Desafortunadamente, no hay un proceso mágico que pueda aplicar para identificar cuáles deberían ser los recursos en su sistema. Requiere un diseño cuidadoso, no una fórmula mecánica.
Darrel Miller el
2
Una vez más, la arquitectura REST NO IMPORTA lo que hay en la URL. La URL debe ser opaca . No importa descansar si usa barras diagonales, punto y coma o corazones unicode como separadores. Lee esto y responde a esto, no a lo que imaginas que estoy diciendo.
Breton