La mejor práctica para la llamada REST API con muchos parámetros


11

Tengo una API REST con operaciones GET que reciben una lista (larga) de parámetros (8 parámetros, por ejemplo). El objetivo de esta operación es buscar y filtrar elementos.

¿Cuál es la mejor práctica para administrar este escenario ?:

(1) ¿ Recibir una lista de parámetros ?:

public ResultType Get(int p1, int p2, string p3...) { ... }

(2) ¿O recibir un objeto que encapsula estos parámetros ?

public class MyClass
{
    public int X { get; set; }
    public int Y { get; set; }
    public string Z { get; set; }
}

public ResultType Get(MyClass parameter) { ... }

Piense en un escenario de comercio electrónico en el que desea buscar y filtrar "productos" por nombre, descripción, categoría, marca, modelo, precio, etc.


1
La posición es un identificador menor que un nombre propio para un valor.
SD

¿Por qué tienes 8 parámetros? ¿Qué hacen? ¿Hay alguna lógica de decisión involucrada (y es un desastre)? ¿Puedes dividir esa API / método en varios métodos que toman 3 o 4 parámetros?
Filip Milovanović

1
8 parámetros es solo un ejemplo. Mi operación Get es un método de "búsqueda". Piense en un escenario de comercio electrónico en el que desea buscar y filtrar "productos" por nombre, descripción, categoría, marca, modelo, precio, etc. He editado la pregunta para agregar contexto
Jose Alonso Monge

Respuestas:


10

Tengo una API REST con operaciones GET que reciben una lista (larga) de> parámetros. ¿Cuál es la mejor práctica para administrar este escenario?

AFAIK, no hay una mejor práctica firmemente establecida (lo siento). Sin embargo, uno puede hacer algunas recomendaciones:

  • Intente evitar usarPOST (en lugar de GET) si la solicitud es segura (es decir, sin efectos secundarios, en particular sin modificar los datos). Si los parámetros son muy grandes, es posible que tenga que usar POSTpara evitar las limitaciones de longitud, pero generalmente esto no es un problema (la mayoría del software admite URL bastante largas), y se deben usar solicitudes seguras GETpara permitir optimizaciones como el almacenamiento en caché y la captación previa.

  • Si lo usa GET, debe enviar sus parámetros como parámetros de URL 1) . En esa situación, la solución natural y común es usar una lista de parámetros , así que eso es lo que recomendaría. Sí, la lista será larga, pero la API REST (probablemente) está destinada para uso programático, por lo que no veo un problema con esto. Los usuarios de la API son libres de encapsular los parámetros en un objeto dentro de su propio código.

  • Técnicamente, también podría poner un objeto en un parámetro de URL (como JSON, XML o lo que sea), pero eso es inusual, por lo que lo evitaría si es posible.

1) Hablando estrictamente, puede usar un cuerpo con una GETsolicitud, pero esto es inusual y generalmente no se recomienda; ver, por ejemplo, HTTP GET con cuerpo de solicitud .


Finalmente, al igual que con los métodos en el código fuente que tienen largas listas de parámetros, es posible que desee considerar si la API REST necesita una refactorización. Al igual que en el código fuente, una lista de parámetros tan larga indica que el punto final de la API está haciendo muchas cosas diferentes. ¿Tiene sentido dividirlo o proporcionar configuraciones predeterminadas? Pero esa es una pregunta diferente ...


Técnicamente también puedes enviar un cuerpo con un GET aunque inusual
Ewan

Además, ¿estás seguro de que te refieres a idempotente? Yo diría que GetTodaysDayName () "almacenable en caché" podría considerarse idempotente, pero no querrás almacenarlo en caché
Ewan,

¡Que comience la batalla GET vs POST! :)
Ewan

@Ewan: en cuanto al almacenamiento en caché de GetTodaysDayName: suponiendo que necesita el nombre de hoy diez veces por segundo, y no le importa usar el día equivocado durante unos segundos, lo más probable es que desee almacenarlo en caché. Aún así, usé erróneamente "idempotente", lo que tenía en mente era "seguro" (= no modificar). Editado
sleske

1
@Ewan batallas constructivas en las que los "oponentes" enriquecen la respuesta de los demás son más que bienvenidos. ¡Gracias a los dos por una visión muy completa de todas las opciones!
Christophe

3

La mejor práctica es POSTAR los parámetros como un objeto.

Esto evita el límite de longitud de URL y otros problemas con las cadenas de consulta. Si envía varios parámetros en JSON, entonces un objeto es la forma estándar de hacerlo, por lo que tiene sentido deserializarlo.

Puede evitar crear objetos aleatorios de 'Solicitud' que solo se usan en sus Controladores deserializando a un objeto dinámico si lo desea; aunque luego elegir los tipos correctos puede ser igualmente complicado.

En los viejos tiempos, podría haber tenido múltiples parámetros en la acción de su controlador automáticamente vinculados a los campos de un objeto JSON entrante. Pero esto ya no funciona fuera de la caja en .net core.

Aunque existe esto, que podría estar tentado a probar

https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/application-model?view=aspnetcore-2.1#application-model-usage-in-webapicompatshim

Editar: solo voy a agregar algunos puntos sobre el uso de GET

  • Almacenamiento en caché: GET será almacenado en caché por clientes que obedecen la especificación HTTP. Pero la especificación está diseñada para hacer que las páginas web se carguen más rápido. El almacenamiento en caché es útil si el resultado de su API tiene los mismos requisitos de caché que una página web, pero no es útil si no lo tiene. Puede agregar su propio almacenamiento en caché de respuestas POST en el cliente si es necesario.

  • Longitud de la URL: esto es principalmente un problema cuando envía una matriz. Obviamente, una matriz puede alargarse fácilmente y los nombres de los parámetros de la cadena de consulta se repetirán para cada elemento. Sin embargo, incluso si solo está enviando una cadena, técnicamente esa cadena puede ser muy muy larga.

  • Registro: Por defecto, muchos servidores web registrarán la cadena de consulta completa. A menudo no desea que los datos de parámetros terminen en registros de texto sin formato.

  • OBTENER con cuerpo: esta parece ser la respuesta perfecta, satisfaciendo a los puristas de REST al tiempo que permite una buena estructura de datos, pero es inusual y mal visto, un POST es la forma estándar de enviar un cuerpo.


2
No creo que esto esté de acuerdo, como buena práctica. En particular, si la solicitud es idempotente, es una mejor práctica usarla GETy no PUT(para la capacidad de almacenamiento en caché, entre otras cosas). Y los límites de longitud de URL son bastante grandes hoy en día, por lo que no necesariamente es un problema.
sleske

@sleske Si cree que GET es mejor, debe escribir una respuesta sobre por qué. Sin embargo
Ewan

en realidad solo busca en Google y la longitud máxima de la cadena json parece incierta
Ewan

Dado el contexto, no es necesario que los parámetros de solicitud no estén en sus registros, a menos que no desee realizar análisis sobre lo que la gente buscaba en su página;) GETtiene sentido desde dos perspectivas: a) análisis yb) a el usuario podría almacenar la consulta para más tarde o compartir la consulta.
Thomas Junk

@ThomasJunk ¿a qué contexto te refieres? la cadena se llama 'z', podría haber literalmente cualquier cosa en ella. ¿Cuál es la multa GDPR de $ 20 millones?
Ewan
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.