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: