From 615ed60168ca7c9b6fd6824ad29933fb0acfa065 Mon Sep 17 00:00:00 2001 From: Will McCutchen <will@mccutch.org> Date: Sun, 28 Aug 2016 12:18:53 -0700 Subject: [PATCH] Add /forms/post, refactor template handling --- main.go | 20 ++++++++++++++------ main_test.go | 10 ++++++++++ middleware.go | 17 +++++++++++++++++ templates/forms-post.html | 29 +++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 templates/forms-post.html diff --git a/main.go b/main.go index b08145d..e6f9b57 100644 --- a/main.go +++ b/main.go @@ -37,13 +37,19 @@ type UserAgentResp struct { UserAgent string `json:"user-agent"` } -func index(w http.ResponseWriter, r *http.Request) { - t, err := template.ParseGlob("templates/*.html") - if err != nil { - http.Error(w, fmt.Sprintf("error parsing templates: %s", err), http.StatusInternalServerError) +// Index must be wrapped by the withTemplates middleware before it can be used +func index(w http.ResponseWriter, r *http.Request, t *template.Template) { + t = t.Lookup("index.html") + if t == nil { + http.Error(w, fmt.Sprintf("error looking up index.html"), http.StatusInternalServerError) return } - t = t.Lookup("index.html") + t.Execute(w, nil) +} + +// FormsPost must be wrapped by withTemplates middleware before it can be used +func formsPost(w http.ResponseWriter, r *http.Request, t *template.Template) { + t = t.Lookup("forms-post.html") if t == nil { http.Error(w, fmt.Sprintf("error looking up index.html"), http.StatusInternalServerError) return @@ -83,7 +89,9 @@ func headers(w http.ResponseWriter, r *http.Request) { func app() http.Handler { h := http.NewServeMux() - h.HandleFunc("/", methods(index, "GET")) + templateWrapper := withTemplates("templates/*.html") + h.HandleFunc("/", methods(templateWrapper(index), "GET")) + h.HandleFunc("/forms/post", methods(templateWrapper(formsPost), "GET")) h.HandleFunc("/get", methods(get, "GET")) h.HandleFunc("/ip", ip) h.HandleFunc("/user-agent", userAgent) diff --git a/main_test.go b/main_test.go index 1baf1a9..327bedb 100644 --- a/main_test.go +++ b/main_test.go @@ -19,6 +19,16 @@ func TestIndex(t *testing.T) { } } +func TestFormsPost(t *testing.T) { + r, _ := http.NewRequest("GET", "/forms/post", nil) + w := httptest.NewRecorder() + app().ServeHTTP(w, r) + + if !strings.Contains(w.Body.String(), `<form method="post" action="/post">`) { + t.Fatalf("expected <form> in body") + } +} + func TestGet__Basic(t *testing.T) { r, _ := http.NewRequest("GET", "/get", nil) r.Host = "localhost" diff --git a/middleware.go b/middleware.go index dc0708c..e857f19 100644 --- a/middleware.go +++ b/middleware.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "html/template" "log" "net/http" ) @@ -50,3 +51,19 @@ func methods(h http.HandlerFunc, methods ...string) http.HandlerFunc { h.ServeHTTP(w, r) } } + +// Simplify function signatures below +type templateHandlerFunc func(http.ResponseWriter, *http.Request, *template.Template) + +func withTemplates(path string) func(templateHandlerFunc) http.HandlerFunc { + t, err := template.ParseGlob(path) + if err != nil { + log.Fatalf("error parsing templates: %s", err) + } + + return func(handler templateHandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + handler(w, r, t) + } + } +} diff --git a/templates/forms-post.html b/templates/forms-post.html new file mode 100644 index 0000000..e79dffd --- /dev/null +++ b/templates/forms-post.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html> + <head> + </head> + <body> + <!-- Example form from HTML5 spec http://www.w3.org/TR/html5/forms.html#writing-a-form's-user-interface --> + <form method="post" action="/post"> + <p><label>Customer name: <input name="custname"></label></p> + <p><label>Telephone: <input type=tel name="custtel"></label></p> + <p><label>E-mail address: <input type=email name="custemail"></label></p> + <fieldset> + <legend> Pizza Size </legend> + <p><label> <input type=radio name=size value="small"> Small </label></p> + <p><label> <input type=radio name=size value="medium"> Medium </label></p> + <p><label> <input type=radio name=size value="large"> Large </label></p> + </fieldset> + <fieldset> + <legend> Pizza Toppings </legend> + <p><label> <input type=checkbox name="topping" value="bacon"> Bacon </label></p> + <p><label> <input type=checkbox name="topping" value="cheese"> Extra Cheese </label></p> + <p><label> <input type=checkbox name="topping" value="onion"> Onion </label></p> + <p><label> <input type=checkbox name="topping" value="mushroom"> Mushroom </label></p> + </fieldset> + <p><label>Preferred delivery time: <input type=time min="11:00" max="21:00" step="900" name="delivery"></label></p> + <p><label>Delivery instructions: <textarea name="comments"></textarea></label></p> + <p><button>Submit order</button></p> + </form> + </body> +</html> -- GitLab