Servir fuera de la carpeta raíz

Servidor web completo en Go

Vamos a ver cómo crear un servidor web en el lenguaje de programación Go, también conocido como Golang. Lo que haremos será crear un servidor simple que responderá a peticiones GET, es decir, a las direcciones URL y que servirá archivos.

Explicado de otra manera, nuestro server hará esto:

  • Responder a peticiones dependiendo de la URL
  • Leer parámetros que pasamos por la URL
  • Servir un directorio y archivos, por ejemplo HTML, imágenes, vídeos, etcétera; algo así como lo hace el buen Apache o el servidor en Python.

No necesitaremos librerías extras ni frameworks, pues el maravilloso lenguaje provee todo lo que necesitamos.

Por cierto, si no lo tienes, mira cómo instalar Go en Windows.

Este tutorial es completo, explicaré a detalle cada cosa, te aseguro que aunque es un poco largo te enseñará lo robusto que es el lenguaje Go en cuanto a la web.

¿Interesado en algo más robusto? conoce mux.

Sobre Go y HTTP

Todo lo que usaremos para este servidor web está dentro del paquete net/http. Go es un lenguaje excelente para la web, y sus librerías incluidas por defecto hacen el trabajo muy bien.

El puerto y la dirección

A diferencia de Apache u otros servidores que ya vienen configurados por defecto, en Go podemos cambiar el puerto en una simple línea de código; nada de archivos de configuración.

Pero no sólo eso, sino que podemos especificar en cuál IP escuchar. En el código de abajo verás que a veces definimos el puerto como cadena, así:

":8080"

Y tú dirás, ¿no el puerto debería ser un entero, o bueno, no debería ir sin los dos puntos? La respuesta es que sí, pero no estamos especificando el puerto, sino la dirección. De otro modo, esa dirección podría quedar así:

"127.0.0.1:8080" o también "localhost:8080", de igual manera podría quedar como "192.168.1.76:8080" en donde 192.168.1.76 es la dirección del servidor.

¿Entonces, cuál es la diferencia? bueno, si especificamos únicamente :8080 entonces escuchamos en localhost, en la ip pública y en 127.0.0.1.

En caso de que sólo especifiquemos, por ejemplo, 127.0.0.1:8080, el servidor sólo respondería a peticiones que se hagan en la computadora que es al mismo tiempo el servidor, no desde otras. Tómalo en cuenta por si no quieres exponer tu servidor.

En resumen, si quieres que cualquier PC se conecte al servidor sabiendo su IP, especifica únicamente el puerto con :8080.

Por cierto, :8080 es un ejemplo, pero el puerto puede ser el que tú quieras, siempre y cuando esté desocupado.

Hola mundo, con un servidor HTTP en Go

El código para tener un servidor HTTP es este:

Lo que hacemos es llamar a HandleFunc, le ponemos la ruta y la función que lo manejará. En el caso de que visiten /hola se mostrará un simple mensaje que dirá “Solicitaste hola”.

De esa manera podemos definir más rutas, y más manejadores. Por cierto, si quieres usar el mismo manejador para dos rutas, define la función primero y guárdala, para más tarde mandarla como argumento.

Después de definir todas nuestras rutas, imprimimos un mensaje para decir que ya está listo nuestro servidor; y llamamos al método http.ListenAndServe; como primer argumento le ponemos la dirección y como segundo sería un manejador que no necesitamos por el momento (más información aquí).

Ahora compilamos y ejecutamos, visitamos la dirección y ya está nuestro servidor web con Go:

Hola mundo en servidor http con Go
Hola mundo en servidor http con Go

Otras rutas con Go

Como lo dije, podemos definir más rutas y manejadores distintos. No importa cómo sea la ruta o qué tan larga sea. Aquí vemos otro ejemplo:

De esta manera estamos sirviendo otra ruta. Más tarde traeré un tutorial para rutas en Go, con expresiones regulares, como lo hicimos con PHP.

Si visitamos ahora la ruta, se ve esto:

Más rutas en servidor web
Más rutas en servidor web

Leer parámetros de la URL

La mayoría de veces usamos la URL para mandar datos. Por ejemplo: sitio.com?id=1&nombre=parzibyte

Con Go, podemos leer los parámetros GET fácilmente. Veamos este ejemplo de lectura de parámetro de la url:

Para leer un parámetro utilizamos:

peticion.URL.Query()["clave"]

En donde clave es la clave que queremos leer. Esta función devolverá false como segunda respuesta si la clave no existe; por eso es que primero comprobamos si existen.

Otra cosa, ¿por qué es listaDeNombres y no simplemente nombre? es porque devolverá un arreglo con los valores que tengan esa clave. Por ejemplo, si la URL es:

http://localhost:8080/saludo?nombre=Parzibyte

Entonces devolverá [Parzibyte]

Pero si la URL es:

http://localhost:8080/saludo?nombre=Parzibyte&nombre=Maggie

Sí, dos veces la misma clave, entonces devuelve:

[Parzibyte, Maggie]

Esto permitiría mandar una lista de valores con la misma clave, pero ese no es el punto, por eso leemos el primer elemento: listaDeNombres[0]

Lo puedes ejecutar y dependiendo de los valores te dirá desconocido o tu nombre:

Parámetros en URL con servidor Go
Parámetros en URL con servidor Go

Servir archivos con servidor web de Go

Un servidor web sirve archivos, y no se limita a responder a rutas. Servir una carpeta pública con Go es muy fácil. Veamos este ejemplo:

En una línea servimos un directorio:

http.Handle("/", http.FileServer(http.Dir("./archivos")))

En este caso, cuando visitemos la raíz, se servirá todo lo que hay en la carpeta archivos. Compilamos y visitamos la página; veremos que muestra todo lo que hay en la carpeta:

Servir archivos o carpeta con servidor web en Go
Servir archivos o carpeta con servidor web en Go

Servidor de archivos con ruta distinta

En ese caso estamos sirviendo a partir de la raíz, en la url:

localhost:8080/

¿Qué pasa si queremos servir la carpeta pero en otra ruta? por ejemplo, en la url:

localhost:8080/archivos/

Eso no es posible con el código de arriba, porque Go sirve relativamente a la ruta del archivo. Si queremos servir en otra ruta, el código se complica pero sólo un poco:

Lo que hacemos es quitar un prefijo de la ruta. Para que se te haga fácil, lo mismo que pongas en la ruta ponlo en StripPrefix y listo.

Cabe mencionar que el argumento que se pasa a http.Dir puede ser una ruta absoluta si así se requiere.

Servir fuera de la carpeta raíz
Servir fuera de la carpeta raíz

Evitar confusiones al servir

Una cosa es la ruta en donde se sirve, y otra es la carpeta que se sirve. El nombre y la ruta no deben ser obligatoriamente las mismas; es decir, podríamos servir en la ruta publico la carpeta llamada archivos:

http.Handle("/publico/", http.StripPrefix("/publico/", http.FileServer(http.Dir("./archivos"))))

En ese caso servimos en la ruta publico, quitamos el prefijo publico, pero en realidad servimos lo que hay en archivos.

Servir otra carpeta

Puedes servir una carpeta que no es relativa al archivo. Así:

http.Handle("/publico/", http.StripPrefix("/publico/", http.FileServer(http.Dir(`D:`))))

De esa manera exponemos el disco local D  en la ruta /publico; por cierto, no lo hagas en casa.

Conclusión

Quedan pendientes más tutoriales que traeré pronto.

Actualización: aquí hay un tutorial con enrutador y middleware usando mux.

Por ejemplo para leer datos de un formulario, parsear rutas, comunicarse a través de JSON, renderizar plantillas y otras cosas interesantes.

Te invito a leer más sobre el módulo HTTP en Gohttps://golang.org/pkg/net/http/

Encantado de ayudarte


Estoy disponible para trabajar en tu proyecto, modificar el programa del post o realizar tu tarea pendiente, no dudes en ponerte en contacto conmigo.

No te pierdas ninguno de mis posts

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.

4 comentarios en “Servidor web completo en Go”

  1. Buenas tardes, una pregunta, tengo una pagina con acceso de login y tambien para logearse, esto hecho en golang con mysql, la pregunta es: 1- con localhost:8089 me funciona perfecto al grabar el logeo en mysql , opara entrar mediante login, pero como hago para que desde culaquier parte en internet se puedan loguear o entrar con el login, no he podido lograrlo, como puede ser la situacion

  2. Pingback: Enrutador y Middleware en Go con Gorilla Mux - Parzibyte's blog

  3. Pingback: WebAssembly en Go: tutorial y ejemplos - Parzibyte's blog

Dejar un comentario