123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- package main
- import (
- "errors"
- "fmt"
- "html/template"
- "log"
- "net/http"
- "sync"
- "github.com/masterminds/sprig"
- )
- const (
- addr = ":8080"
- )
- type data map[string]any
- var (
- flashMessage string
- flashMX sync.Mutex
- )
- /*
- @app.route("/")
- def index():
- */
- func index(w http.ResponseWriter, r *http.Request) {
- http.Redirect(w, r, "/contacts", http.StatusSeeOther)
- }
- /*
- @app.route("/contacts")
- */
- func contacts(cs *ContactsStore) http.HandlerFunc {
- tpl := makeTemplate(
- "layout",
- "index",
- )
- return func(w http.ResponseWriter, r *http.Request) {
- search := r.URL.Query().Get("q")
- var contacts_set []*Contact
- if search == "" {
- contacts_set = cs.GetAll()
- } else {
- contacts_set = cs.Get(search)
- }
- if err := tpl.ExecuteTemplate(w, "layout.html", data{
- "contacts": contacts_set,
- "search": search,
- }); err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- }
- }
- }
- /*
- @app.route("/contacts/new", methods=['GET']) (1)
- */
- func contactsNewGet(cs *ContactsStore) http.HandlerFunc {
- tpl := makeTemplate(
- "layout",
- "new",
- )
- return func(w http.ResponseWriter, r *http.Request) {
- contact := cs.New(nil)
- if err := tpl.ExecuteTemplate(w, "layout.html", contact); err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- }
- }
- }
- /*
- @app.route("/contacts/new", methods=['POST'])
- */
- func contactsNew(cs *ContactsStore) http.HandlerFunc {
- tpl := makeTemplate(
- "layout",
- "new",
- )
- return func(w http.ResponseWriter, r *http.Request) {
- contact := cs.New(map[string]string{
- "first": r.PostFormValue("first_name"),
- "last": r.PostFormValue("last_name"),
- "phone": r.PostFormValue("phone"),
- "email": r.PostFormValue("email"),
- })
- if err := cs.Save(contact); err != nil {
- flash(fmt.Sprintf("Error saving contact: %v", err))
- if err := tpl.ExecuteTemplate(w, "layout.html", contact); err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- }
- }
- flash("Created New Contact!")
- http.Redirect(w, r, "/contacts", http.StatusSeeOther)
- return
- }
- }
- // flash implements a public flash: the first handler asking for a flash gets it.
- //
- // Not a good system in the general case, but it avoids using a session.
- func flash(newFlash string) {
- flashMX.Lock()
- defer flashMX.Unlock()
- flashMessage += newFlash
- }
- func getFlash() string {
- flashMX.Lock()
- defer flashMX.Unlock()
- previousFlash := flashMessage
- flashMessage = ""
- return previousFlash
- }
- func makeTemplate(first string, others ...string) *template.Template {
- paths := append([]string{first}, others...)
- for i, path := range paths {
- paths[i] = "./templates/" + path + ".gohtml"
- }
- tpl := template.Must(
- template.New(first).
- Funcs(sprig.FuncMap()).
- Funcs(template.FuncMap{"flash": getFlash}).
- ParseFiles(paths...))
- return tpl
- }
- func setupRoutes(mux *http.ServeMux, cs *ContactsStore) {
- mux.HandleFunc("/", index)
- mux.HandleFunc("/favicon.ico", func(w http.ResponseWriter, r *http.Request) {
- http.ServeFile(w, r, "./static/img/favicon.ico")
- })
- mux.Handle("GET /static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./static"))))
- mux.Handle("GET /contacts", contacts(cs))
- mux.Handle("GET /contacts/new", contactsNewGet(cs))
- mux.Handle("POST /contacts/new", contactsNew(cs))
- }
- func main() {
- cs, err := NewContactsStore()
- if err != nil {
- log.Fatalf("initializing contacts: %v\n", err)
- }
- mux := http.NewServeMux()
- setupRoutes(mux, cs)
- log.Printf("Listening on http://localhost%s", addr)
- if err := http.ListenAndServe(addr, mux); err != nil {
- if !errors.Is(err, http.ErrServerClosed) {
- log.Printf("Server error: %v\n", err)
- return
- }
- }
- log.Println("Server shutdown")
- }
|