diff options
Diffstat (limited to 'pkg/ext')
| -rw-r--r-- | pkg/ext/compression.go | 2 | ||||
| -rw-r--r-- | pkg/ext/log.go | 53 | ||||
| -rw-r--r-- | pkg/ext/router.go | 72 | 
3 files changed, 126 insertions, 1 deletions
| diff --git a/pkg/ext/compression.go b/pkg/ext/compression.go index 92144b8..57ad49a 100644 --- a/pkg/ext/compression.go +++ b/pkg/ext/compression.go @@ -24,7 +24,7 @@ type CompressionResponseWriter struct {  	compressWriter io.Writer  } -func Compress(next func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) { +func Compress(next http.HandlerFunc) http.HandlerFunc {  	return func(w http.ResponseWriter, r *http.Request) {  		if accept, ok := r.Header["Accept-Encoding"]; ok {  			if compress, algo := GetCompressionWriter(u.FirstOrZero(accept), w); algo != "" { diff --git a/pkg/ext/log.go b/pkg/ext/log.go new file mode 100644 index 0000000..a9d26a9 --- /dev/null +++ b/pkg/ext/log.go @@ -0,0 +1,53 @@ +package ext + +import ( +	"log/slog" +	"net/http" +	"time" +) + +type statusWraper struct { +	statusCode  int +	innerWriter http.ResponseWriter +} + +func (s *statusWraper) Header() http.Header { +	return s.innerWriter.Header() +} + +func (s *statusWraper) Write(b []byte) (int, error) { +	return s.innerWriter.Write(b) +} + +func (s *statusWraper) WriteHeader(statusCode int) { +	s.statusCode = statusCode +	s.innerWriter.WriteHeader(statusCode) +} + +func (s *statusWraper) StatusCode() int { +	if s.statusCode == 0 { +		return 200 +	} +	return s.statusCode +} + +func wrap(w http.ResponseWriter) *statusWraper { +	return &statusWraper{ +		innerWriter: w, +	} +} + +func Log(next http.HandlerFunc) http.HandlerFunc { +	return func(w http.ResponseWriter, r *http.Request) { +		t := time.Now() +		s := wrap(w) +		next(s, r) +		slog.Info( +			"Http request", +			"method", r.Method, +			"code", s.StatusCode(), +			"path", r.URL, +			"elapsed", time.Since(t), +		) +	} +} diff --git a/pkg/ext/router.go b/pkg/ext/router.go new file mode 100644 index 0000000..5d22814 --- /dev/null +++ b/pkg/ext/router.go @@ -0,0 +1,72 @@ +package ext + +import ( +	"errors" +	"fmt" +	"net/http" + +	"git.gabrielgio.me/cerrado/pkg/service" +	"git.gabrielgio.me/cerrado/templates" +) + +type ( +	Router struct { +		middlewares []Middleware +		router      *http.ServeMux +	} +	Middleware          func(next http.HandlerFunc) http.HandlerFunc +	ErrorRequestHandler func(w http.ResponseWriter, r *http.Request) error +) + +func NewRouter() *Router { +	return &Router{ +		router: http.NewServeMux(), +	} +} +func (r *Router) Handler() http.Handler { +	return r.router +} + +func (r *Router) AddMiddleware(middleware Middleware) { +	r.middlewares = append(r.middlewares, middleware) +} + +func wrapError(next ErrorRequestHandler) http.HandlerFunc { +	return func(w http.ResponseWriter, r *http.Request) { +		if err := next(w, r); err != nil { +			if errors.Is(err, service.RepositoryNotFoundErr) { +				NotFound(w) +			} else { +				InternalServerError(w, err) +			} +		} +	} +} + +func (r *Router) run(next ErrorRequestHandler) http.HandlerFunc { +	return func(w http.ResponseWriter, re *http.Request) { +		req := wrapError(next) +		for _, r := range r.middlewares { +			req = r(req) +		} +		req(w, re) +	} +} + +func (r *Router) HandleFunc(path string, handler ErrorRequestHandler) { +	r.router.HandleFunc(path, r.run(handler)) +} + +func NotFound(w http.ResponseWriter) { +	w.WriteHeader(http.StatusNotFound) +	templates.WritePageTemplate(w, &templates.ErrorPage{ +		Message: "Not Found", +	}) +} + +func InternalServerError(w http.ResponseWriter, err error) { +	w.WriteHeader(http.StatusInternalServerError) +	templates.WritePageTemplate(w, &templates.ErrorPage{ +		Message: fmt.Sprintf("Internal Server Error:\n%s", err.Error()), +	}) +} | 
