Skip to content

Commit

Permalink
Add error reponses and render helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
theandrew168 committed Sep 7, 2024
1 parent c736aa1 commit 2da579d
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 13 deletions.
45 changes: 32 additions & 13 deletions backend/web/error.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,44 @@
package web

import (
"io"
"net/http"

"github.com/theandrew168/bloggulus/backend/web/page"
)

func HandleNotFoundPage() http.Handler {
func NotFoundResponse(w http.ResponseWriter, r *http.Request) {
tmpl := page.NewError()

code := 404
data := page.ErrorData{
StatusCode: code,
StatusText: http.StatusText(code),
Message: "Sorry, this page could not be found.",
}

RenderError(w, r, code, func(w io.Writer) error {
return tmpl.Render(w, data)
})
}

func InternalServerErrorResponse(w http.ResponseWriter, r *http.Request, err error) {
tmpl := page.NewError()

code := 500
data := page.ErrorData{
StatusCode: code,
StatusText: http.StatusText(code),
Message: "Sorry, something went wrong.",
}

RenderError(w, r, code, func(w io.Writer) error {
return tmpl.Render(w, data)
})
}

func HandleNotFoundPage() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(404)

data := page.ErrorData{
StatusCode: 404,
StatusText: http.StatusText(404),
Message: "This page could not be found.",
}
err := tmpl.Render(w, data)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
NotFoundResponse(w, r)
})
}
50 changes: 50 additions & 0 deletions backend/web/render.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package web

import (
"bytes"
"io"
"log/slog"
"net/http"
)

// Generic function type for rendering data to an io.Writer.
type RenderFunc func(w io.Writer) error

// Render an HTML template based on a given RenderFunc.
func Render(w http.ResponseWriter, r *http.Request, code int, render RenderFunc) {
// Write the template to the buffer, instead of straight to the http.ResponseWriter.
// If there's an error, call our serverError() helper and then return.
var buf bytes.Buffer
err := render(&buf)
if err != nil {
InternalServerErrorResponse(w, r, err)
return
}

// If the template is written to the buffer without any errors, we are safe
// to go ahead and write the HTTP status code to http.ResponseWriter.
w.WriteHeader(code)

// Write the contents of the buffer to the http.ResponseWriter. Note: this
// is another time where we pass our http.ResponseWriter to a function that
// takes an io.Writer.
buf.WriteTo(w)
}

// Render an HTML error template based on a given RenderFunc. This function
// differs from Render in that it doesn't call InternalServerErrorResponse
// if something goes wrong since that could cause an infinite recursion.
func RenderError(w http.ResponseWriter, r *http.Request, code int, render RenderFunc) {
var buf bytes.Buffer
err := render(&buf)
if err != nil {
slog.Error(err.Error())

code = http.StatusInternalServerError
http.Error(w, http.StatusText(code), code)
return
}

w.WriteHeader(code)
buf.WriteTo(w)
}

0 comments on commit 2da579d

Please sign in to comment.