¿Cómo crear URL REST sin verbos?

Estoy luchando para determinar cómo diseñar URL tranquilas. Estoy a favor del enfoque reparador de usar URL con sustantivos y no verbos que no entienden cómo hacerlo.

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

  1. Cargar nuevos parámetros
  2. Obtenga los últimos parámetros
  3. Obtener parámetros para una fecha de negocios dada
  4. Haz un conjunto de parámetros activos
  5. Validar un conjunto de parámetros

Entiendo que el enfoque tranquilo sería tener los siguientes tipos de URL:

/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 posterior
  2. GET de la primera URL
  3. GET de segunda URL

¿Pero cómo se hace el caso de uso 4to y 5to sin un verbo? No necesitarías URLs como:

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

??

Quizás algo como:

 PUT /parameters/activation HTTP/1.1 Content-Type: application/json; encoding=UTF-8 Content-Length: 18 { "active": true } 

Principios generales para un buen diseño de URI:

  • No use parámetros de consulta para alterar el estado
  • No use caminos mixtos si puede evitarlo; minúsculas es lo mejor
  • No use extensiones específicas de la implementación en sus URI (.php, .py, .pl, etc.)
  • No caigas en RPC con tus URI
  • Limite su espacio de URI tanto como sea posible
  • Mantenga cortos los segmentos del camino
  • Prefiere /resource o /resource/ ; crear 301 redirecciones de la que no usas
  • Utilice parámetros de consulta para la selección de un recurso; es decir, paginación, consultas de búsqueda
  • Mueva cosas del URI que deberían estar en un encabezado HTTP o en un cuerpo

(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:

  • Nunca use GET para alterar el estado; esta es una excelente manera de hacer que Googlebot arruine tu día
  • No use PUT a menos que esté actualizando un recurso completo
  • No use PUT a menos que también pueda hacer un GET legítimamente 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
  • Utiliza GET tanto como sea posible
  • Use POST con preferencia a PUT cuando tenga dudas
  • Use POST cada vez que tenga que hacer algo que se sienta como RPC
  • Use PUT para clases de recursos que son más grandes o jerárquicos
  • Utilice DELETE con preferencia a POST para eliminar recursos
  • Use GET para cosas como cálculos, a menos que su entrada sea grande, en cuyo caso use POST

Principios generales del diseño del servicio web con HTTP:

  • No meta metadatos en el cuerpo de una respuesta que debe estar en un encabezado
  • No coloque los metadatos en un recurso separado a menos que al incluirlo se genere una sobrecarga significativa
  • Use el código de estado apropiado
    • 201 Created despué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 Request cuando alguien realiza una operación con datos que son claramente falsos; para su aplicación esto podría ser un error de validación; en general, reserve 500 para excepciones no detectadas
    • 401 Unauthorized cuando alguien accede a su API sin proporcionar un encabezado de Authorization necesario o cuando las credenciales dentro de la Authorization no son válidas; no use este código de respuesta si no espera credenciales a través de un encabezado de Authorization .
    • 403 Forbidden cuando alguien accede a su API de una manera que puede ser maliciosa o no está autorizada
    • 405 Method Not Allowed cuando alguien usa POST cuando debería haber usado PUT, etc.
    • 413 Request Entity Too Large cuando alguien intenta enviarle un archivo inaceptablemente grande
    • 418 I'm a teapot cuando bash preparar café con una tetera
  • Usa los encabezados de almacenamiento en caché siempre que puedas
    • ETag encabezados ETag son buenos cuando puede reducir fácilmente un recurso a un valor hash
    • Last-Modified debe indicarle que mantener una fecha y hora de cuándo se actualizan los recursos es una buena idea
    • Cache-Control y Expires deberían recibir valores razonables
  • Haga todo lo posible para respetar los encabezados de almacenamiento en caché en una solicitud ( If-None-Modified , If-Modified-Since )
  • Use redireccionamientos cuando tengan sentido, pero estos deberían ser raros para un servicio web

Con respecto a su pregunta específica, POST debe usarse para # 4 y # 5. Estas operaciones se encuentran bajo la directriz “RPC-like” arriba. Para # 5, recuerde que POST no necesariamente tiene que usar Content-Type: application/x-www-form-urlencoded . Esto podría ser fácilmente una carga útil JSON o CSV.

Cuando parezca que necesitas un verbo nuevo, piensa convertir ese verbo en un sustantivo en su lugar. Por ejemplo, active “activar” en “activación” y “validar” en “validación”.

Pero por lo que has escrito, diría que tu aplicación tiene problemas mucho más grandes.

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 cantidad de cosas diferentes, cada una de las cuales debe tener un recurso separado dedicado a ella.

Otra forma de abordar esto: cuando discutes tu aplicación con los usuarios finales (aquellos que supuestamente saben poco sobre progtwigció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 todavía no has tenido esta conversión con usuarios potenciales, detén todo ahora mismo y no escribas otra línea de código hasta que lo hagas. Solo entonces su equipo tendrá una idea de lo que se debe construir.

No sé nada sobre el software financiero, pero si tuviera que adivinar, diría que algunos de los recursos podrían ir por nombres como “Informe”, “Pago”, “Transferencia” y “Moneda”.

Hay una serie de buenos libros sobre esta parte del proceso de diseño del software. Dos de los que puedo recomendar son Diseño de dominio y patrones de análisis .

El diseño de sus URL no tiene nada que ver con si su aplicación es RESTful o no. la frase “RESTful URLS” no tiene sentido.

Creo que deberías leer un poco más sobre lo que REST en realidad es. REST trata las URL como opacas y, como tales, no sabe qué contienen, si hay verbos o sustantivos o lo que sea. Es posible que aún desee diseñar sus URL, pero se trata de UI, 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 se toma en serio el REST, tendrá que replantearse cómo funciona su aplicación desde cero. O eso, o abandona REST y simplemente haz tu aplicación como una aplicación RPC.

Hmmmm tal vez no.

La idea aquí es que tienes que tratar todo como un recurso, así que una vez que un conjunto de parámetros tiene una URL a la que puedes referirte, simplemente agrega

obtener [parametersurl] / validationresults

publicar [patwigtersurl]

cuerpo: {comando: “activar”}

pero nuevamente, esa cosa activa es RPC, no REST.

Los requisitos de activar y validar son situaciones en las que intenta cambiar el estado de un recurso. No es diferente que hacer una orden “completada” o alguna otra solicitud “enviada”. Existen numerosas maneras de modelar estos tipos de cambios de estado, pero una que encuentro que a menudo funciona es crear recursos de recolección para recursos del mismo estado y luego mover el recurso entre las colecciones para afectar el estado.

Por ejemplo, crea algunos recursos como,

 /ActiveParameters /ValidatedParameters 

Si desea activar un conjunto de parámetros, agregue ese conjunto a la colección ActiveParameters. Podría pasar el conjunto de parámetros como un cuerpo de entidad, o podría pasar una url como parámetro de consulta, de la siguiente manera:

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

Lo mismo se puede hacer con / 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.

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

Haga los parámetros activos y / o valídelos:

 > PUT /parameters//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 < 

Verifique si los parámetros están activos y son válidos:

 > GET /parameters//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': '...'} < } < 

En un entorno REST, cada URL es un recurso único. ¿Cuáles son tus recursos? Una calculadora financiera realmente no tiene ningún recurso obvio. 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 para el calendario puede incluir start_date, term (en meses o años), period (período de tiempo (cuando el interés está compuesto), tasa de interés y principio inicial. Con todos esos valores tiene un calendario específico de pagos:

 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 suena RESTful. Como dijo otra persona, sus requisitos anteriores suenan más XMLRPC. Si estás intentando REST necesitas nombres. Los cálculos no son sustantivos, son verbos que actúan sobre sustantivos. Necesitas darle la vuelta para sacar los nombres de tus calcos.

Editar: De hecho, el URI habría impedido que las solicitudes GET permanezcan 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.

Reporte con un código de estado de 400 Bad Request si los datos enviados son / son inválidos y la solicitud debe ser alterada antes de ser reenviada ( HTTP / 1.1 Status Codes ).

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.