// package main is used here just for ease of running the demo.
// In reality, this would be package app
package main
import (
"flag"
"fmt"
"log"
"net/http"
)
// App is our Application's base http.Handler
type App struct {
*http.ServeMux
}
// NewApp constructs a new App and initializes our routing
func NewApp() *App {
mux := http.NewServeMux()
app := &App{mux}
mux.HandleFunc("/", app.Root)
return app
}
// Root is the root page of our application
func (a *App) Root(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello!")
}
var port = flag.Int("port", 8080, "Port to serve on")
func main() {
flag.Parse()
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", *port), NewApp()))
}
2. main_test.go
func TestAppRoot(t *testing.T) {
app := NewApp()
server := httptest.NewServer(app)
defer server.Close()
resp, err := http.Get(server.URL + "/")
if err != nil {
t.Error(err)
}
buf := &bytes.Buffer{}
buf.ReadFrom(resp.Body)
if strings.Index(buf.String(), "Hello!") == -1 {
t.Error("Root should say hello")
}
}
3. cookie.go
// Root is the root page of our application
func (a *App) Root(w http.ResponseWriter, r *http.Request) {
var name string
nameCookie, err := r.Cookie("name")
if err == nil {
name = nameCookie.Value
} else if err != http.ErrNoCookie {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
t := template.Must(template.New("root").Parse(`
<!doctype html>
<html>
<head><title>greeter</title></head>
<body>
{{if .}}
<h1>Hi {{.}}!</h1>
{{else}}
<h1>Welcome! Who are you?</h1>
<form method="POST" action="/name">
<input type="text" placeholder="Your name" name="name">
<input type="submit" value="Set Name">
</form>
{{end}}
</body>
</html>
`))
if err := t.Execute(w, name); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
// NewApp constructs a new App and initializes our routing
func NewApp() *App {
mux := http.NewServeMux()
app := &App{mux}
mux.HandleFunc("/", app.Root)
mux.HandleFunc("/name", app.SetName) // <- NEW
return app
}
func (a *App) SetName(w http.ResponseWriter, r *http.Request) {
http.SetCookie(w, &http.Cookie{
Name: "name",
Value: r.FormValue("name"),
HttpOnly: true,
Expires: time.Now().Add(24 * 14 * time.Hour),
})
http.Redirect(w, r, "/", http.StatusFound)
}
4. cookie_test.go
func TestSetName(t *testing.T) {
app := NewApp()
server := httptest.NewServer(app)
defer server.Close()
jar, err := cookiejar.New(nil)
if err != nil {
t.Error(err)
}
client := &http.Client{Jar: jar}
resp, err := client.Get(server.URL + "/")
if err != nil {
t.Error(err)
}
buf := &bytes.Buffer{}
buf.ReadFrom(resp.Body)
if strings.Index(buf.String(), "Welcome") == -1 {
t.Errorf("Root should say Welcome!:\n%s", buf.String())
}
resp, err = client.PostForm(
server.URL+"/name",
url.Values{"name": {"Nick"}},
)
if err != nil {
t.Error(err)
}
buf.Reset()
buf.ReadFrom(resp.Body)
if strings.Index(buf.String(), "Hi Nick!") == -1 {
t.Errorf("Root should say Hi Nick!:\n%s", buf.String())
}
}