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