package routes import ( "log" "net/http" "os" "path" "slices" "strings" "github.com/dimfeld/httptreemux/v5" "go.alanpearce.eu/elgit/config" ) // Checks for gitprotocol-http(5) specific smells; if found, passes // the request on to the git http service, else render the web frontend. func (d *deps) Multiplex(w http.ResponseWriter, r *http.Request, params map[string]string) { rest := params["rest"] switch params["name"] { case "info", "git-upload-pack": rest = path.Join(params["name"], params["rest"]) params["name"] = params["category"] params["category"] = "" } if d.isNotAllowed(path.Join(params["category"], params["name"])) { d.Write404(w) return } if r.URL.RawQuery == "service=git-receive-pack" { w.WriteHeader(http.StatusBadRequest) _, err := w.Write([]byte("no pushing allowed!")) if err != nil { log.Println(err) d.Write500(w) return } return } if rest == "info/refs" && r.URL.RawQuery == "service=git-upload-pack" && r.Method == "GET" { d.InfoRefs(w, r, params) } else if rest == "git-upload-pack" && r.Method == "POST" { d.UploadPack(w, r, params) } else if r.Method == "GET" { d.RepoIndex(w, r, params) } } func Handlers(c *config.Config) *httptreemux.TreeMux { mux := httptreemux.New() projects, err := ReadProjectsList(c) if err != nil { log.Fatal(err) } d := deps{ c, projects, } categories := []string{} for _, project := range projects { if cat, _, found := strings.Cut(project, string(os.PathSeparator)); found { categories = append(categories, cat) } } categories = slices.Compact(categories) mux.NotFoundHandler = func(w http.ResponseWriter, r *http.Request) { d.Write404(w) } mux.RedirectTrailingSlash = false mux.GET("/", d.Index) mux.GET("/static/:file", d.ServeStatic) mux.GET("/:name/tree/:ref/*rest", d.RepoTree) mux.GET("/:name/blob/:ref/*rest", d.FileContent) mux.GET("/:name/tree/:ref/", d.RepoTree) mux.GET("/:name/blob/:ref/", d.FileContent) mux.GET("/:name/log/:ref", d.Log) mux.GET("/:name/archive/:file", d.Archive) mux.GET("/:name/commit/:ref", d.Diff) mux.GET("/:name/refs/", d.Refs) mux.GET("/:name", d.Multiplex) mux.POST("/:name", d.Multiplex) mux.GET("/:name/", d.Multiplex) mux.POST("/:name/", d.Multiplex) mux.GET("/:name/*rest", d.Multiplex) mux.POST("/:name/*rest", d.Multiplex) mux.GET("/:category/:name/tree/:ref/*rest", d.RepoTree) mux.GET("/:category/:name/blob/:ref/*rest", d.FileContent) mux.GET("/:category/:name/tree/:ref/", d.RepoTree) mux.GET("/:category/:name/blob/:ref/", d.FileContent) mux.GET("/:category/:name/log/:ref", d.Log) mux.GET("/:category/:name/archive/:file", d.Archive) mux.GET("/:category/:name/commit/:ref", d.Diff) mux.GET("/:category/:name/refs/", d.Refs) mux.GET("/:category/:name", d.Multiplex) mux.POST("/:category/:name", d.Multiplex) mux.GET("/:category/:name/", d.Multiplex) mux.POST("/:category/:name/", d.Multiplex) mux.GET("/:category/:name/*rest", d.Multiplex) mux.POST("/:category/:name/*rest", d.Multiplex) return mux }