cerrado @ 3739c9e14b0c65a59a520dbfefa459e43af3bf20

feat: Wrap request

Since request is not a interface I need to create a wraper for it so I
can extend it later.
  1diff --git a/pkg/ext/auth.go b/pkg/ext/auth.go
  2index 5c3070e869de09ec7b6c8239603cf037330085c1..ef126ec7372e7954b5886bd32969312fbecc9fd2 100644
  3--- a/pkg/ext/auth.go
  4+++ b/pkg/ext/auth.go
  5@@ -14,19 +14,20 @@ type authService interface {
  6 	ValidateToken(token []byte) (bool, error)
  7 }
  8 
  9-func DisableAuthentication(next http.HandlerFunc) http.HandlerFunc {
 10-	return func(w http.ResponseWriter, r *http.Request) {
 11+func DisableAuthentication(next HandlerFunc) HandlerFunc {
 12+	return func(w http.ResponseWriter, r *Request) {
 13 		ctx := r.Context()
 14 		ctx = context.WithValue(ctx, "disableAuthentication", true)
 15-		next(w, r.WithContext(ctx))
 16+		r.Request = r.WithContext(ctx)
 17+		next(w, r)
 18 	}
 19 }
 20 
 21 func VerifyRespository(
 22 	config *serverconfig.ConfigurationRepository,
 23-) func(next http.HandlerFunc) http.HandlerFunc {
 24-	return func(next http.HandlerFunc) http.HandlerFunc {
 25-		return func(w http.ResponseWriter, r *http.Request) {
 26+) func(next HandlerFunc) HandlerFunc {
 27+	return func(next HandlerFunc) HandlerFunc {
 28+		return func(w http.ResponseWriter, r *Request) {
 29 			name := r.PathValue("name")
 30 			if name != "" {
 31 				repo := config.GetByName(name)
 32@@ -41,9 +42,9 @@ 		}
 33 	}
 34 }
 35 
 36-func Authenticate(auth authService) func(next http.HandlerFunc) http.HandlerFunc {
 37-	return func(next http.HandlerFunc) http.HandlerFunc {
 38-		return func(w http.ResponseWriter, r *http.Request) {
 39+func Authenticate(auth authService) func(next HandlerFunc) HandlerFunc {
 40+	return func(next HandlerFunc) HandlerFunc {
 41+		return func(w http.ResponseWriter, r *Request) {
 42 			cookie, err := r.Cookie("auth")
 43 			if err != nil {
 44 				if !errors.Is(err, http.ErrNoCookie) {
 45@@ -70,9 +71,10 @@ 			}
 46 
 47 			ctx := r.Context()
 48 			ctx = context.WithValue(ctx, "logged", valid)
 49+			r.Request = r.WithContext(ctx)
 50 
 51 			slog.Info("Validated token", "valid?", valid)
 52-			next(w, r.WithContext(ctx))
 53+			next(w, r)
 54 		}
 55 	}
 56 }
 57diff --git a/pkg/ext/compression.go b/pkg/ext/compression.go
 58index 6c7a219401a031a9bf275adee9b842e4459e978f..d3a3df1bc64ba86d41d0b8924f79c904d4e09a8f 100644
 59--- a/pkg/ext/compression.go
 60+++ b/pkg/ext/compression.go
 61@@ -15,18 +15,37 @@ 	"github.com/andybalholm/brotli"
 62 	"github.com/klauspost/compress/zstd"
 63 )
 64 
 65-var (
 66-	errInvalidParam = errors.New("Invalid weighted param")
 67-)
 68+var errInvalidParam = errors.New("Invalid weighted param")
 69 
 70 type CompressionResponseWriter struct {
 71 	innerWriter    http.ResponseWriter
 72 	compressWriter io.Writer
 73 }
 74 
 75-func Compress(next http.HandlerFunc) http.HandlerFunc {
 76-	return func(w http.ResponseWriter, r *http.Request) {
 77+func Compress(next HandlerFunc) HandlerFunc {
 78+	return func(w http.ResponseWriter, r *Request) {
 79+		// TODO: hand this better
 80+		if strings.HasSuffix(r.URL.Path, ".tar.gz") {
 81+			next(w, r)
 82+			return
 83+		}
 84+
 85+		if accept, ok := r.Header["Accept-Encoding"]; ok {
 86+			if compress, algo := GetCompressionWriter(u.FirstOrZero(accept), w); algo != "" {
 87+				defer compress.Close()
 88+				w.Header().Add("Content-Encoding", algo)
 89+				w = &CompressionResponseWriter{
 90+					innerWriter:    w,
 91+					compressWriter: compress,
 92+				}
 93+			}
 94+		}
 95+		next(w, r)
 96+	}
 97+}
 98 
 99+func Decompress(next http.HandlerFunc) http.HandlerFunc {
100+	return func(w http.ResponseWriter, r *http.Request) {
101 		// TODO: hand this better
102 		if strings.HasSuffix(r.URL.Path, ".tar.gz") {
103 			next(w, r)
104@@ -61,12 +80,12 @@ 		return GetZSTDWriter(inner), c
105 	default:
106 		return nil, ""
107 	}
108-
109 }
110 
111 func (c *CompressionResponseWriter) Header() http.Header {
112 	return c.innerWriter.Header()
113 }
114+
115 func (c *CompressionResponseWriter) Write(b []byte) (int, error) {
116 	return c.compressWriter.Write(b)
117 }
118diff --git a/pkg/ext/log.go b/pkg/ext/log.go
119index 8e681345058d9e9f720928457c953bcc2b0df4bc..e0ad89f4e2a63ded5492d6186b2cfd18cde31de0 100644
120--- a/pkg/ext/log.go
121+++ b/pkg/ext/log.go
122@@ -39,8 +39,8 @@ 		innerWriter: w,
123 	}
124 }
125 
126-func Log(next http.HandlerFunc) http.HandlerFunc {
127-	return func(w http.ResponseWriter, r *http.Request) {
128+func Log(next HandlerFunc) HandlerFunc {
129+	return func(w http.ResponseWriter, r *Request) {
130 		t := time.Now()
131 		s := wrap(w)
132 		next(s, r)
133diff --git a/pkg/ext/request.go b/pkg/ext/request.go
134new file mode 100644
135index 0000000000000000000000000000000000000000..d1593b2453bf93f195f9a8fa355fe5f657a352a6
136--- /dev/null
137+++ b/pkg/ext/request.go
138@@ -0,0 +1,14 @@
139+package ext
140+
141+import (
142+	"io"
143+	"net/http"
144+)
145+
146+type Request struct {
147+	*http.Request
148+}
149+
150+func (r *Request) ReadBody() io.ReadCloser {
151+	return r.Body
152+}
153diff --git a/pkg/ext/router.go b/pkg/ext/router.go
154index 434972b1a4cd545a5b275ae43581678032625c83..bbbffa14136ea5dba83267edb386f66b8a5a5d60 100644
155--- a/pkg/ext/router.go
156+++ b/pkg/ext/router.go
157@@ -16,8 +16,9 @@ 	Router struct {
158 		middlewares []Middleware
159 		router      *http.ServeMux
160 	}
161-	Middleware          func(next http.HandlerFunc) http.HandlerFunc
162-	ErrorRequestHandler func(w http.ResponseWriter, r *http.Request) error
163+	HandlerFunc         func(http.ResponseWriter, *Request)
164+	Middleware          func(next HandlerFunc) HandlerFunc
165+	ErrorRequestHandler func(w http.ResponseWriter, r *Request) error
166 )
167 
168 func NewRouter() *Router {
169@@ -34,15 +35,15 @@ func (r *Router) AddMiddleware(middleware Middleware) {
170 	r.middlewares = append(r.middlewares, middleware)
171 }
172 
173-func wrapError(next ErrorRequestHandler) http.HandlerFunc {
174-	return func(w http.ResponseWriter, r *http.Request) {
175+func wrapError(next ErrorRequestHandler) HandlerFunc {
176+	return func(w http.ResponseWriter, r *Request) {
177 		if err := next(w, r); err != nil {
178 			if errors.Is(err, service.ErrRepositoryNotFound) ||
179 				errors.Is(err, plumbing.ErrReferenceNotFound) {
180 				NotFound(w, r)
181 			} else {
182 				slog.Error("Internal Server Error", "error", err)
183-				InternalServerError(r, w, err)
184+				InternalServerError(w, r, err)
185 			}
186 		}
187 	}
188@@ -54,7 +55,7 @@ 		req := wrapError(next)
189 		for _, r := range r.middlewares {
190 			req = r(req)
191 		}
192-		req(w, re)
193+		req(w, &Request{Request: re})
194 	}
195 }
196 
197@@ -62,14 +63,14 @@ func (r *Router) HandleFunc(path string, handler ErrorRequestHandler) {
198 	r.router.HandleFunc(path, r.run(handler))
199 }
200 
201-func NotFound(w http.ResponseWriter, r *http.Request) {
202+func NotFound(w http.ResponseWriter, r *Request) {
203 	w.WriteHeader(http.StatusNotFound)
204 	templates.WritePageTemplate(w, &templates.ErrorPage{
205 		Message: "Not Found",
206 	}, r.Context())
207 }
208 
209-func BadRequest(w http.ResponseWriter, r *http.Request, msg string) {
210+func BadRequest(w http.ResponseWriter, r *Request, msg string) {
211 	w.WriteHeader(http.StatusBadRequest)
212 	templates.WritePageTemplate(w, &templates.ErrorPage{
213 		Message: msg,
214@@ -81,7 +82,7 @@ 	w.Header().Add("location", location)
215 	w.WriteHeader(http.StatusTemporaryRedirect)
216 }
217 
218-func InternalServerError(r *http.Request, w http.ResponseWriter, err error) {
219+func InternalServerError(w http.ResponseWriter, r *Request, err error) {
220 	w.WriteHeader(http.StatusInternalServerError)
221 	templates.WritePageTemplate(w, &templates.ErrorPage{
222 		Message: fmt.Sprintf("Internal Server Error:\n%s", err.Error()),
223diff --git a/pkg/handler/about/handler.go b/pkg/handler/about/handler.go
224index ee084cd38dc3bf6124cd8e7462005446cfb0222c..b3a1593bab83ca1aaa87a6c63b72c18b0ef82f8a 100644
225--- a/pkg/handler/about/handler.go
226+++ b/pkg/handler/about/handler.go
227@@ -9,6 +9,7 @@ 	"github.com/gomarkdown/markdown"
228 	"github.com/gomarkdown/markdown/html"
229 	"github.com/gomarkdown/markdown/parser"
230 
231+	"git.gabrielgio.me/cerrado/pkg/ext"
232 	"git.gabrielgio.me/cerrado/templates"
233 )
234 
235@@ -26,7 +27,7 @@ func NewAboutHandler(configRepo configurationRepository) *AboutHandler {
236 	return &AboutHandler{configRepo.GetRootReadme()}
237 }
238 
239-func (g *AboutHandler) About(w http.ResponseWriter, r *http.Request) error {
240+func (g *AboutHandler) About(w http.ResponseWriter, r *ext.Request) error {
241 	f, err := os.Open(g.readmePath)
242 	if err != nil {
243 		return err
244diff --git a/pkg/handler/auth/login.go b/pkg/handler/auth/login.go
245index 89fd87b21cb316c68f253ff21a7dcc38a8359fdf..9cc13ccecea15f5504ae1e1005e28bf4e3178c8b 100644
246--- a/pkg/handler/auth/login.go
247+++ b/pkg/handler/auth/login.go
248@@ -26,7 +26,7 @@ 		auth: auth,
249 	}
250 }
251 
252-func (g *LoginHandler) Logout(w http.ResponseWriter, r *http.Request) error {
253+func (g *LoginHandler) Logout(w http.ResponseWriter, r *ext.Request) error {
254 	cookie := &http.Cookie{
255 		Name:    "auth",
256 		Value:   "",
257@@ -44,7 +44,7 @@ 	ext.Redirect(w, referer)
258 	return nil
259 }
260 
261-func (g *LoginHandler) Login(w http.ResponseWriter, r *http.Request) error {
262+func (g *LoginHandler) Login(w http.ResponseWriter, r *ext.Request) error {
263 	referer := r.URL.Query().Get("referer")
264 
265 	// if query value is empty tries to get from header
266diff --git a/pkg/handler/git/handler.go b/pkg/handler/git/handler.go
267index e409ed719abfd178be266731832d7469075ef611..cb202a2e0a5a5409454f72d82c7da4f28449c243 100644
268--- a/pkg/handler/git/handler.go
269+++ b/pkg/handler/git/handler.go
270@@ -48,7 +48,7 @@ 		config:     confRepo,
271 	}
272 }
273 
274-func (g *GitHandler) List(w http.ResponseWriter, r *http.Request) error {
275+func (g *GitHandler) List(w http.ResponseWriter, r *ext.Request) error {
276 	// this is the only handler that needs to handle authentication itself.
277 	// everything else relay on name path parameter
278 	logged := ext.IsLoggedIn(r.Context())
279@@ -90,7 +90,7 @@ 	templates.WritePageTemplate(w, gitList, r.Context())
280 	return nil
281 }
282 
283-func (g *GitHandler) Archive(w http.ResponseWriter, r *http.Request) error {
284+func (g *GitHandler) Archive(w http.ResponseWriter, r *ext.Request) error {
285 	ext.SetGZip(w)
286 	name := r.PathValue("name")
287 	file := r.PathValue("file")
288@@ -116,7 +116,7 @@
289 	return nil
290 }
291 
292-func (g *GitHandler) Multiplex(w http.ResponseWriter, r *http.Request) error {
293+func (g *GitHandler) Multiplex(w http.ResponseWriter, r *ext.Request) error {
294 	path := r.PathValue("rest")
295 	name := r.PathValue("name")
296 
297@@ -160,7 +160,7 @@
298 	return nil
299 }
300 
301-func (g *GitHandler) Summary(w http.ResponseWriter, r *http.Request) error {
302+func (g *GitHandler) Summary(w http.ResponseWriter, r *ext.Request) error {
303 	ext.SetHTML(w)
304 	name := r.PathValue("name")
305 	ref, err := g.gitService.GetHead(name)
306@@ -200,7 +200,7 @@ 	templates.WritePageTemplate(w, gitList, r.Context())
307 	return nil
308 }
309 
310-func (g *GitHandler) About(w http.ResponseWriter, r *http.Request) error {
311+func (g *GitHandler) About(w http.ResponseWriter, r *ext.Request) error {
312 	ext.SetHTML(w)
313 	name := r.PathValue("name")
314 	ref, err := g.gitService.GetHead(name)
315@@ -244,7 +244,7 @@ 	templates.WritePageTemplate(w, gitList, r.Context())
316 	return nil
317 }
318 
319-func (g *GitHandler) Refs(w http.ResponseWriter, r *http.Request) error {
320+func (g *GitHandler) Refs(w http.ResponseWriter, r *ext.Request) error {
321 	ext.SetHTML(w)
322 	name := r.PathValue("name")
323 
324@@ -275,7 +275,7 @@ 	templates.WritePageTemplate(w, gitList, r.Context())
325 	return nil
326 }
327 
328-func (g *GitHandler) Tree(w http.ResponseWriter, r *http.Request) error {
329+func (g *GitHandler) Tree(w http.ResponseWriter, r *ext.Request) error {
330 	ext.SetHTML(w)
331 	name := r.PathValue("name")
332 	ref := r.PathValue("ref")
333@@ -304,7 +304,7 @@ 	templates.WritePageTemplate(w, gitList, r.Context())
334 	return nil
335 }
336 
337-func (g *GitHandler) Blob(w http.ResponseWriter, r *http.Request) error {
338+func (g *GitHandler) Blob(w http.ResponseWriter, r *ext.Request) error {
339 	ext.SetHTML(w)
340 	name := r.PathValue("name")
341 	ref := r.PathValue("ref")
342@@ -372,7 +372,7 @@ 	templates.WritePageTemplate(w, gitList, r.Context())
343 	return nil
344 }
345 
346-func (g *GitHandler) Log(w http.ResponseWriter, r *http.Request) error {
347+func (g *GitHandler) Log(w http.ResponseWriter, r *ext.Request) error {
348 	ext.SetHTML(w)
349 	name := r.PathValue("name")
350 	ref := r.PathValue("ref")
351@@ -395,7 +395,7 @@ 	templates.WritePageTemplate(w, gitList, r.Context())
352 	return nil
353 }
354 
355-func (g *GitHandler) Ref(w http.ResponseWriter, r *http.Request) error {
356+func (g *GitHandler) Ref(w http.ResponseWriter, r *ext.Request) error {
357 	ext.SetHTML(w)
358 	name := r.PathValue("name")
359 	ref := r.PathValue("ref")
360@@ -417,7 +417,7 @@ 	templates.WritePageTemplate(w, gitList, r.Context())
361 	return nil
362 }
363 
364-func (g *GitHandler) Commit(w http.ResponseWriter, r *http.Request) error {
365+func (g *GitHandler) Commit(w http.ResponseWriter, r *ext.Request) error {
366 	ext.SetHTML(w)
367 	name := r.PathValue("name")
368 	ref := r.PathValue("ref")
369diff --git a/pkg/handler/static/handler.go b/pkg/handler/static/handler.go
370index 361f6900b8266e8ccf0d8aca25b995b91ff3a97c..cdb2ae6d4b81ebc5396a0e6ce9d01bd48a73e2e9 100644
371--- a/pkg/handler/static/handler.go
372+++ b/pkg/handler/static/handler.go
373@@ -16,7 +16,7 @@ 	if err != nil {
374 		return nil, err
375 	}
376 
377-	return func(w http.ResponseWriter, r *http.Request) error {
378+	return func(w http.ResponseWriter, r *ext.Request) error {
379 		var (
380 			f = r.PathValue("file")
381 			e = filepath.Ext(f)
382@@ -24,7 +24,7 @@ 			m = mime.TypeByExtension(e)
383 		)
384 		ext.SetMIME(w, m)
385 		w.Header().Add("Cache-Control", "max-age=31536000")
386-		http.ServeFileFS(w, r, staticFs, f)
387+		http.ServeFileFS(w, r.Request, staticFs, f)
388 		return nil
389 	}, nil
390 }