diff --git a/snippetbox/cmd/web/handlers.go b/snippetbox/cmd/web/handlers.go index 294c2e4..e44b175 100644 --- a/snippetbox/cmd/web/handlers.go +++ b/snippetbox/cmd/web/handlers.go @@ -3,13 +3,13 @@ package main import ( "fmt" "html/template" - "log" + "log/slog" "net/http" "strconv" ) // home ... -func home(w http.ResponseWriter, r *http.Request) { +func (app *application) home(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { http.NotFound(w, r) return @@ -23,21 +23,21 @@ func home(w http.ResponseWriter, r *http.Request) { ts, err := template.ParseFiles(files...) if err != nil { - log.Print(err.Error()) + app.logger.Error(err.Error(), slog.String("method", r.Method), slog.String("uri", r.URL.RequestURI())) http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } err = ts.ExecuteTemplate(w, "base", nil) if err != nil { - log.Print(err.Error()) + app.logger.Error(err.Error(), slog.String("method", r.Method), slog.String("uri", r.URL.RequestURI())) http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } } // snippetView ... -func snippetView(w http.ResponseWriter, r *http.Request) { +func (app *application) snippetView(w http.ResponseWriter, r *http.Request) { id, err := strconv.Atoi(r.URL.Query().Get("id")) if err != nil || id < 1 { http.NotFound(w, r) @@ -48,7 +48,7 @@ func snippetView(w http.ResponseWriter, r *http.Request) { } // snippetCreate ... -func snippetCreate(w http.ResponseWriter, r *http.Request) { +func (app *application) snippetCreate(w http.ResponseWriter, r *http.Request) { w.Header().Set("Allow", "POST") if r.Method != http.MethodPost { diff --git a/snippetbox/cmd/web/main.go b/snippetbox/cmd/web/main.go index b0b88e2..6652d9f 100644 --- a/snippetbox/cmd/web/main.go +++ b/snippetbox/cmd/web/main.go @@ -2,27 +2,55 @@ package main import ( "flag" - "log" + "log/slog" "net/http" + "os" ) +// for application wide dependencies +type application struct { + logger *slog.Logger +} + // main it's the snippetbox webapp func main() { - //configuration + // configuration addr := flag.String("addr", ":4000", "HTTP network address") + logfmt := flag.String("logfmt", "text", "Log output format") + loglevel := flag.String("loglevel", "INFO", "Log level: DEBUG, INFO, WARN, or ERROR") flag.Parse() + var logger *slog.Logger + var handler_options slog.HandlerOptions + + switch *loglevel { + case "DEBUG": handler_options = slog.HandlerOptions{Level: slog.LevelDebug} + case "INFO": handler_options = slog.HandlerOptions{Level: slog.LevelInfo} + case "WARN": handler_options = slog.HandlerOptions{Level: slog.LevelWarn} + case "ERROR": handler_options = slog.HandlerOptions{Level: slog.LevelError} + } + + switch *logfmt { + case "json": logger = slog.New(slog.NewJSONHandler(os.Stdout, &handler_options)) + default: logger = slog.New(slog.NewTextHandler(os.Stdout, &handler_options)) + } + + app := &application{ + logger: logger, + } + mux := http.NewServeMux() // setup server for static files fileServer := http.FileServer(http.Dir("./ui/static")) mux.Handle("/static/", http.StripPrefix("/static", fileServer)) - mux.HandleFunc("/", home) - mux.HandleFunc("/snippet/view", snippetView) - mux.HandleFunc("/snippet/create", snippetCreate) + mux.HandleFunc("/", app.home) + mux.HandleFunc("/snippet/view", app.snippetView) + mux.HandleFunc("/snippet/create", app.snippetCreate) - log.Printf("starting a server on %s", *addr) + logger.Info("starting server", slog.String("addr", *addr)) err := http.ListenAndServe(*addr, mux) - log.Fatal(err) + logger.Error(err.Error()) + os.Exit(1) } diff --git a/snippetbox/ui/html/pages/home.tmpl b/snippetbox/ui/html/pages/home.bak similarity index 100% rename from snippetbox/ui/html/pages/home.tmpl rename to snippetbox/ui/html/pages/home.bak