Construyendo aplicaciones Web con Go

El paquete net/http

Probablemente has escuchado que Go es fantástico para crear aplicaciones web de todas las formas y tamaños. Esto se debe en parte al fantástico esfuerzo que se ha puesto en hacer una biblioteca estándar limpia, consistente y fácil de usar.

Tal vez uno de los paquetes más importantes para cualquier desarrollador web en ciernes Go es el paquete net/http. Este paquete te permite construir servidores HTTP en Go con sus poderosas construcciones de composición. Antes de comenzar a codificar, hagamos un muy rápido resumen de HTTP.

Conceptos HTTP básicos

Cuando hablamos de la construcción de aplicaciones web, normalmente queremos decir que estamos construyendo servidores HTTP. HTTP es un protocolo que originalmente fue diseñado para transportar documentos HTML desde un servidor hasta un navegador web cliente. Hoy, HTTP se utiliza para el transporte de un mucho más amplio conjunto de cosas que simplemente HTML.

Lo importante a notar en este diagrama son los dos puntos de interacción entre el servidor y el navegador. El navegador realiza una petición HTTP con un poco de información, el servidor procesa esa petición y devuelve una respuesta.

Este modelo de petición-respuesta es uno de los puntos focales clave en la construcción de aplicaciones web en Go. De hecho, la pieza más importante del paquete es la interfaz http.Handler.

La Interfaz http.Handler

A medida que te familiarices más con Go, te darás cuenta de cuanto impactan las interfaces en el diseño de tus programas. La interfaz net/http encapsula en un método el patrón petición-respuesta:

type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

Se espera que los implementadores de esta interfaz inspeccionen y procesen datos procedentes del objeto http.Request y escriban una respuesta en el objeto http.ResponseWriter.

La interfaz http.ResponseWriter tiene esta apariencia:

type ResponseWriter interface {
    Header() Header
    Write([]byte) (int, error)
    WriteHeader(int)
}

Componiendo servicios Web

Debido a que gran parte del paquete net/http está construido de tipos interfaz bien definidos, puedes (y se espera que) construyas tus aplicaciones web con la composición en mente. Cada implementación de http.Handler se puede considerar como su propio servidor web.

Puedes encontrar muchos patrones en esa simple pero poderosa suposición. A lo largo de este libro cubriremos algunos de estos patrones y cómo podemos utilizarlos para resolver problemas del mundo real.

Ejercicio: Un servidor de ficheros en 1 línea

Vamos a resolver un problema del mundo real en 1 línea de código.

La mayoría de las veces la gente sólo tiene que servir archivos estáticos. Tal vez tienes una página HTML estática y sólo quieres servir un poco de HTML, imágenes y CSS y llamarla un día. Claro, podrías ponerla bajo el servidor Apache o SimpleHTTPServer de Python, pero Apache es demasiado para este pequeño sitio y SimpleHTTPServer es, bueno, demasiado lento.

Empecemos creando un nuevo proyecto en nuestro GOPATH.

cd GOPATH/src
mkdir servidorfichero && cd servidorfichero

Crea un fichero main.go con nuestro típico y repetitivo texto modelo:

package main

import "net/http"

func main() {
}

Todo lo que necesitamos importar para que esto funcione es el paquete net/http. Recuerda que todo esto es parte de la biblioteca estándar de Go.

Escribamos nuestro código del servidor de ficheros:

http.ListenAndServe(":8080" , http.FileServer(http.Dir(".")))

La función http.ListenAndServe se utiliza para iniciar el servidor, se vinculará a la dirección que le dimos (:8080) y cuando reciba una petición HTTP, la entregaremos al http.Handler que suministramos como segundo argumento. En nuestro caso es la función incorporada http.FileServer.

La función http.FileServer construye un http.Handler que servirá un directorio de ficheros completo y averiguará cual fichero entregar basándose en la ruta de la petición. Con http.Dir(".") especificamos que el servidor de ficheros sirve el directorio de trabajo actual.

Todo el programa se ve así:

package main

import "net/http"

func main() {
    http.ListenAndServe(":8080", http.FileServer(http.Dir(".")))
}

Ahora construyamos y ejecutemos nuestro programa servidor de ficheros:

go build
./servidorfichero

Si visitas localhost:8080/main.go en tu navegador web, deberías ver el contenido de tu fichero main.go. Puedes ejecutar este programa desde cualquier directorio y servir el árbol como un servidor de ficheros estáticos. Todo esto en 1 sola línea de código Go.