From 715445ee5d97017472776b0cd680818eb8f1325d Mon Sep 17 00:00:00 2001 From: Maxim Lebedev Date: Sat, 27 Jan 2024 13:47:23 +0600 Subject: [PATCH] :recycle: Refactored custom headers support into middleware --- internal/cmd/home/home.go | 37 +++---------------- internal/domain/headers.go | 17 +++++++++ internal/domain/server.go | 4 +-- internal/middleware/header.go | 67 +++++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+), 35 deletions(-) create mode 100644 internal/domain/headers.go create mode 100644 internal/middleware/header.go diff --git a/internal/cmd/home/home.go b/internal/cmd/home/home.go index 98ba2c5..e7bc90b 100644 --- a/internal/cmd/home/home.go +++ b/internal/cmd/home/home.go @@ -77,23 +77,6 @@ func NewApp(logger *log.Logger, config *domain.Config) (*App, error) { return } - siteServer, err := serverer.Do(r.Context(), *s) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - - return - } - - for i := range siteServer.Headers { - if !siteServer.Headers[i].IsMatched(r.URL.Path) { - continue - } - - for name, value := range siteServer.Headers[i].Values { - w.Header().Add(name, value) - } - } - if s.IsMultiLingual() { head, tail := urlutil.ShiftPath(r.URL.Path) if head == "" { @@ -132,22 +115,6 @@ func NewApp(logger *log.Logger, config *domain.Config) (*App, error) { return } - if siteServer, err = serverer.Do(r.Context(), *s); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - - return - } - - for i := range siteServer.Headers { - if !siteServer.Headers[i].IsMatched(r.URL.Path) { - continue - } - - for name, value := range siteServer.Headers[i].Values { - w.Header().Add(name, value) - } - } - p, err := pager.Do(r.Context(), lang, r.URL.Path) if err != nil { if !errors.Is(err, page.ErrNotExist) { @@ -216,6 +183,10 @@ func NewApp(logger *log.Logger, config *domain.Config) (*App, error) { Siter: siter, Serverer: serverer, }), + middleware.Header(middleware.HeaderConfig{ + Siter: siter, + Serverer: serverer, + }), } return &App{server: &http.Server{ diff --git a/internal/domain/headers.go b/internal/domain/headers.go new file mode 100644 index 0000000..096c7aa --- /dev/null +++ b/internal/domain/headers.go @@ -0,0 +1,17 @@ +package domain + +type Headers []Header + +func (h Headers) Match(p string) []Header { + result := make(Headers, 0, len(h)) + + for i := range h { + if !h[i].IsMatched(p) { + continue + } + + result = append(result, h[i]) + } + + return result +} diff --git a/internal/domain/server.go b/internal/domain/server.go index d10004d..e997ff8 100644 --- a/internal/domain/server.go +++ b/internal/domain/server.go @@ -1,13 +1,13 @@ package domain type Server struct { - Headers []Header + Headers Headers Redirects Redirects } func NewServer() *Server { return &Server{ - Headers: make([]Header, 0), + Headers: make(Headers, 0), Redirects: make(Redirects, 0), } } diff --git a/internal/middleware/header.go b/internal/middleware/header.go new file mode 100644 index 0000000..fd7ba57 --- /dev/null +++ b/internal/middleware/header.go @@ -0,0 +1,67 @@ +package middleware + +import ( + "net/http" + + "source.toby3d.me/toby3d/home/internal/domain" + "source.toby3d.me/toby3d/home/internal/server" + "source.toby3d.me/toby3d/home/internal/site" + "source.toby3d.me/toby3d/home/internal/urlutil" +) + +type HeaderConfig struct { + Skipper Skipper + Siter site.UseCase + Serverer server.UseCase +} + +func Header(config HeaderConfig) Interceptor { + if config.Skipper == nil { + config.Skipper = DefaultSkipper + } + + if config.Siter == nil { + panic("middleware: header: Siter is nil") + } + + if config.Serverer == nil { + panic("middleware: header: Serverer is nil") + } + + return func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + if config.Skipper(r) { + next(w, r) + + return + } + + lang, path := domain.LanguageUnd, r.URL.Path + if head, tail := urlutil.ShiftPath(r.URL.Path); head != "" { + if lang = domain.NewLanguage(head); lang != domain.LanguageUnd { + path = tail + } + } + + site, err := config.Siter.Do(r.Context(), lang) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + + return + } + + server, err := config.Serverer.Do(r.Context(), *site) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + + return + } + + for _, header := range server.Headers.Match(path) { + for k, v := range header.Values { + w.Header().Add(k, v) + } + } + + next(w, r) + } +}