Por lo que puedo decir, cada recurso individual debe tener solo una ruta canónica . Entonces, en el siguiente ejemplo, ¿cuáles serían los buenos patrones de URL?
Tomemos como ejemplo un resto de representación de empresas. En este ejemplo hipotético, cada compañía posee 0 o más departamentos y cada departamento posee 0 o más empleados.
Un departamento no puede existir sin una empresa asociada.
Un empleado no puede existir sin un departamento asociado.
Ahora me parece que la representación natural de los patrones de recursos es.
/companies
Una colección de compañías - Acepta poner para una nueva compañía. Obtenga para toda la colección./companies/{companyId}
Una empresa individual. Acepta GET, PUT y DELETE/companies/{companyId}/departments
Acepta POST para un nuevo artículo. (Crea un departamento dentro de la empresa)./companies/{companyId}/departments/{departmentId}/
/companies/{companyId}/departments/{departmentId}/employees
/companies/{companyId}/departments/{departmentId}/employees/{empId}
Dadas las restricciones, en cada una de las secciones, siento que esto tiene sentido si está un poco anidado.
Sin embargo, mi dificultad viene si quiero enumerar ( GET
) a todos los empleados de todas las empresas.
El patrón de recursos para eso se correlacionaría más estrechamente con /employees
(La colección de todos los empleados)
¿Eso significa que debería haberlo hecho /employees/{empId}
también porque, de ser así, hay dos URI para obtener el mismo recurso?
O tal vez todo el esquema debería ser aplanado, pero eso significaría que los empleados son un objeto anidado de nivel superior.
En un nivel básico, /employees/?company={companyId}&department={deptId}
devuelve exactamente la misma vista de los empleados que el patrón más profundamente anidado.
¿Cuál es la mejor práctica para los patrones de URL donde los recursos son propiedad de otros recursos pero deberían poder consultarse por separado?
fuente
Respuestas:
Lo que has hecho es correcto. En general, puede haber muchos URI para el mismo recurso; no hay reglas que indiquen que no debe hacer eso.
Y, en general, es posible que deba acceder a los elementos directamente o como un subconjunto de otra cosa, por lo que su estructura tiene sentido para mí.
Solo porque los empleados son accesibles bajo el departamento:
company/{companyid}/department/{departmentid}/employees
No significa que no puedan ser accesibles bajo la compañía también:
company/{companyid}/employees
Lo que devolvería a los empleados de esa empresa. Depende de lo que necesite su cliente consumidor: para eso debe estar diseñando.
Pero espero que todos los manejadores de URL utilicen el mismo código de respaldo para satisfacer las solicitudes, de modo que no esté duplicando el código.
fuente
/company/3/department/2/employees/1
). Si la API proporciona formas de obtener cada recurso, entonces hacer cada una de esas solicitudes podría hacerse en una biblioteca del lado del cliente o como un punto final único que reutiliza el código./company/*
, solo debe devolver el recurso de la empresa y no cambiar el tipo de recurso en absoluto. Nada de esto está especificado por REST, generalmente es una especificación pobre, solo una preferencia personal.He probado ambas estrategias de diseño: puntos finales anidados y no anidados. He encontrado que:
Si el recurso anidado tiene una clave primaria y no tiene su clave primaria principal, la estructura anidada requiere que la obtenga, aunque el sistema no la requiera realmente.
Los puntos finales anidados generalmente requieren puntos finales redundantes. En otras palabras, la mayoría de las veces necesitará el punto final adicional / empleados para que pueda obtener una lista de empleados en todos los departamentos. Si tienes / empleados, ¿qué es exactamente lo que te compran / compañías / departamentos / empleados?
Los puntos finales de anidación no evolucionan tan bien. Por ejemplo, es posible que no necesite buscar empleados ahora, pero podría hacerlo más tarde y si tiene una estructura anidada, no tiene más remedio que agregar otro punto final. Con un diseño no anidado, simplemente agrega más parámetros, lo cual es más simple.
a veces un recurso puede tener múltiples tipos de padres. Resultando en múltiples puntos finales que devuelven el mismo recurso.
los puntos finales redundantes hacen que los documentos sean más difíciles de escribir y también hacen que la API sea más difícil de aprender.
En resumen, el diseño no anidado parece permitir un esquema de punto final más flexible y simple.
fuente
Moví lo que hice de la pregunta a una respuesta donde es probable que más personas lo vean.
Lo que he hecho es tener los puntos finales de creación en el punto final anidado. El punto final canónico para modificar o consultar un elemento no está en el recurso anidado .
Entonces, en este ejemplo (solo enumerando los puntos finales que cambian un recurso)
POST
/companies/
crea una nueva compañía devuelve un enlace a la compañía creada.POST
/companies/{companyId}/departments
cuando se crea un departamento, el nuevo departamento devuelve un enlace a/departments/{departmentId}
PUT
/departments/{departmentId}
modifica un departamentoPOST
/departments/{deparmentId}/employees
crea un nuevo empleado devuelve un enlace a/employees/{employeeId}
Por lo tanto, hay recursos de nivel raíz para cada una de las colecciones. Sin embargo, la creación está en el objeto propietario .
fuente
POST
significadoPUT
, y de otra maneraHe leído todas las respuestas anteriores, pero parece que no tienen una estrategia común. Encontré un buen artículo sobre las mejores prácticas en Design API de Microsoft Documents . Creo que deberías referirte.
.
fuente
El aspecto de sus URL no tiene nada que ver con REST. Todo vale. En realidad es un "detalle de implementación". Entonces, al igual que cómo nombras tus variables. Todo lo que tienen que ser es único y duradero.
No pierdas demasiado tiempo en esto, solo haz una elección y cúmplelo / sé constante. Por ejemplo, si vas con jerarquías, entonces lo haces para todos tus recursos. Si va con parámetros de consulta ... etc. al igual que las convenciones de nomenclatura en su código.
Porque ? Hasta donde yo sé, una API "RESTful" debe ser navegable (ya sabes ... "Hypermedia como el motor del estado de la aplicación"), por lo tanto, a un cliente API no le importa cómo son tus URL siempre que sean válido (no hay SEO, ningún humano que necesite leer esas "URL amigables", excepto que puede ser para depurar ...)
Lo bueno / comprensible que es una URL en una API REST solo es interesante para usted como desarrollador de API, no como cliente de API, como lo sería el nombre de una variable en su código.
Lo más importante es que su cliente API sepa cómo interpretar su tipo de medio. Por ejemplo, sabe que:
A continuación se muestra un ejemplo de intercambio HTTP (los cuerpos están en yaml ya que es más fácil de escribir):
Solicitud
Respuesta: una lista de enlaces al recurso principal (empresas, personas, lo que sea ...)
Solicitud: enlace a empresas (usando el cuerpo de la respuesta anterior. Links.companies)
Respuesta: una lista parcial de compañías (debajo de los ítems), el recurso contiene enlaces relacionados, como un enlace para obtener las próximas dos compañías (body.links.next) y otro enlace (con plantilla) para buscar (body.links.search)
Entonces, como ve si sigue los enlaces / relaciones, la forma en que estructura la parte de la ruta de sus URL no tiene ningún valor para su cliente API. Y si está comunicando la estructura de sus URL a su cliente como documentación, entonces no está haciendo REST (o al menos no Nivel 3 según el " modelo de madurez de Richardson ")
fuente
No estoy de acuerdo con este tipo de camino
Si desea obtener departamentos, creo que es mejor usar un recurso / departamentos
Supongo que tiene una
companies
tabla y unadepartments
tabla, luego clases para mapearlas en el lenguaje de programación que usa. También supongo que los departamentos podrían estar vinculados a otras entidades que no sean empresas, por lo que un recurso / departamentos es sencillo, es conveniente tener recursos asignados a tablas y tampoco necesita tantos puntos finales ya que puede reutilizarpara cualquier tipo de búsqueda, por ejemplo
Si desea crear un departamento, el
se debe utilizar el recurso y el cuerpo de la solicitud debe contener el ID de la empresa (si el departamento puede vincularse a una sola empresa)
fuente
GET /companies/{companyId}?include=departments
, ya que esto permite que tanto la empresa como sus departamentos se recuperen en una sola solicitud HTTP. Fractal hace esto realmente bien./departments
punto final para que solo sea accesible por un administrador, y que cada empresa acceda a sus propios departamentos solo a través de `/ companies / {companyId} / departamentos`Rails proporciona una solución a esto: anidamiento superficial .
Creo que esto es bueno porque cuando se trata directamente con un recurso conocido, no hay necesidad de usar rutas anidadas, como se ha discutido en otras respuestas aquí.
fuente