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.