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 }