3. Creating a Basic Web App

最后更新于:2022-04-01 03:03:48

# Creating a Basic Web App Now that we are done going over the basics of HTTP, let's create a simple butuseful web application in Go. Pulling from our fileserver program that we implemented last chapter, we willimplement a Markdown generator using the `github.com/russross/blackfriday`package. ## HTML Form For starters, we will need a basic HTML form for the markdown input: ~~~ <html> <head> <link href="/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="container"> <div class="page-title"> <h1>Markdown Generator</h1> <p class="lead">Generate your markdown with Go</p> <hr /> </div> <form action="/markdown" method="POST"> <div class="form-group"> <textarea class="form-control" name="body" 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> ~~~ Put this HTML into a file named `index.html` in the "public" folder of our applicationand the `bootstrap.min.css` from [http://getbootstrap.com/](http://getbootstrap.com/) in the "public/css" folder.Notice that the form makes an HTTP POST to the "/markdown" endpoint of ourapplication. We don't actually handle that route right now, so let's add it. ## The "/markdown" route The program to handle the '/markdown' route and serve the public `index.html`file looks like this: ~~~ package main import ( "net/http" "github.com/russross/blackfriday" ) func main() { http.HandleFunc("/markdown", GenerateMarkdown) http.Handle("/", http.FileServer(http.Dir("public"))) http.ListenAndServe(":8080", nil) } func GenerateMarkdown(rw http.ResponseWriter, r *http.Request) { markdown := blackfriday.MarkdownCommon([]byte(r.FormValue("body"))) rw.Write(markdown) } ~~~ Let's break it down into smaller pieces to get a better idea of what is goingon. ~~~ http.HandleFunc("/markdown", GenerateMarkdown) http.Handle("/", http.FileServer(http.Dir("public"))) ~~~ We are using the `http.HandleFunc` and `http.Handle` methods to define somesimple routing for our application. It is important to note that calling`http.Handle` on the "/" pattern will act as a catch-all route, so we definethat route last. `http.FileServer` returns an `http.Handler` so we use`http.Handle` to map a pattern string to a handler. The alternative method,`http.HandleFunc`, uses an `http.HandlerFunc` instead of an `http.Handler`.This may be more convenient, to think of handling routes via a functioninstead of an object. ~~~ func GenerateMarkdown(rw http.ResponseWriter, r *http.Request) { markdown := blackfriday.MarkdownCommon([]byte(r.FormValue("body"))) rw.Write(markdown) } ~~~ Our GenerateMarkdown function implements the standard `http.HandlerFunc`interface and renders HTML from a form field containingmarkdown-formatted text. In this case, the content is retrievedwith `r.FormValue("body")`. It is very common to get input from the`http.Request` object that the `http.HandlerFunc` receives as an argument.Some other examples of input are the `r.Header`, `r.Body`, and `r.URL` members. We finalize the request by writing it out to our `http.ResponseWriter`. Noticethat we didn't explicitly send a response code. If we write out to the responsewithout a code, the `net/http` package will assume that the response is a `200OK`. This means that if something did happen to go wrong, we should set theresponse code via the `rw.WriteHeader()` method. ~~~ http.ListenAndServe(":8080", nil) ~~~ The last bit of this program starts the server, we pass `nil` as our handler,which assumes that the HTTP requests will be handled by the `net/http` packagesdefault `http.ServeMux`, which is configured using `http.Handle` and`http.HandleFunc`, respectively. And that is all you need to be able to generate markdown as a service in Go. Itis a surprisingly small amount of code for the amount of heavy lifting it does.In the next chapter we will learn how to deploy this application to the webusing Heroku.
';