Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

unidades:10_servidor:01_rest [2014/08/30 11:18]
admin [Tratamiendo de errores]
unidades:10_servidor:01_rest [2014/10/13 09:32] (actual)
admin [Referencias]
Línea 21: Línea 21:
 Los datos que se envían es una petición HTTP son: Los datos que se envían es una petición HTTP son:
   * La URI del recurso que se pide.   * La URI del recurso que se pide.
 +  * El método HTTP
   * Las cabeceras HTTP. Hay gran cantidad de cabeceras pero su formato es siempre el nombre de la cabecera y su valor.   * Las cabeceras HTTP. Hay gran cantidad de cabeceras pero su formato es siempre el nombre de la cabecera y su valor.
   * El cuerpo de la petición con los datos del usuario. Por ejemplo datos en formato JSON o datos en formato XML.   * El cuerpo de la petición con los datos del usuario. Por ejemplo datos en formato JSON o datos en formato XML.
Línea 42: Línea 43:
   * El formato de los datos   * El formato de los datos
   * El estado de la aplicación   * El estado de la aplicación
-  * La paginación+  * Cache 
 +  * Etc.
  
 ===== Las operaciones a realizar ===== ===== Las operaciones a realizar =====
Línea 101: Línea 103:
 Una posible modificación que vi en un proyecto real consistía en hacer que el update y el insert no retornaran el objeto completo actualizado o insertado. Y no lo retornaban para ahorra tiempo y ancho de banda. Solo se retornaba en id del objeto recién insertado. Luego si hacía falta todos los datos , cosa que no solía necesitarse,​ se podían obtener con una llamada a ''​GET''​ extra. Una posible modificación que vi en un proyecto real consistía en hacer que el update y el insert no retornaran el objeto completo actualizado o insertado. Y no lo retornaban para ahorra tiempo y ancho de banda. Solo se retornaba en id del objeto recién insertado. Luego si hacía falta todos los datos , cosa que no solía necesitarse,​ se podían obtener con una llamada a ''​GET''​ extra.
 </​note>​ </​note>​
 +
 +
  
 ===== Tratamiendo de errores ===== ===== Tratamiendo de errores =====
 Como ya podemos imaginar la gestión de errores la tenemos que hacer siguiendo los códigos de estado de HTTP. Como ya podemos imaginar la gestión de errores la tenemos que hacer siguiendo los códigos de estado de HTTP.
  
-En la siguiente imagen podemos ver los [[https://​developer.yahoo.com/​social/​rest_api_guide/​http-response-codes.html|código ​que usa Yahoo en su API de social]]:+En la siguiente imagen podemos ver los [[https://​developer.yahoo.com/​social/​rest_api_guide/​http-response-codes.html|códigos ​que usa Yahoo en su API de social]]:
  
 {{:​unidades:​10_servidor:​yahoo_http_error_codes.png?​nolink|}} {{:​unidades:​10_servidor:​yahoo_http_error_codes.png?​nolink|}}
  
 +Controlar todos estos códigos en la aplicación es un poco excesivo, así que nosotros vamos a simplificar el números de códigos que retornará nuestra aplicación.
 +
 +Primero empecemos con solo 3 códigos:
 +  * ''​200 OK'':​ Si la petición ha sido realizada con éxito
 +  * ''​500 Internal Server Error'':​ Si ha habido algún error interno en nuestro propio servidor.
 +  * ''​400 Bad Request'':​ Si los datos enviados por el cliente no eran correctos. Normalmente son datos  escritos por el usuario y que son erróneos.
 +
 +El siguiente código útil es ''​204 No Content'',​ este lo deberíamos retornar en vez del ''​200 OK''​ cuando no retornemos ninguna dato. Por lo que debería retornarse al hacer un ''​DELETE''​.
 +
 +Los códigos ''​401 Unauthorized''​ y ''​403 Forbidden''​ los retornaría la parte de seguridad que no veremos en este curso.
 +
 +El código ''​404 Not Found''​ lo suele retornar el propio servidor si no encuentra la forma de procesar la petición y lo mismo pasa con el código ''​405 Not Allowed'' ​ que lo suele retornar automáticamente Spring ((El framework que vamos a usar para implementar la parte servidora en java)) si usamos un método HTTP con una URL que no soporta ese método.
 +
 +Así que resumiendo en nuestra aplicación solo deberíamos retornar los siguientes códigos:
 +
 +^ Código ​ ^ Nombre ^ Significado ^
 +| ''​200''​ | OK | Todo ha funcionado correctamente y retornamos los datos |
 +| ''​204''​ | No Content | Todo ha funcionado correctamente pero **NO** retornamos datos ya que no es necesario. Se usa en el DELETE en el que no se retorna nada |
 +| ''​400''​ | Bad Request | Hay errores en los datos que ha enviado el usuario. Se retornará un objeto ''​List<​BusinessMessage>''​ en formato JSON |
 +| ''​500''​ | Internal Server Error | Error del servidor. Se produce cuando hay un error en el código. Se retorna la excepción que se ha producido |
 +
 +REST no dice nada sobre que datos retornar cuando hay algún problema como es en el caso del ''​400 Bad Request''​ y ''​500 Internal Server Error''​. En nuestra arquitectura REST hemos decidido hace los siguiente.
 +
 +En caso de ''​500 Internal Server Error''​ retornaremos un texto plano con la traza de la excepción que se ha producido en Java. Ya que lo normal de cuando hay un error es que sea debido a que se ha lanzado una excepción en Java. De esa forma podremos depurar que ha ocurrido. Esto por otro lado podría ser un fallo de seguridad ya que la traza podría contener información que ayudara a realizar un ataque. La solución a ésto es simplemente que haya en el servidor una variable que indique si retornamos la traza completa , solo el nombre de la excepción o un mensaje diciendo que ha habido un error. Esta variable la podríamos cambiar según estemos en desarrollo o en producción , etc.
 +
 +En caso del ''​400 Bad Request''​ retornaremos una lista de mensajes para el usuario. Esta lista suelen ser las validaciones que han fallado al intentar realizar la operación. En nuestra arquitectura usaremos un array de clases Java llamada ''​BusinessMessage''​ que retornaremos en formato JSON al cliente. ​
 +
 +La estructura de la clase ''​BusinessMessage''​ es la siguiente:
 +<sxh java>
 +public class BussinessMessage ​ {
 +    private final String fieldName;
 +    private final String message;
 +
 +    public BussinessMessage(String fieldName, String message) {
 +        this.fieldName = fieldName;
 +        this.message = message;
 +    }
 +    ​
 +    public String getFieldName() {
 +        return fieldName;
 +    }
 +
 +    public String getMessage() {
 +        return message;
 +    }
 +   
 +}
 +</​sxh>​
 +
 +Mas información sobre esta clase la puedes encontrar en mi curso de hibernate en [[http://​cursohibernate.es/​doku.php?​id=unidades:​07_arquitectura:​02_excepciones&#​el_codigo_de_bussinessexception|El código de BussinessException]]
 +
 +===== El formato de los datos =====
 +Como ya dijimos al ver el formato de las URI, para indicar el formato en el que queremos que nos retornen los datos hay que usar la cabecera ''​Accept''​. Desde Angular no tenemos que preocuparnos por poner esta cabera ya que lo hace automáticamente para pedir los datos en formato JSON.
 +
 +Por otro lado cuando insertamos o actualizamos , estamos enviando datos en formato JSON, ¿Como le decimos al servidor que son en formato JSON? Usando la cabecera ''​Content-Type:​ application/​json''​. Tampoco debemos preocuparnos en ponerla ya que AngularJS también lo hace por defecto.
 +
 +Al retornarnos el servidor los datos también incluirá en la respuesta otra cabecera ''​Content-Type''​ para indicar el formato de los datos que ha retornado.
 +
 +Vamos ahora a resumir las cabeceras que hay al hacer una petición y recibir la respuesta:
 +  * En la petición:
 +    * ''​Accept''​ : Para indicar el formato de los datos que queremos que nos retorne el servidor
 +    * ''​ContentType''​ : Para indicar el formato de los datos que le estamos enviando.
 +  * En la respuesta:
 +    * ''​ContentType''​ : Para indicar el formato de los datos que se está devolviendo.
 +
 +Como ya hemos dicho, en la petición no tendremos que preocuparnos de poner estas cabeceras ya que AngularJS ya lo hace pero en la respuesta nosotros deberemos desde Java indicar el ''​Content-Type''​
 +
 +===== El estado de la aplicación =====
 +El tema del estado de la aplicación en el servidor es muy sencillo de tratar en REST. Simplemente nunca hay estado en el servidor para cada cliente. Cada petición debe ser independiente de las demas y nunca guardar nada en la sesión del servidor. ​
 +
 +Aunque esto es la teoría , yo personalmente si que guardo en la sesión el usuario que ha entrado en el sistema aunque se podría crear una solución **similar** ​ sin necesidad de guardar en el servidor nada usando [[https://​auth0.com/​blog/​2014/​01/​07/​angularjs-authentication-with-cookies-vs-token/​|Token-Based Authentication]].
 +
 +
 +===== Cache =====
 +Al ser una petición REST como cualquier otra petición a una página web deberíamos tener en cuenta que las peticiones se pueden cachear en el navegador o en cualquier otro punto de la red. Por ello en general es adecuado indicar desde el servidor si la respuesta puede ser o no cacheada.
 +
 +===== Otras características =====
 +Siguiente HTTP podríamos ver mas cosas como por ejemplo como hacer la paginación,​ como retornar solo ciertos campos , etc. Pero no los vamos a ver en este curso.
 +
 +
 +====== Referencias ======
 +  * [[http://​en.wikipedia.org/​wiki/​Representational_state_transfer|Wikipedia > REST]]
 +  * [[http://​martinfowler.com/​articles/​richardsonMaturityModel.html|Richardson Maturity Model]]
 +  * [[https://​auth0.com/​blog/​2014/​01/​07/​angularjs-authentication-with-cookies-vs-token/​|Cookies vs Tokens. Getting auth right with Angular.JS]]
 +  * [[http://​stackoverflow.com/​questions/​2001773/​understanding-rest-verbs-error-codes-and-authentication|Understanding REST: Verbs, error codes, and authentication]]:​ Clásica pregunta sobre REST en stackoverflow
 +  * [[http://​java.dzone.com/​articles/​restful-standard-resolved|RESTful Standard Resolved!]]:​ Resumen del formato de las URL en REST
 +  * [[http://​rest.elkstein.org/​|Learn REST: A Tutorial]]: Tutorial en inglés sobre REST
 +  * [[http://​roy.gbiv.com/​untangled/​2008/​rest-apis-must-be-hypertext-driven|REST APIs must be hypertext-driven]]:​ Las API REST deben tener las URL a los recursos.
 +  * [[http://​blog.2partsmagic.com/​restful-uri-design/​|REST-ful URI design]]: Como diseñar un buen API REST
 +  * [[http://​elbauldelprogramador.com/​buenas-practicas-para-el-diseno-de-una-api-restful-pragmatica/​|Buenas prácticas para el diseño de una API RESTful pragmática]]
  
unidades/10_servidor/01_rest.1409390317.txt.gz · Última modificación: 2014/08/30 11:18 por admin
Ir hasta arriba
CC Attribution-Share Alike 3.0 Unported
chimeric.de = chi`s home Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0