2009-09-22 16 views
6

Mis colegas y yo estamos implementando una serie de servicios HTTP RESTful, y estamos tratando de asegurarnos de que estamos a) siguiendo las especificaciones, yb) haciendo lo correcto " donde la especificación es corto de detalles.Opiniones necesarias sobre la atomicidad de un RESTful PUT

Aquí es una situación particular que hemos llegado a y está buscando opiniones de la comunidad sobre: ​​

Suponga que tiene un recurso/personas/Bob, y su cliente va a actualizar con un PUT. El servidor puede generar representaciones para/People/Bob en application/json y text/html. El servidor puede interpretar representaciones para/People/Bob en application/json.

Teniendo en cuenta esta solicitud:

 
PUT /People/Bob 
Content-Type: application/json 
Accept: application/xml 

{ name: "Still Bob" } 

el servidor no puede producir una representación XML, pero puede procesar el JSON entrante. Entonces sabemos que la respuesta correcta es que el servidor devuelva el estado 406.

La pregunta es: ¿debería el servidor haber realizado la actualización a/People/Bob?

+1

Esta respuesta a una pregunta previa de StackOverflow podría ser útil: http://stackoverflow.com/questions/982351/alternative-bodies-for-http-put/984436#984436 –

+0

Gracias, Matt. Creo que ese hilo aclara un punto de confusión que algunos tienen sobre Content-Type versus Accept (y 406 contra 415). Lo que estoy preguntando aquí es la atomicidad de manejar una solicitud ya que la especificación parece un poco corta aquí. – user30921

Respuesta

2

+1 para Filosofía del RESTO.

Sin un conocimiento detallado de la especificación HTTP, simplemente elegiría una de las opciones y documentaría el dilema y la elección.

Mi preferencia sería que el servidor no puede responder según lo solicitado, entonces no debe procesar ninguna solicitud.

Pero eso puede no funcionar en algunos escenarios, por lo que es posible que deba hacer lo contrario.

+0

Hehe, gracias.Estamos muy muertos en tener implementaciones más seguras de REST. Me estoy inclinando en esta dirección (rescatar toda la solicitud), y lo más importante es que requerirá una reescritura de una sección de nuestro motor hehehehe – user30921

+0

Gracias a todos los que respondieron. Creo que vamos a ir con el fracaso de toda la solicitud, si dejara de ser tan vago. – user30921

1

Yo discutiría 'sí' en teoría, pero 'no' para la aplicación en el mundo real.

Veo la lógica de no procesar si hay un error. Como devuelve un 406, no un 500, sabría que no es un error en los datos que proporcioné, sino más bien en la forma en que se me presenta el resultado.

Dicho esto, algunas aplicaciones no verifican los códigos de error; simplemente verán que regresó con un error en lugar del XML que solicitó, y supondrán que la transacción falló.

Supongo que no maneja la aplicación/xml no es un problema real, pero para los fines de la pregunta, si esto realmente se implementa como un servicio real, casi seguramente querría poder tener una representación XML, ya que es (sospecho) la interacción RESTful más común, y muchos llamadores probablemente estarían codificados para usar XML.

En resumen: si en realidad no proporciona la aplicación/xml, entonces diría que no realice la actualización. Si va a manejar todas las normas, pero usted está planeando para la contingencia de que un usuario le preguntará para la aplicación/fooSomethingNonStandard, y luego seguir adelante y llevar a cabo la actualización, pero asegúrese de responder con un 406.

+0

Gracias por los comentarios. La pregunta no es realmente sobre XML o cualquier formato en particular. Estamos intentando decidir si el motor que elige nuestras representaciones debe inspeccionar el tipo Aceptar antes o después de procesar la solicitud. Hacerlo al final de la solicitud (lo que hacemos ahora) significa responder 'sí'; hacerlo al comienzo de la solicitud significa responder 'no'. – user30921

2

La pregunta es: ¿debería el servidor haber realizado la actualización a/People/Bob?

De the HTTP spec, a 406 medios:

el recurso identificado por la solicitud es únicamente capaz de generar entidades de respuesta que tienen características de contenido no aceptable de acuerdo con las cabeceras aceptar enviados en la solicitud.

A menos que fuera una solicitud HEAD, la respuesta DEBERÍA incluir una entidad que contenga una lista de características de entidad disponibles y ubicación (s) de la cual el usuario o agente de usuario puede elegir la más apropiada. El formato de entidad se especifica mediante el tipo de medio proporcionado en el campo de encabezado Content-Type. Según el formato y las capacidades del agente de usuario, la selección de la opción más adecuada PUEDE realizarse automáticamente. Sin embargo, esta especificación no define ningún estándar para dicha selección automática.

Note: HTTP/1.1 servers are allowed to return responses which are 
    not acceptable according to the accept headers sent in the 
    request. In some cases, this may even be preferable to sending a 
    406 response. User agents are encouraged to inspect the headers of 
    an incoming response to determine if it is acceptable. 

Si la respuesta podría ser inaceptable, un agente de usuario debe suspender temporalmente la recepción de más datos y solicitar al usuario una decisión sobre nuevas medidas.

Esa nota en el medio acerca de HTTP/1.1 puede ser su respuesta. Lo leí diciendo "puede devolver un 200 en respuesta a la solicitud PUT a/People/Bob cuando el agente de usuario especifica application/xml en el encabezado Accept, seleccionando cualquier tipo de contenido adecuado, y que este resultado puede ser preferible a regresando 406. "

Bajo este escenario, el PUT tendría éxito en el servidor, devolvería 200, pero el cliente obtendría una representación de aplicación/json. El cliente debe ser capaz de manejar esa posibilidad asegurándose de que entiende el tipo de medio dado en el encabezado de tipo de contenido, y comportarse de una manera bien definida si no lo hace.

Pero esto siempre es cierto de todos modos.

Una cosa más: es posible que desee considerar no utilizar tipos de medios simple-vainilla como application/xml y application/json, sino definir sus propios tipos de medios personalizados, tal vez basados ​​en XHTML o JSON. Todo el client-server coupling in a RESTful application ocurre a través de los tipos de medios. Sin tipos de medios lo suficientemente ricos como para capturar los conceptos de su dominio, está especificando de manera incompleta su API REST.

+0

Gracias, observaciones muy astutas. Estoy tentado de responder a esta pregunta (es lo que sugirió uno de mis colegas de inmediato), pero no me siento bien al devolver algo inútil al cliente. También, gracias por los consejos sobre los tipos de medios, pero los que elegí para este ejemplo fueron simplemente vainilla y se aplicarían a cualquier combinación de tipos de medios. – user30921

+0

Esto comienza a parecerse al tipo de acoplamiento entre cliente y servidor que es mejor evitar. ¿Qué tan factible sería equipar el servidor con salida XML o equipar al cliente con la entrada JSON? Si la respuesta es "no muy", ¿qué hay de devolver un 400 para indicar inequívocamente que la solicitud falló y el servidor no se actualizó? –

1

Una forma de salir de su enigma es tener un PUT exitoso devolver un 204 (Sin contenido). De esta forma, el encabezado Accept del cliente es irrelevante para la cuestión de si se realiza la actualización.

Un cliente "RESTful" (o al menos "HTTP-abrazo") sabrá que no debe actualizar su "página" actual, y que tendrá que hacer un GET para actualizar su vista del PUT recurso. El encabezado Accept en ese GET ahora es, por supuesto, una preocupación separada de la atomicidad de la actualización.

+0

Gracias por los comentarios, pero en nuestra arquitectura, permitimos que PUT tenga un cuerpo de respuesta, que es la forma más eficiente de comunicar los cambios en el servidor, las actualizaciones de validación y los mensajes de validación al cliente (incluido un cuerpo en 422, que usamos para fallas de validación). – user30921

+0

@Chris, pensé que estabas demasiado lejos. :) Y definitivamente entiendo querer evitar una solicitud-respuesta adicional. Simplemente pensé que esta respuesta podría ser útil para otros que se enfrentan a una pregunta similar y que podrían tener requisitos diferentes. –

0

Yo tendría éxito y devolvería un 200 usando el método que Rich sugiere arriba o un 406 y falla. El protocolo no permite un enfoque más matizado al mezclar 2xx (Success) con códigos 4xx (Error), por lo que 4xx se puede leer para implicar NO éxito.

Cuestiones relacionadas