From 839483242813e35e14a702c88c35f610ce6d48d7 Mon Sep 17 00:00:00 2001 From: Muyao CHEN Date: Sun, 30 Jun 2024 17:08:47 +0200 Subject: [PATCH] Server-side form validation 1 --- cmd/web/routes.go | 1 + internal/forms/errors.go | 18 ++++++++++++++++++ internal/forms/forms.go | 26 ++++++++++++++++++++++++++ internal/handlers/handlers.go | 9 ++++++++- internal/models/templatedata.go | 3 +++ templates/make-reservation.page.tmpl | 4 +++- 6 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 internal/forms/errors.go create mode 100644 internal/forms/forms.go diff --git a/cmd/web/routes.go b/cmd/web/routes.go index 5c121f7..5f8d939 100644 --- a/cmd/web/routes.go +++ b/cmd/web/routes.go @@ -26,6 +26,7 @@ func routes(app *config.AppConfig) http.Handler { mux.Post("/availability", handlers.Repo.PostAvailability) mux.Post("/availability-json", handlers.Repo.AvailabilityJSON) mux.Get("/make-reservation", handlers.Repo.MakeReservation) + mux.Post("/make-reservation", handlers.Repo.PostMakeReservation) fileServer := http.FileServer(http.Dir("./static/")) mux.Handle("/static/*", http.StripPrefix("/static", fileServer)) diff --git a/internal/forms/errors.go b/internal/forms/errors.go new file mode 100644 index 0000000..43f45c6 --- /dev/null +++ b/internal/forms/errors.go @@ -0,0 +1,18 @@ +package forms + +type errors map[string][]string + +// Add adds an error message for a given form field +func (e errors) Add(field, message string) { + e[field] = append(e[field], message) +} + +// Get returns the first error message +func (e errors) Get(field string) string { + es := e[field] + + if len(es) == 0 { + return "" + } + return es[0] +} diff --git a/internal/forms/forms.go b/internal/forms/forms.go new file mode 100644 index 0000000..c1a03c6 --- /dev/null +++ b/internal/forms/forms.go @@ -0,0 +1,26 @@ +package forms + +import ( + "net/http" + "net/url" +) + +// Form creates a custom form struct, embeds a url.Values object +type Form struct { + url.Values + Errors errors +} + +// New initializes a form struct +func New(data url.Values) *Form { + return &Form{ + data, + errors(map[string][]string{}), + } +} + +// Has checks if form field is in post and not emtpy +func (f *Form) Has(field string, r *http.Request) bool { + x := r.Form.Get(field) + return x != "" +} diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go index 51dacfa..41dd0ba 100644 --- a/internal/handlers/handlers.go +++ b/internal/handlers/handlers.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "go-udemy-web-1/internal/config" + "go-udemy-web-1/internal/forms" "go-udemy-web-1/internal/models" "go-udemy-web-1/internal/render" "log" @@ -68,7 +69,13 @@ func (m *Repository) Majors(w http.ResponseWriter, r *http.Request) { // MakeReservation is the make reservation page handler func (m *Repository) MakeReservation(w http.ResponseWriter, r *http.Request) { - render.RenderTemplate(w, r, "make-reservation.page.tmpl", &models.TemplateData{}) + render.RenderTemplate(w, r, "make-reservation.page.tmpl", &models.TemplateData{ + Form: forms.New(nil), + }) +} + +// PostMakeReservation is the make reservation page post handler +func (m *Repository) PostMakeReservation(w http.ResponseWriter, r *http.Request) { } // Availability is the search for availability page handler diff --git a/internal/models/templatedata.go b/internal/models/templatedata.go index f800586..a852bf9 100644 --- a/internal/models/templatedata.go +++ b/internal/models/templatedata.go @@ -1,5 +1,7 @@ package models +import "go-udemy-web-1/internal/forms" + // TemplateData holds data sent from handlers to templates type TemplateData struct { StringMap map[string]string @@ -10,4 +12,5 @@ type TemplateData struct { Flash string Warning string Error string + Form *forms.Form } diff --git a/templates/make-reservation.page.tmpl b/templates/make-reservation.page.tmpl index c0a4c10..8005a68 100644 --- a/templates/make-reservation.page.tmpl +++ b/templates/make-reservation.page.tmpl @@ -5,7 +5,9 @@

Make reservation

-
+ + +