Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

A free and open-source forge that lives in your Git repo.

Blame · server/forgepaths.go

Line attribution on main · 54 line(s)

ed03b3d1
Keenan Nemetz
2h ago
1 package server
2
3 // The two paths the forge serves that are not pages: a repository's Git
4 // transport at <name>.git/…, and the go command's module discovery probe on a
5 // module path. Both decide from the first path segment alone, so they run before
6 // the mux instead of as routes; a wildcard in a route fills a whole segment, and
7 // neither "<name>.git" nor a module path with a package suffix can be written as
8 // one.
9
10 import (
11 "net/http"
12 "path"
13 "strings"
14
15 "rodent.software/vole/server/githttp"
16 )
17
18 // forgeHandler is the mux with the non-page paths in front of it. It sits inside
19 // the web middleware, so the session, the security headers, the compressor and
20 // the page-view recorder behave exactly as they do for a page.
21 func (s *Server) forgeHandler(next http.Handler) http.Handler {
22 return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
23 if s.gitTransport(rw, r) {
24 return
25 }
26 if s.Web.GoModuleMeta(rw, r) {
27 return
28 }
29 next.ServeHTTP(rw, r)
30 })
31 }
32
33 // gitTransport serves a clone or fetch from <name>.git/…, the URL the clone
34 // menu and the go-import tag advertise. githttp.Route parses that shape; this
35 // only decides whether the request belongs to the transport or to the mux.
36 //
37 // LFS requests are left to the mux: a client asks <name>.git/info/lfs/…, and
38 // those handlers own the batch and object endpoints.
39 func (s *Server) gitTransport(rw http.ResponseWriter, r *http.Request) bool {
40 if s.Proxy == nil || s.Cfg == nil || !s.Cfg.GitHTTP {
41 return false
42 }
43 // An unclean path is the mux's business: it redirects to the cleaned one, and
44 // the transport must not be the one place that skips that check.
45 if path.Clean(r.URL.Path) != r.URL.Path {
46 return false
47 }
48 _, rest, ok := githttp.Route(r.URL.Path)
49 if !ok || rest == "" || strings.HasPrefix(rest, "info/lfs") {
50 return false
51 }
52 s.Proxy.ServeHTTP(rw, r)
53 return true
54 }