Go con Gin, el mega tutorial (VIII)

Nómadas ya estamos de vuelta con una nueva entrada de Go con Gin. Esta vez vamos a realizar comprobaciones de los errores que suceden en GoBlog. Comúnmente conocido como tratamiento de errores o error handling.

Go con Gin

Hasta ahora hemos estado utilizando Gin en modo desarrollo y todo ha ido genial, pero en algún momento nos tendremos que plantear usar GoBlog en producción. El cambiar a modo producción es muy sencillo, en Gin solo tenemos que añadir la siguiente instrucción antes iniciar el servidor Gin.

Si ahora ejecutamos GoBlog, veremos que nos aparece menos información que antes. Básicamente Gin nos está ocultando cuales son los handlers que tenemos configurados.

Hasta ahora hemos estado utilizando dos middleware por defecto y que nos hacían el uso de Gin mucho más cómodo. Éstos son gin.Logger() y gin.Recover(). Estos middleware proporcionan la capacidad de mostrar por pantalla las peticiones y errores y, recuperar el servidor ante errores inesperados, respectivamente. Ambos midelwares van implícitos con la llamada gin.Default().

Gin nos da la posibilidad de cambiar este comportamiento y utilizar los middlewares que nos interese.

Para iniciar Gin sin pre configuraciones es necesario iniciar el servidor con la llamada gin.New() en vez de gin.Default().

Solo con ese cambio podemos ejecutar GoBlog y todo funcionará bien, pero no tendremos la recuperación del servidor ante fallos inesperados ni la salida por pantalla de las peticiones y errores.

Ahora vamos a insertar un error inesperado para poder ver como tratar con éstos. La configuración ahora es la de iniciar Gin con gin.New().

El error será una división por cero. El error lo introduciremos en la función EditProfileFn en concreto en la línea 32 de:

Si intentamos modificar el nombre de usuario en el perfil veremos algo parecido a esto en el navegador:

Error inesperado en navegador

Y en el servidor algo parecido a esto otro:

Error inesperado en el terminal

Como podréis apreciar el servidor se queda bloqueado sin poder procesar más peticiones. Así que vamos a construir nuestro propio sistema de recuperación.

Te puede interesar  Telegram bots en golang (IV)

La función encargada de recuperar el estado de nuestro servidor la meteremos dentro de un middleware, por lo que deberemos de actualizar nuestro NewServer para registrar el nuevo middleware.

Lo que vemos en RegisterRecovery es una función que devuelve una función anónima de tipo gin handler. A su vez, este handler ejecuta una función anónima recuperando un panic.

En la línea 5 será donde debemos introducir la nueva lógica de control para la situación inesperada.

Si mostramos la petición desde c.Request podemos ver información parecida a esta:

Vista la información que nos proporciona la petición, vamos a enviarnos un correo electrónico cuando suceda un error inesperado.

Envío de errores por correo

Para enviar un correo electrónico podríamos hacerlo con la librería smtp de Go. Pero es algo ardua de tratar, así que vamos a utilizar una librería externa que nos facilitará un poco el envío de correos electrónicos. Esta librería se llama gomail.

No vamos a explicar el uso de gomail más allá del uso que le vamos a dar. Si alguien quiere profundizar puede visitar su documentación.

Como se puede ver la función es la misma que antes, lo único que ahora hemos añadido el código necesario en la línea 5 para recuperar la petición que se hizo. También hemos creado un mensaje para enviarlo por correo entre las líneas 7 y 18.

En el mensaje se envía tanto la petición que realizó el usuario, así como el error que ha producido el error.

Por último, se muestra la plantilla del índice con un error, así indicamos al usuario que algo inesperado ha sucedido.

Para comprobar los correos hemos utilizado un servidor smtp muy ligero para hacer las pruebas. Nosotros hemos utilizado https://github.com/andrewarrow/jungle_smtp que después de compilar el proyecto y ejecutarlo en local se queda un servidor de correo escuchando al puerto 25. el servidor parece que no hace nada, pero en cambio cuando se envía un correo el servidor lo guarda en un fichero junto al binario. Así que para ver el resultado del correo solo hay que leer el fichero generado.

Te puede interesar  DEP, el gestor de librerías y vendoring de Go

Ruta: Not Found

Otra situación incomoda que tenemos ahora mismo es que no proporcionamos un error adecuado para cuando el usuario visita una página que no existe.

La solución a este error es muy sencilla, pues Gin nos ofrece un método para registrar un handler en caso que no se cumpla ninguna ruta. El método es NoRoute. Este método lo utilizaremos en la función RegisterRoutes y le asignaremos el siguiente handler handlers.NoRouteFn.

Si probamos de nuevo a visitar una URI que no existe veremos que ahora el error está “dentro” de GoBlog.

Error NotFound en GoBlog

Logging a fichero

Desde que hemos empezado el post no hemos tenido apenas información por pantalla, así que ahora vamos a por ello.

Si queremos mostrar información tal cual la estábamos viendo hasta ahora deberíamos de incluir el logger de Gin. Por ejemplo, srv.Use(gin.Logger()) en la función NewServer.

Pero si por el contrario queremos registrar los resultados en un fichero podemos utilizar el método de Gin LoggerWithWriter. Este método requiere que el primer parámetro sea de tipo io.Writer. Esto significa que podemos abrir un fichero y proporcionarlo como primer parámetro para escribir en él. Pero nosotros vamos a implementar nuestro propio sistema de logging. No porque el sistema de logging de Gin no sea bueno, sino para mostrar más opciones.

Para realizar nuestro logger vamos a utilizar un fichero, donde escribiremos los logs, y también necesitamos definir un middleware.

El middleware es prácticamente el mismo que implementa Gin con LoggerWithWriter, lo cierto es que no necesitamos ni más ni menos, pero así vemos como podemos mostrar logs según nos interese.

Al final de la jugada se trata de enviar el log a un fichero, que pasamos como parámetro, mediante la función Fprintf del módulo fmt.

La función NewServer también sufre pequeñas modificaciones para poder utilizar nuestro sistema de logging.

Como se puede apreciar, hemos añadido la línea 6 y también es fácil ver que pasamos como parámetro una variable llamada Logger. Esta variable la definimos justo antes de de la función NewServer, de forma global. La variable la definimos tal que así: var Logger *os.File.

Para inicializar la variable Logger hacemos algo parecido a lo que hicimos con la base de datos. En el fichero main.go situado en cmd/goblog/main.go abrimos un fichero, comprobamos que no haya ningún error y asignamos el fichero abierto a la variable Logger.

Con esto nuestro sistema de blogging nos registrará todas las peticiones en el fichero goblog.log, pero seguiremos sin ver nada por la pantalla. La solución es añadir el middelware que Gin proporciona para registrar las peticiones de los usuarios y mostrarlas por pantalla.

Te puede interesar  Telegram bots en golang

Con esos cambios aplicados la función NewServer queda como sigue:

Solucionar el bug introducido

En la entrada anterior habíamos introducido un error cuando permitíamos modificar la información del perfil. Pues, un usuario puede cambiar el nombre por el de otro usuario provocando un error en la base de datos. Como hemos definido que el nombre es un dato único éste no puede repetirse en la columna. Así que antes de aceptar los cambios debemos de validar que el nombre de usuario sea único.

Lo que haremos pues, es buscar en la base de datos si existe algún usuario con el nombre solicitado y en caso que exista el nombre de usuario rechazaremos la petición del usuario, en caso contrario actualizaremos el objeto usuario de la sesión y en la base de datos.

En la línea 27 es donde buscamos el nuevo nombre de usuario en la base de datos. En la línea 28 comprobamos si existe el usuario o no y según los resultados actualizamos los datos del usuario tanto en la sesión como en la base de datos o, por el contrario, establecemos un error para ser mostrado en la página del perfil.

Bueno nómadas, hasta aquí el tratamiento de errores. En el siguiente post veremos como añadir seguidores.

Saludos,

Go con Gin, el mega tutorial (VIII)
Etiquetado en:                 

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *