Routes setup
Let’s begin this section by adding five new routes to our application, so that it looks like this:
Method | Pattern | Handler | Action |
---|---|---|---|
GET | / | home | Display the home page |
GET | /snippet/view/:id | snippetView | Display a specific snippet |
GET | /snippet/create | snippetCreate | Display a HTML form for creating a new snippet |
POST | /snippet/create | snippetCreatePost | Create a new snippet |
GET | /user/signup | userSignup | Display a HTML form for signing up a new user |
POST | /user/signup | userSignupPost | Create a new user |
GET | /user/login | userLogin | Display a HTML form for logging in a user |
POST | /user/login | userLoginPost | Authenticate and login the user |
POST | /user/logout | userLogoutPost | Logout the user |
GET | /static/*filepath | http.FileServer | Serve a specific static file |
Notice how the new state-changing actions — userSignupPost
, userLoginPost
and userLogoutPost
— are all using POST
requests, not GET
?
Open up your handlers.go
file and add placeholders for the five new handler functions as follows:
package main ... func (app *application) userSignup(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Display a HTML form for signing up a new user...") } func (app *application) userSignupPost(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Create a new user...") } func (app *application) userLogin(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Display a HTML form for logging in a user...") } func (app *application) userLoginPost(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Authenticate and login the user...") } func (app *application) userLogoutPost(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Logout the user...") }
Then when that’s done, let’s create the corresponding routes in our routes.go
file:
package main ... func (app *application) routes() http.Handler { router := httprouter.New() router.NotFound = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { app.notFound(w) }) fileServer := http.FileServer(http.Dir("./ui/static/")) router.Handler(http.MethodGet, "/static/*filepath", http.StripPrefix("/static", fileServer)) dynamic := alice.New(app.sessionManager.LoadAndSave) router.Handler(http.MethodGet, "/", dynamic.ThenFunc(app.home)) router.Handler(http.MethodGet, "/snippet/view/:id", dynamic.ThenFunc(app.snippetView)) router.Handler(http.MethodGet, "/snippet/create", dynamic.ThenFunc(app.snippetCreate)) router.Handler(http.MethodPost, "/snippet/create", dynamic.ThenFunc(app.snippetCreatePost)) // Add the five new routes, all of which use our 'dynamic' middleware chain. router.Handler(http.MethodGet, "/user/signup", dynamic.ThenFunc(app.userSignup)) router.Handler(http.MethodPost, "/user/signup", dynamic.ThenFunc(app.userSignupPost)) router.Handler(http.MethodGet, "/user/login", dynamic.ThenFunc(app.userLogin)) router.Handler(http.MethodPost, "/user/login", dynamic.ThenFunc(app.userLoginPost)) router.Handler(http.MethodPost, "/user/logout", dynamic.ThenFunc(app.userLogoutPost)) standard := alice.New(app.recoverPanic, app.logRequest, secureHeaders) return standard.Then(router) }
Finally, we’ll also need to update the nav.tmpl
partial to include navigation items for the new pages:
{{define "nav"}} <nav> <div> <a href='/'>Home</a> <a href='/snippet/create'>Create snippet</a> </div> <div> <a href='/user/signup'>Signup</a> <a href='/user/login'>Login</a> <form action='/user/logout' method='POST'> <button>Logout</button> </form> </div> </nav> {{end}}
If you like, you can run the application at this point and you should see the new items in the navigation bar like this:

If you click the new links, they should respond with the relevant placeholder plain-text response. For example, if you click the ‘Signup’ link you should see a response similar to this:
