¿Está bien devolver HTML desde una API JSON?

25

En mi proyecto actual, soy responsable de la implementación de un servicio que implica el consumo de API RESTful recién creadas, documentadas como únicamente compatibles con JSON.

El cliente realiza constantemente solicitudes con el encabezado de aceptación de 'application / json' y el tipo de contenido de 'application / json'. Sin embargo, algunos puntos finales envían una respuesta con un tipo de contenido HTML, incluso un cuerpo HTML. Para mí, este es claramente el enfoque equivocado y nunca puede justificarse.

A lo largo del proyecto, esta misma práctica se ha aplicado en dos proveedores diferentes y dos servicios diferentes. Me encontré teniendo que justificar por qué los servicios necesitaban ser cambiados. Los proveedores declararon que el cliente debería hacer frente a esto e incluso mi biblioteca REST elegida ha sido cuestionada (RestEasy) porque no hace frente a esto de forma predeterminada 'fuera de la caja'.

Este ha sido un importante punto de frustración. No puedo encontrar muchas referencias para respaldar mi argumento, supongo que esto se debe a que el punto es discutible ya que es muy obvio.

La pregunta es, ¿me estoy perdiendo algo? ¿Estoy siendo pedante sobre esto? ¿Está bien tener una API JSON que no tenga un tipo de contenido de aplicación / json en este escenario? Se agradecerán las referencias. ¿Cómo se resuelve esta situación desde un punto de vista comercial?

phillip.darley
fuente
1
Por tipo de contexto, ¿quiere decir el encabezado HTTP de tipo de contenido?
Marjan Venema
Sí, me refiero al encabezado de tipo de contenido HTTP. Editado
phillip.darley
Bueno, al menos no deben llamarlo una "API REST JSON" cuando se trata de una API REST HTML.
Bergi

Respuestas:

28

Cuando envía un acceptencabezado solicitando un tipo de medio específico, el servidor no debe enviar otra cosa, y ciertamente no con un código de estado 200 OK

De Restpatterns.org :

Si no hay un campo de encabezado Aceptar, se supone que el cliente acepta todos los tipos de medios. Si hay un campo de encabezado Aceptar y el servidor no puede enviar una respuesta que sea aceptable de acuerdo con el valor combinado del campo Aceptar, entonces el servidor DEBE enviar una respuesta 406 (no aceptable).

(El énfasis es mío)

Restpatterns.org toma esto del estándar HTTP real: definiciones de campo de encabezado - Aceptar

En resumen: no estás siendo pedante. Los servicios no siguen el estándar HTTP si están devolviendo HTML cuando el encabezado de aceptación específicamente les dice que regresen application/jsony nada más.

Marjan Venema
fuente
1
+1. Estoy de acuerdo con esta respuesta, pero lamentablemente la palabra shouldse usa repetidamente en las especificaciones HTTP. Tenemos que comenzar una petición en línea para cambiar esas palabras must.
Reactgular
3
@MarjanVenema "debería" es correcto porque en la sección 10 del mismo rfc hay una nota: "Los servidores HTTP / 1.1 pueden devolver respuestas que no son aceptables de acuerdo con los encabezados de aceptación enviados en la solicitud. En algunos casos, esto puede incluso ser preferible a enviar una respuesta 406 ".
imel96
1
Si un cliente solicita un recurso que realmente no tiene una representación JSON, no importa cuánto quieran JSON, quizás sea mejor que reciban algo más que sea definitivo; no se garantiza que obtenga un 406. Lo importante es que el servidor debe describir cuál es realmente el tipo de contenido de la respuesta.
Donal Fellows
66
@DonalFellows: No, estarían mejor informados de lo que realmente es el caso. El servidor no solo debe devolver cualquier cosa que considere adecuada, sino enviar una respuesta 406 No aceptable como se indica en la norma. Tenga en cuenta que cuando el cliente solicita específicamente un tipo de medio y no especifica ningún retroceso, probablemente no tenga forma de procesar ningún otro tipo de medio.
Marjan Venema
2
@ imel96: el hecho de que Internet nunca haya sido estricto es exactamente lo que ha llevado a las dificultades para tratar de admitir varios navegadores y a que los servidores ahora se vean obligados a seguir siendo compatibles con versiones anteriores no válidas, ya que simplemente hay demasiado de eso por ahí (y lamentablemente todavía se está creando).
Marjan Venema
9

¿Qué quiere decir con "RESTful JSON API"? Creo que el primer problema aquí es que está mezclando conceptos (o posiblemente alguien entre usted y sus contrapartes técnicas en sus "proveedores").

Una API RESTful (ya sea que esté hablando, no descanse realmente en el nivel 1 o algo en el nivel 3 o superior cf http://martinfowler.com/articles/richardsonMaturityModel.html ) trata sobre la forma en que interactúa con la API, no sobre El formato del contenido enviado o recibido de. Ni siquiera se trata de protocolos o mecanismos de transporte ...

Del mismo modo, una API JSON es una API que admite el uso de JSON como formato de datos: puede o no ser tranquila, puede o no implementarse usando HTTP y (y este es el punto clave) puede o no admitir JSON exclusivamente.

Un buen API que se ejecute a través de HTTP (es razonable suponer que en el contexto que está hablando de una API expuesta a través de HTTP) debería permitirle solicitar contenido en una variedad de formatos y esos formatos pueden (y posiblemente deberían) incluir tanto HTML como JSON y XML. ¿Por qué? Bueno, facilitaría mucho el aprendizaje de la API, conceptualmente proporciona un UX basado en navegador instantáneo para cualquier propósito, etc.

La pregunta interesante es si mi API, que admite una variedad de formatos de contenido, se llama sin que se le diga qué formato espera el cliente, ¿qué formato debería devolver ...? Esto tiende a un argumento religioso, pero HTML le da al proveedor la opción de incluir información útil (como "recuerde configurar el encabezado de aceptación de contenido").

Para responder a la pregunta una API, una que sea tranquila y que admita json debería poder devolver HTML si ese es el contenido solicitado.

Murph
fuente
1
Tomo ambos puntos y he editado mi pregunta en consecuencia. El hecho de que el servicio sea RESTful no es relevante y he detallado que el cliente acepta 'application / json' en cada solicitud.
phillip.darley
Yo diría que "RESTful JSON API" tiene un significado muy obvio.
gnasher729
1
Diría que mis maestros se esforzaron mucho para asegurarse de que entendiéramos por qué "nunca asumir" fue una parte clave de ser un buen programador
Murph
5

El cliente realiza constantemente solicitudes con el encabezado de aceptación de 'application / json' y el tipo de contenido de 'application / json'

Sí, esto es lo correcto, pero no significa que al proveedor le importe. Si bien entiendo totalmente su frustración, porque también creo que un servicio JSON siempre debe dar una respuesta JSON, pero hay muchos ejemplos en los que ese no es el caso.

A lo largo del proyecto, esta misma práctica se ha aplicado en dos proveedores diferentes y dos servicios diferentes. Me encontré teniendo que justificar por qué los servicios necesitaban ser cambiados. Los proveedores declararon que el cliente debería hacer frente a esto e incluso mi biblioteca REST elegida ha sido cuestionada (RestEasy) porque no hace frente a esto de forma predeterminada 'fuera de la caja'.

Bueno, tengo que estar de acuerdo con el vendedor. Es su servicio y siempre y cuando documenten claramente los casos especiales para usarlo, no se puede imponer que lo cambien. Es una desventaja para ellos, ya que los desarrolladores tardarán en adoptar su API, y si escucharan lo que los desarrolladores necesitan, lo cambiarían, pero lamentablemente no hay una regla que deba seguir los estándares.

La pregunta es ¿me estoy perdiendo algo?

Los encabezados de solicitud no significan nada a menos que se interrumpan correctamente en el otro extremo. Sé que si desarrollo una API web con PHP, al diablo con los encabezados de solicitud. Puedo responder con lo que quiera. Mientras que un servicio configurado en IIS con C # ofrece un manejo mucho más fácil de los encabezados de solicitud, su tipo y el tipo de respuesta. Tiene mucho que ver con las herramientas que el proveedor usó para construir la API.

¿Estoy siendo pedante sobre esto?

Sí y no. Tengo amigos desarrolladores que no podrían superar esto. Estarían tan obsesionados con el problema y no podrían continuar con otras tareas hasta que la API funcione de la manera que esperan que funcione. Ahora eso es ser pedante.

Es un problema porque el proveedor ha creado "más trabajo" para completar sus tareas. Cualquiera se sentiría frustrado por eso. Sé que lo estaría.

¿Está bien tener una API JSON que no tenga un tipo de contenido de aplicación / json en este escenario?

Absolutamente, pero no es una buena práctica.

Un cliente solo puede decirle al servidor cuál es el tipo de contexto de a request. No tiene la capacidad de imponer un tipo de contenido para el response. El cliente solo puede informar al servidor que hará acceptuna colección de posibles tipos de contenido.

Definiciones de campo de encabezado

El campo Aceptar encabezado de solicitud se puede usar para especificar ciertos tipos de medios que son aceptables para la respuesta. Los encabezados de aceptación se pueden usar para indicar que la solicitud está específicamente limitada a un pequeño conjunto de tipos deseados, como en el caso de una solicitud de una imagen en línea.

Es posible que un cliente solicite una imagen de image/jpeg, pero el servidor responde con text/htmly un código de estado de 404si la imagen no se encontró. Los servidores también pueden responder incorrectamente. Hay muchos sitios web de Wordpress que responden con un text/htmlcódigo de estado 200para archivos que no se encuentran páginas.

Ahora, eso es una práctica MALA por parte del servidor. Lo que intento decirte es que es absolutamente posible, y sucede a menudo. Las personas no saben lo que hacen cuando configuran estas cosas.

Se agradecerán las referencias. ¿Cómo se resuelve esta situación desde un punto de vista comercial?

Me he encontrado con este problema en algunos proyectos. Usted postenvía datos JSON al servidor y le devuelve una respuesta JSON o HTML.

Realmente no es un gran problema saber qué tipo estaba en la respuesta. Si el primer carácter es {o [puede asumir JSON. Si es así, <puede asumir HTML. Así lo he manejado en el pasado. A veces, el programador que escribió la API sabe todo sobre los encabezados HTTP. Todo vuelve como text/htmlrespuestas. Si tiene suerte, tienen Apache configurado por defecto, lo text/plainque a veces puede ayudar.

Estos problemas existen y continuarán existiendo en el futuro. La comunicación de servidor a servidor es, con mucho, una actividad no regulada. No existe un organismo rector que expulse a un proveedor de un sindicato por un servidor que dé malas respuestas HTTP.

Reactgular
fuente
Esto está en línea con la respuesta de @Marjan Venema, pero otro punto clave que plantea es la documentación de este comportamiento. Para agregar a mi frustración, el vendedor no ha documentado este comportamiento. El tipo de contenido varía según el estado de la sesión, aunque solo se documenta la respuesta JSON.
phillip.darley