Routes setup
Let’s begin this section by adding five new routes to our application, so that it looks like this:
Route pattern | Handler | Action |
---|---|---|
GET /{$} | home | Display the home page |
GET /snippet/view/{id} | snippetView | Display a specific snippet |
GET /snippet/create | snippetCreate | Display a form for creating a new snippet |
POST /snippet/create | snippetCreatePost | Create a new snippet |
GET /user/signup | userSignup | Display a form for signing up a new user |
POST /user/signup | userSignupPost | Create a new user |
GET /user/login | userLogin | Display a form for logging in a user |
POST /user/login | userLoginPost | Authenticate and login the user |
POST /user/logout | userLogoutPost | Logout the user |
GET /static/ | http.FileServer | Serve a specific static file |
Note that the new state-changing handlers — userSignupPost
, userLoginPost
and userLogoutPost
— are all using POST
requests, not GET
.
If you’re following along, 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 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 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 the routes.go
file:
package main ... func (app *application) routes() http.Handler { mux := http.NewServeMux() fileServer := http.FileServer(http.Dir("./ui/static/")) mux.Handle("GET /static/", http.StripPrefix("/static", fileServer)) dynamic := alice.New(app.sessionManager.LoadAndSave) mux.Handle("GET /{$}", dynamic.ThenFunc(app.home)) mux.Handle("GET /snippet/view/{id}", dynamic.ThenFunc(app.snippetView)) mux.Handle("GET /snippet/create", dynamic.ThenFunc(app.snippetCreate)) mux.Handle("POST /snippet/create", dynamic.ThenFunc(app.snippetCreatePost)) // Add the five new routes, all of which use our 'dynamic' middleware chain. mux.Handle("GET /user/signup", dynamic.ThenFunc(app.userSignup)) mux.Handle("POST /user/signup", dynamic.ThenFunc(app.userSignupPost)) mux.Handle("GET /user/login", dynamic.ThenFunc(app.userLogin)) mux.Handle("POST /user/login", dynamic.ThenFunc(app.userLoginPost)) mux.Handle("POST /user/logout", dynamic.ThenFunc(app.userLogoutPost)) standard := alice.New(app.recoverPanic, app.logRequest, commonHeaders) return standard.Then(mux) }
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:
