Ahora que terminamos de repasar los conceptos básicos de HTTP, vamos a crear una sencilla pero útil aplicación web en Go.
Mejorando nuestro programa servidor de ficheros que implementamos en el
capítulo anterior, vamos a implementar un pequeño editor de texto en el
cual podemos introducir marcas del formato markdown
, a partir del cual
generaremos código HTML con el paquete github.com/russross/blackfriday
.
Para empezar, necesitamos un formulario HTML básico para introducir texto:
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8">
<title>Generador de HTML</title>
<link href="/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="page-title">
<h1>Editor de texto en formato markdown</h1>
<p class="lead">Go genera HTML a partir de markdown</p>
<hr />
</div>
<form action="/markdown" method="POST">
<div class="form-group">
<textarea class="form-control" name="cuerpo" cols="30" rows="10"></textarea>
</div>
<div class="form-group">
<input type="submit" class="btn btn-primary pull-right" />
</div>
</form>
</div>
<script src="/js/bootstrap.min.js"></script>
</body>
</html>
Pon este código HTML en un fichero llamado index.html
en el directorio
"publico"
de la aplicación y el bootstrap.min.css
de
http://getbootstrap.com/
en el directorio "publico/css"
. Observa que
el formulario hace un POST
HTTP al destino final "/markdown"
de
nuestra aplicación. Realmente en este momento todavía no manejamos esta
ruta, por lo tanto la vamos a añadir.
El programa para manejar la ruta '/markdown'
y para servir el fichero
index.html
al público en general se ve así:
package main
import (
"net/http"
"github.com/russross/blackfriday"
)
func main () {
http.HandleFunc("/markdown", GeneraDesdeMarkdown)
http.Handle("/", http.FileServer(http.Dir("publico")))
http.ListenAndServe(":8080", nil)
}
func GeneraDesdeMarkdown(rw http.ResponseWriter, r *http.Request) {
html := blackfriday.MarkdownCommon([]byte (r.FormValue("cuerpo")))
rw.Write(html)
}
Dividamos este código en pequeñas piezas para tener una mejor idea de lo que está pasando:
http.HandleFunc("/markdown", GeneraDesdeMarkdown)
http.Handle("/", http.FileServer(http.Dir("publico")))
Estamos utilizando los métodos http.HandleFunc
y http.Handle
para
definir algún sencillo enrutamiento para nuestra aplicación. Es
importante señalar que llamar a http.Handle
en el patrón "/"
actuará
como una ruta comodín que captura todo, motivo por el cual definimos esa
ruta al último. http.FileServer
devuelve un http.Handler
así que
usamos http.Handle
para asignar una cadena de caracteres como patrón a
un controlador. El método alternativo, http.HandleFunc
, utiliza un
http.HandlerFunc
en lugar de un http.Handler
. Este posiblemente sea
más conveniente, para pensar en el manejo de las rutas a través de una
función en lugar de con un objeto.
func GeneraDesdeMarkdown(rw http.ResponseWriter, r *http.Request) {
html := blackfriday.MarkdownCommon([]byte (r.FormValue("cuerpo")))
rw.Write (html)
}
Nuestra función GeneraDesdeMarkdown
implementa la interfaz
http.HandlerFunc
estándar y renderiza código HTML de un campo del
formulario que contiene texto con formato markdown
. En este caso, el
contenido se recupera con r.FormValue("cuerpo")
. Es muy común conseguir
entrada desde el objeto http.Request
que recibe el http.HandlerFunc
como argumento. Algunos otros ejemplos de entrada son los miembros
r.Header
, r.Body
y r.URL
.
Finalizamos la petición escribiendo a nuestro http.ResponseWriter
.
Nótese que no enviamos explícitamente un código de respuesta. Si
escribimos a la respuesta sin un código, el paquete net/http
asumirá que
la respuesta es 200 OK
. Esto significa que si sucedió algo malo para
Go, debemos establecer el código de respuesta a través del método
rw.WriteHeader()
.
http.ListenAndServe(":8080", nil)
La última parte de este programa inicia el servidor, le pasamos nil
como
nuestro controlador, con lo cual asume que las peticiones HTTP serán
manejadas de manera predeterminada por los paquetes net/http
y
http.ServeMux
, que se configuran utilizando http.Handle
y
http.HandleFunc
, respectivamente.
Y eso es todo lo que se necesita para poder generar código HTML a partir
de markdown
con un servicio en Go. Es una sorprendentemente pequeña
cantidad de código para la cantidad de trabajo pesado que hace. En el
próximo capítulo aprenderemos cómo desplegar esta aplicación en la web
usando Heroku
.