package server import ( "errors" "fmt" "log/slog" "net/http" "strconv" "git.runcible.io/learning/ratchet/internal/model" ) // TODO function should accept and a pointer to an interface allowing for mocking in tests. func handleHome(logger *slog.Logger, tc *TemplateCache, snippetService *model.SnippetService) http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { // Retrieve Snippets from DB snippets, err := snippetService.Lastest() if err != err { serverError(w, r, err) return } logger.Debug(fmt.Sprintf("%d snippets retrieved", len(snippets))) // Old way. We want default data so // data := templateData{ // Snippets: snippets, // } data := newTemplateData() data.Snippets = snippets renderTemplate(w, r, tc, http.StatusOK, "home.go.tmpl", data) // // Initialize a slice containing the paths to the two files. It's important // // to note that the file containing our base template must be the *first* // // file in the slice. // files := []string{ // "./ui/html/base.go.tmpl", // "./ui/html/partials/nav.go.tmpl", // "./ui/html/pages/home.go.tmpl", // } // read template file into template set. // ts, err := template.ParseFiles(files...) // ts, err := parseTemplateFiles(files...) // if err != nil { // serverError(w, r, err) // return // } // // Write template content to response body // err = ts.ExecuteTemplate(w, "base", data) // if err != nil { // // This is the older more verbose way of doing what RatchetServer.serverError does // // rs.logger.Error(err.Error()) // // http.Error(w, "Internal Server Error", http.StatusInternalServerError) // serverError(w, r, err) // } }) } func handleSnippetView(logger *slog.Logger, tc *TemplateCache, snippetService *model.SnippetService) http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { id, err := strconv.Atoi(r.PathValue("id")) if err != nil || id < 1 { clientError(w, http.StatusNotFound) return } // Set a new cache-control header. If an existing "Cache-Control" header exists // it will be overwritten. // w.Header().Set("Cache-Control", "public, max-age=31536000") snippet, err := snippetService.Get(id) if err != nil { logger.Debug(fmt.Sprintf("Failed to retrieve an active record with id: %d", id)) if errors.Is(err, model.ErrNoRecord) { clientError(w, http.StatusNotFound) } else { serverError(w, r, err) } return } // files := []string{ // "./ui/html/base.go.tmpl", // "./ui/html/partials/nav.go.tmpl", // "./ui/html/pages/view.go.tmpl", // } // //ts, err := template.ParseFiles(files...) // ts, err := parseTemplateFiles(files...) // if err != nil { // serverError(w, r, err) // return // } // data := templateData{ // Snippet: snippet, // } // logger.Debug(fmt.Sprintf("created template: %s", ts.Name())) // Any data that you pass as the final parameter to ts.ExecuteTemplate() // is represented within your HTML templates by the . character (referred to as dot). // In this specific case, the underlying type of dot will be a models.Snippet struct. // When the underlying type of dot is a struct, you can render (or yield) the value // of any exported field in your templates by postfixing dot with the field name // field, we could yield the snippet title by writing {{.Title}} in our templates. // err = ts.ExecuteTemplate(w, "base", data) // if err != nil { // serverError(w, r, err) // } // data := templateData{ // Snippet: snippet, // } data := newTemplateData() data.Snippet = snippet renderTemplate(w, r, tc, http.StatusOK, "view.go.tmpl", data) }) } func handleSnippetCreateGet() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Create snippet form..")) }) } // snippetCreate handles display of the form used to create snippets // // curl -iL -d "" http://localhost:5001/snippet/create func handleSnippetCreatePost(logger *slog.Logger, tc *TemplateCache, snippetService *model.SnippetService) http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { // example of a custom header. Must be done before calling WriteHeader // or they will fail to take effect. w.Header().Add("Server", "Dirp") // Create some variables holding dummy data. We'll remove these later on // during the build. title := "O snail" content := "O snail\nClimb Mount Fuji,\nBut slowly, slowly!\n\n– Kobayashi Issa" expires := 7 id, err := snippetService.Insert(title, content, expires) if err != nil { serverError(w, r, err) } logger.Info(fmt.Sprintf("Inserted record. id: %d", id)) http.Redirect(w, r, fmt.Sprintf("/snippet/view/%d", id), http.StatusSeeOther) }) }