cerrado @ f19adedc4b7f71c824a59d4a797bd8872bdb0bbd

 1package ext
 2
 3import (
 4	"errors"
 5	"fmt"
 6	"log/slog"
 7	"net/http"
 8
 9	"git.gabrielgio.me/cerrado/pkg/service"
10	"git.gabrielgio.me/cerrado/templates"
11	"github.com/go-git/go-git/v5/plumbing"
12)
13
14type (
15	Router struct {
16		middlewares []Middleware
17		router      *http.ServeMux
18	}
19	Middleware          func(next http.HandlerFunc) http.HandlerFunc
20	ErrorRequestHandler func(w http.ResponseWriter, r *http.Request) error
21)
22
23func NewRouter() *Router {
24	return &Router{
25		router: http.NewServeMux(),
26	}
27}
28
29func (r *Router) Handler() http.Handler {
30	return r.router
31}
32
33func (r *Router) AddMiddleware(middleware Middleware) {
34	r.middlewares = append(r.middlewares, middleware)
35}
36
37func wrapError(next ErrorRequestHandler) http.HandlerFunc {
38	return func(w http.ResponseWriter, r *http.Request) {
39		if err := next(w, r); err != nil {
40			if errors.Is(err, service.ErrRepositoryNotFound) ||
41				errors.Is(err, plumbing.ErrReferenceNotFound) {
42				NotFound(w, r)
43			} else {
44				slog.Error("Internal Server Error", "error", err)
45				InternalServerError(r, w, err)
46			}
47		}
48	}
49}
50
51func (r *Router) run(next ErrorRequestHandler) http.HandlerFunc {
52	return func(w http.ResponseWriter, re *http.Request) {
53		req := wrapError(next)
54		for _, r := range r.middlewares {
55			req = r(req)
56		}
57		req(w, re)
58	}
59}
60
61func (r *Router) HandleFunc(path string, handler ErrorRequestHandler) {
62	r.router.HandleFunc(path, r.run(handler))
63}
64
65func NotFound(w http.ResponseWriter, r *http.Request) {
66	w.WriteHeader(http.StatusNotFound)
67	templates.WritePageTemplate(w, &templates.ErrorPage{
68		Message: "Not Found",
69	}, r.Context())
70}
71
72func Redirect(w http.ResponseWriter, location string) {
73	w.Header().Add("location", location)
74	w.WriteHeader(http.StatusTemporaryRedirect)
75}
76
77func InternalServerError(r *http.Request, w http.ResponseWriter, err error) {
78	w.WriteHeader(http.StatusInternalServerError)
79	templates.WritePageTemplate(w, &templates.ErrorPage{
80		Message: fmt.Sprintf("Internal Server Error:\n%s", err.Error()),
81	}, r.Context())
82}