Let's Go User authentication › Routes setup
Previous · Contents · Next
Chapter 10.1.

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:

File: cmd/web/handlers.go
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:

File: cmd/web/routes.go
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:

File: ui/html/partials/nav.tmpl
{{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:

10.01-01.png

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:

10.01-02.png