REST: compensaciones entre la negociación de contenido a través de aceptar encabezado versus extensiones

40

Estoy trabajando en el diseño de una API RESTful. Sabemos que queremos devolver JSON y XML para cualquier recurso dado. Había estado pensando que haríamos algo como esto:

GET /api/something?param1=value1
Accept:  application/xml (or application/json)

Sin embargo, alguien rechazó el uso de extensiones para esto, así:

GET /api/something.xml?parm1=value1 (or /api/something.json?param1=value1)

¿Cuáles son las compensaciones con estos enfoques? ¿Es mejor confiar en el encabezado aceptar cuando no se especifica una extensión, pero honrar las extensiones cuando se especifica? ¿Hay algún inconveniente en ese enfoque?

Brandon Linton
fuente
¿Qué servidor web estás usando? ¿Y cómo analiza las URL?
Dipan Mehta
1
No tengo idea sobre el lado técnico (servidor) de las cosas. Dicho esto, prefiero su enfoque, ya que utiliza el estándar http, lo que hace que sea más fácil de entender (por ejemplo, cuando se supone que alguien más debe realizar algún mantenimiento en el futuro). Puede confiar en la extensión cuando la aceptación no está especificada o tiene un valor inesperado, pero siempre iría primero con la forma estándar.
Treb
@Dipan Estoy pirateando esto con la API web MVC4 (todavía en beta). Utiliza las abstracciones de enrutamiento de ASP.NET, que son bastante buenas.
Brandon Linton
1
@Treb Sí, soy mucho más fanático de usar el valor de encabezado de aceptación. Me pregunto si hay algún inconveniente en apoyar a ambos.
Brandon Linton

Respuestas:

38

Esto, "Sin embargo, filosóficamente, el primer enfoque es el único enfoque", y este "El enfoque RESTful oficial adecuado es usar Aceptar: encabezado". son ampliamente percibidos como el caso, pero también son absolutamente incorrectos .

Aquí hay un breve fragmento de Roy Fielding (quien definió REST) ​​...

"la sección 6.2.1 no dice que la negociación de contenido debe usarse todo el tiempo". citar

Esa conversación particular está en el contexto del encabezado 'Accept-Language:', pero lo mismo se aplica igualmente al encabezado 'Accept:', como se aclara más adelante en su respuesta ...

"No tengo idea de por qué la gente no puede ver el segundo y tercer enlace en la página superior

http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm

ese punto a las dos ediciones en PDF ".

Lo que quiere decir es que no hay problema al usar diferentes puntos finales para diferentes representaciones de los mismos datos de origen. (En este caso, un punto final .html y dos puntos finales .pdf diferentes).

También en una discusión similar, esta vez con respecto a las virtudes del uso de parámetros de consulta versus el uso de extensiones de archivo para diferentes tipos de medios ...

"Es por eso que siempre prefiero las extensiones. Ninguna opción tiene nada que ver con REST". citar

Una vez más, eso es ligeramente diferente a Aceptar frente a extensiones de nombre de archivo, pero la posición de Fielding aún es clara.

Respuesta: realmente no importa mucho. Las compensaciones entre los dos no son muy significativas y ambos son estilos aceptables.

Tom Christie
fuente
3
Gran respuesta equilibrada. Creo que agregaría que a veces es 'obvio' del URI que se pretende cierto contenido. por ejemplo, extensión .html o extensión .pdf en el URI. Y en este caso, realmente no hay necesidad de apoyar la negociación de contenido, y tener contenido implícito en el URI hace que sea más fácil para los humanos compartir el URI y usarlo para vincular cosas de una manera que puedan consumir de inmediato. En otros casos, como si desea evitar extensiones en sus URI y / o si desea exponer una API web que admita múltiples tipos de contenido json / XML por igual, un encabezado de aceptación puede encajar mejor.
Tim Lovell-Smith
Respuesta actualizada para contener nuevos enlaces. Creo que los grupos de Yahoo cambiaron su estructura.
Phil Sturgeon
Estoy en desacuerdo. El lenguaje de descripción de recursos que devuelve el servidor debe ser irrelevante para la lógica empresarial realizada por el punto final del servicio. Tener múltiples URI para el mismo punto final de servicio, solo para acomodar diferentes lenguajes de descripción de recursos, parece un malentendido de cómo deben construirse los URI REST.
Dejay Clayton
10

El enfoque RESTful oficial adecuado es usar el Accept:encabezado.

Sin embargo, debe tener cuidado de no romper la capacidad de almacenamiento en caché, que es uno de los requisitos de REST. Necesita tener Vary: Acceptencabezado y caché que lo entienda. En el mundo ideal lo tendrías, pero en la vida real tu millaje puede variar. Entonces, la segunda solución no es tan limpia, pero podría ser más práctica.

Además, tenga en cuenta que algunos navegadores muy antiguos solían ignorar los encabezados, confiando en su lugar en la extensión.

vartec
fuente
1
De hecho inexacto. Ver respuesta aceptada.
Phil Sturgeon
9

Técnicamente, en realidad no importa: su servidor web podrá pasar el proceso adecuadamente como parece. (Asumo esto pero no parece un showtopper).

Sin embargo, filosóficamente: el primer enfoque es el único enfoque. En REST, la URL en realidad solo apunta a un URI, que es solo un recurso. Piense por un momento en este recurso igual que el objeto en la programación orientada a objetos. Usted habla con este recurso a través de solo 4 métodos (también conocido como GET / POST / PUT / DELETE, o si algo lo permite el transporte), pero ese método no se convierte en la descripción del objeto. Del mismo modo, los aspectos del valor de retorno no son el URI. El objeto sigue siendo algo y no algo.xml o algo.json

Suponga que si no desea usar el encabezado Aceptar, pero si todavía quiere estar verdaderamente DESCANSO filosóficamente, no me importaría algo como:

GET /api/something?parm1=value1&return_type=xml

Opuesto a

GET /api/something.xml?parm1=value1 (or /api/something.json?param1=value1)

Pero como dije, esta diferencia es solo filosófica.

Dipan Mehta
fuente
+1 Dipan, tienes razón, excepto por una cosa: / api / something? Return_type = xml todavía no es tranquilo . La razón por la que no es RESTful es que las URL son opacas. IOW, desde el punto de vista del protocolo, no hay diferencia entre / api / something / xml y / api / something? Xml. Ver w3.org/DesignIssues/Axioms.html .
Mark E. Haase
0

@vartec: creo que te equivocas

El principio RESTful oficial apropiado dice que nada debe estar oculto en los encabezados HTTP, ya que es el URI el que está expuesto o referenciado, cualquier detalle sobre la solicitud / respuesta debe proporcionarse como parte del URI

Por lo tanto, recomiendo evitar usar el encabezado para obtener detalles sobre la solicitud y la respuesta, y seguir con

 GET /api/something.xml?parm1=value1 (or /api/something.json?param1=value1)

No puedo encontrar las referencias rápidamente, pero las volveré a publicar (en realidad, puede consultar el libro de publicación de O'reilly "Servicios web RESTful" ( http://shop.oreilly.com/product/9780596529260.do ) que confirma lo mismo

Basav
fuente
17
-1 completamente equivocado. Por un lado, la URL se envía en los encabezados HTTP. Además, cada URL distinta debe representar un recurso distinto. Las codificaciones XML y JSON del mismo contenido claramente no son 2 recursos diferentes; son 2 representaciones diferentes del mismo recurso.
Mark E. Haase
Los encabezados HTTP son un lugar legítimo y recomendado para almacenar "metadatos de mensajes", como: credenciales de seguridad, identificador de correlación, ID de sesión, contexto transaccional, formatos de datos. Este tipo de información no debe saturar sus URL o la carga de su mensaje.
Paulo Merson