switch to atreugo
1 file changed, 176 insertions(+), 186 deletions(-)
changed files
M routes/routes.go → routes/routes.go
@@ -4,7 +4,6 @@ import ( "compress/gzip" "fmt" "log" - "net/http" "path" "path/filepath" "strconv"@@ -15,6 +14,8 @@ "alin.ovh/elgit/git" "alin.ovh/elgit/templates" "github.com/microcosm-cc/bluemonday" "github.com/russross/blackfriday/v2" + "github.com/savsgio/atreugo/v11" + "github.com/valyala/fasthttp" ) type deps struct {@@ -22,49 +23,41 @@ c *config.Config projects []string } -func (d *deps) Index(w http.ResponseWriter, _ *http.Request, _ map[string]string) { +func (d *deps) Index(rc *atreugo.RequestCtx) error { repos := d.getAllRepos() pageData := templates.PageData{ Meta: d.c.Meta, } - if err := templates.IndexPage(pageData, repos).Render(w); err != nil { - log.Println(err) + rc.SetContentType("text/html; charset=utf-8") - return - } + return templates.IndexPage(pageData, repos).Render(rc) } -func (d *deps) RepoIndex(w http.ResponseWriter, _ *http.Request, params map[string]string) { - name := path.Join(params["category"], params["name"]) +func (d *deps) RepoIndex(rc *atreugo.RequestCtx) error { + category, _ := rc.UserValue("category").(string) + name, _ := rc.UserValue("name").(string) + repoName := path.Join(category, name) - if d.isNotAllowed(name) { - d.Write404(w) - - return + if d.isNotAllowed(repoName) { + return ErrNotFound } - path, err := d.GetCleanPath(name) + path, err := d.GetCleanPath(repoName) if err != nil { log.Printf("getcleanpath error: %v", err) - d.Write404(w) - return + return ErrNotFound } gr, err := git.Open(path, "") if err != nil { - d.Write404(w) - - return + return ErrNotFound } commits, err := gr.Commits() if err != nil { - d.Write500(w) - log.Println(err) - - return + return err } var readmeContent string@@ -91,10 +84,7 @@ } mainBranch, err := gr.FindMainBranch(d.c.Repo.MainBranch) if err != nil { - d.Write500(w) - log.Println(err) - - return + return err } if len(commits) >= 3 {@@ -103,151 +93,144 @@ } pageData := templates.PageData{ Meta: d.c.Meta, - Name: name, - DisplayName: getDisplayName(name), + Name: repoName, + DisplayName: getDisplayName(repoName), Ref: mainBranch, Description: getDescription(path), Servername: d.c.Server.Name, Gomod: isGoModule(gr), } - if err := templates.RepoPage(pageData, commits, readmeContent).Render(w); err != nil { - log.Println(err) - } + rc.SetContentType("text/html; charset=utf-8") + + return templates.RepoPage(pageData, commits, readmeContent).Render(rc) } -func (d *deps) RepoTree(w http.ResponseWriter, _ *http.Request, params map[string]string) { - name := path.Join(params["category"], params["name"]) - if d.isNotAllowed(name) { - d.Write404(w) +func (d *deps) RepoTree(rc *atreugo.RequestCtx) error { + category, _ := rc.UserValue("category").(string) + name, _ := rc.UserValue("name").(string) + repoName := path.Join(category, name) - return + if d.isNotAllowed(repoName) { + return ErrNotFound } - treePath := strings.TrimSuffix(params["rest"], "/") - ref := params["ref"] + + rest, _ := rc.UserValue("rest").(string) + treePath := strings.TrimSuffix(rest, "/") + ref := rc.UserValue("ref").(string) - path, err := d.GetCleanPath(name) + path, err := d.GetCleanPath(repoName) if err != nil { log.Printf("getcleanpath error: %v", err) - d.Write404(w) - return + return ErrNotFound } gr, err := git.Open(path, ref) if err != nil { - d.Write404(w) - - return + return err } files, err := gr.FileTree(treePath) if err != nil { - d.Write500(w) - log.Println(err, treePath) - - return + return err } data := make(map[string]any) - data["name"] = name - data["displayname"] = getDisplayName(name) + data["name"] = repoName + data["displayname"] = getDisplayName(repoName) data["ref"] = ref data["parent"] = treePath data["desc"] = getDescription(path) data["dotdot"] = filepath.Dir(treePath) - d.listFiles(files, data, w) + rc.SetContentType("text/html; charset=utf-8") + + return d.listFiles(files, data, rc) } -func (d *deps) FileContent(w http.ResponseWriter, r *http.Request, params map[string]string) { +func (d *deps) FileContent(rc *atreugo.RequestCtx) error { var raw bool - if rawParam, err := strconv.ParseBool(r.URL.Query().Get("raw")); err == nil { + if rawParam, err := strconv.ParseBool(string(rc.Request.URI().QueryArgs().Peek("raw"))); err == nil { raw = rawParam } - name := path.Join(params["category"], params["name"]) - if d.isNotAllowed(name) { - d.Write404(w) + category, _ := rc.UserValue("category").(string) + name, _ := rc.UserValue("name").(string) + repoName := path.Join(category, name) - return + if d.isNotAllowed(repoName) { + return ErrNotFound } - treePath := params["rest"] - ref := params["ref"] + treePath := rc.UserValue("rest").(string) + ref := rc.UserValue("ref").(string) - path, err := d.GetCleanPath(name) + path, err := d.GetCleanPath(repoName) if err != nil { log.Printf("getcleanpath error: %v", err) - d.Write404(w) - return + return ErrNotFound } gr, err := git.Open(path, ref) if err != nil { - d.Write404(w) - - return + return ErrNotFound } contents, err := gr.FileContent(treePath) if err != nil { - d.Write500(w) - - return + return err } data := make(map[string]any) - data["name"] = name - data["displayname"] = getDisplayName(name) + data["name"] = repoName + data["displayname"] = getDisplayName(repoName) data["ref"] = ref data["desc"] = getDescription(path) data["path"] = treePath if raw { - d.showRaw(contents, w) - } else { - d.showFile(contents, data, w) + return rc.TextResponse(contents) } + + rc.SetContentType("text/html; charset=utf-8") + + return d.showFile(contents, data, rc) } -func (d *deps) Archive(w http.ResponseWriter, _ *http.Request, params map[string]string) { - name := path.Join(params["category"], params["name"]) - if d.isNotAllowed(name) { - d.Write404(w) +func (d *deps) Archive(rc *atreugo.RequestCtx) error { + category, _ := rc.UserValue("category").(string) + name, _ := rc.UserValue("name").(string) + repoName := path.Join(category, name) - return + if d.isNotAllowed(repoName) { + return ErrNotFound } - file := params["file"] + file := rc.UserValue("file").(string) if !strings.HasSuffix(file, ".tar.gz") { - d.Write404(w) - - return + return ErrNotFound } ref := strings.TrimSuffix(file, ".tar.gz") // This allows the browser to use a proper name for the file when downloading - filename := fmt.Sprintf("%s-%s.tar.gz", name, ref) - setContentDisposition(w, filename) - setGZipMIME(w) + filename := fmt.Sprintf("%s-%s.tar.gz", repoName, ref) + setContentDisposition(rc, filename) + setGZipMIME(rc) - path, err := d.GetCleanPath(name) + path, err := d.GetCleanPath(repoName) if err != nil { log.Printf("getcleanpath error: %v", err) - d.Write404(w) - return + return ErrNotFound } gr, err := git.Open(path, ref) if err != nil { - d.Write404(w) - - return + return ErrNotFound } - gw := gzip.NewWriter(w) + gw := gzip.NewWriter(rc) defer func() { err := gw.Close() if err != nil {@@ -255,14 +238,14 @@ log.Printf("failed to close gzip writer: %s", err) } }() - prefix := fmt.Sprintf("%s-%s", name, ref) + prefix := fmt.Sprintf("%s-%s", repoName, ref) err = gr.WriteTar(gw, prefix) if err != nil { // once we start writing to the body we can't report error anymore // so we are only left with printing the error. log.Println(err) - return + return nil } err = gw.Flush()@@ -270,179 +253,154 @@ if err != nil { // once we start writing to the body we can't report error anymore // so we are only left with printing the error. log.Println(err) + } - return - } + return nil } -func (d *deps) Log(w http.ResponseWriter, _ *http.Request, params map[string]string) { - name := path.Join(params["category"], params["name"]) - if d.isNotAllowed(name) { - d.Write404(w) +func (d *deps) Log(rc *atreugo.RequestCtx) error { + category, _ := rc.UserValue("category").(string) + name, _ := rc.UserValue("name").(string) + repoName := path.Join(category, name) - return + if d.isNotAllowed(repoName) { + return ErrNotFound } - ref := params["ref"] + ref := rc.UserValue("ref").(string) - path, err := d.GetCleanPath(name) + path, err := d.GetCleanPath(repoName) if err != nil { log.Printf("getcleanpath error: %v", err) - d.Write404(w) - return + return ErrNotFound } gr, err := git.Open(path, ref) if err != nil { - d.Write404(w) - - return + return ErrNotFound } commits, err := gr.Commits() if err != nil { - d.Write500(w) - log.Println(err) - - return + return err } pageData := templates.PageData{ Meta: d.c.Meta, - Name: name, - DisplayName: getDisplayName(name), + Name: repoName, + DisplayName: getDisplayName(repoName), Ref: ref, Description: getDescription(path), Log: true, } - if err := templates.LogPage(pageData, commits).Render(w); err != nil { - log.Println(err) + rc.SetContentType("text/html; charset=utf-8") - return - } + return templates.LogPage(pageData, commits).Render(rc) } -func (d *deps) Diff(w http.ResponseWriter, _ *http.Request, params map[string]string) { - name := path.Join(params["category"], params["name"]) - if d.isNotAllowed(name) { - d.Write404(w) +func (d *deps) Diff(rc *atreugo.RequestCtx) error { + category, _ := rc.UserValue("category").(string) + name, _ := rc.UserValue("name").(string) + repoName := path.Join(category, name) - return + if d.isNotAllowed(repoName) { + return ErrNotFound } - ref := params["ref"] + ref := rc.UserValue("ref").(string) - path, err := d.GetCleanPath(name) + path, err := d.GetCleanPath(repoName) if err != nil { log.Printf("getcleanpath error: %v", err) - d.Write404(w) - return + return ErrNotFound } gr, err := git.Open(path, ref) if err != nil { - d.Write404(w) - - return + return ErrNotFound } diff, err := gr.Diff() if err != nil { - d.Write500(w) - log.Println(err) - - return + return err } pageData := templates.PageData{ Meta: d.c.Meta, - Name: name, + Name: repoName, Stat: diff.Stat, Diff: diff.Diff, - DisplayName: getDisplayName(name), + DisplayName: getDisplayName(repoName), Ref: ref, Description: getDescription(path), } - if err := templates.CommitPage(pageData, diff).Render(w); err != nil { - log.Println(err) + rc.SetContentType("text/html; charset=utf-8") - return - } + return templates.CommitPage(pageData, diff).Render(rc) } // FileDiff shows the changes to a specific file in a commit -func (d *deps) FileDiff(w http.ResponseWriter, _ *http.Request, params map[string]string) { - name := path.Join(params["category"], params["name"]) - if d.isNotAllowed(name) { - d.Write404(w) +func (d *deps) FileDiff(rc *atreugo.RequestCtx) error { + category, _ := rc.UserValue("category").(string) + name, _ := rc.UserValue("name").(string) + repoName := path.Join(category, name) - return + if d.isNotAllowed(repoName) { + return ErrNotFound } - ref := params["ref"] - filePath := strings.TrimSuffix(params["file"], "/") + ref := rc.UserValue("ref").(string) + filePath := strings.TrimSuffix(rc.UserValue("file").(string), "/") - path, err := d.GetCleanPath(name) + path, err := d.GetCleanPath(repoName) if err != nil { log.Printf("getcleanpath error: %v", err) - d.Write404(w) - return + return ErrNotFound } g, err := git.Open(path, ref) if err != nil { - log.Printf("git open error: %v", err) - d.Write404(w) - - return + return err } diff, err := g.DiffFile(filePath) if err != nil { - log.Printf("git diff error: %v", err) - d.Write500(w) - - return + return err } pageData := templates.PageData{ Meta: d.c.Meta, - DisplayName: getDisplayName(name), - Name: name, + DisplayName: getDisplayName(repoName), + Name: repoName, Ref: ref, Description: getDescription(path), Path: filePath, Diff: diff.Diff, } - if err := templates.CommitPage(pageData, diff).Render(w); err != nil { - log.Printf("diff template: %s", err) - d.Write500(w) - } + rc.SetContentType("text/html; charset=utf-8") + + return templates.CommitPage(pageData, diff).Render(rc) } -func (d *deps) Refs(w http.ResponseWriter, _ *http.Request, params map[string]string) { - name := path.Join(params["category"], params["name"]) - if d.isNotAllowed(name) { - d.Write404(w) +func (d *deps) Refs(rc *atreugo.RequestCtx) error { + category, _ := rc.UserValue("category").(string) + name, _ := rc.UserValue("name").(string) + repoName := path.Join(category, name) - return + if d.isNotAllowed(repoName) { + return ErrNotFound } - path, err := d.GetCleanPath(name) + path, err := d.GetCleanPath(repoName) if err != nil { - log.Printf("getcleanpath error: %v", err) - d.Write404(w) - - return + return err } gr, err := git.Open(path, "") if err != nil { - d.Write404(w) - - return + return ErrNotFound } tags, err := gr.Tags()@@ -453,22 +411,54 @@ } branches, err := gr.Branches() if err != nil { - log.Println(err) - d.Write500(w) - - return + return err } pageData := templates.PageData{ Meta: d.c.Meta, - Name: name, - DisplayName: getDisplayName(name), + Name: repoName, + DisplayName: getDisplayName(repoName), Description: getDescription(path), } - if err := templates.RefsPage(pageData, branches, tags).Render(w); err != nil { - log.Println(err) + rc.SetContentType("text/html; charset=utf-8") + + return templates.RefsPage(pageData, branches, tags).Render(rc) +} + +func (d *deps) NotFound(rc *atreugo.RequestCtx) error { + log.Printf("Not found: %s", rc.Request.URI().RequestURI()) + + return ErrNotFound +} + +func (d *deps) Error(rc *atreugo.RequestCtx, cause error, statusCode int) { + log.Printf("Error: %v", cause) + + var err error + if rc.Request.Header.HasAcceptEncoding("text/html") { + rc.SetContentType("text/html; charset=utf-8") + + err = templates.ErrorPage(templates.PageData{ + Error: &templates.Error{ + Code: statusCode, + Message: cause.Error(), + }, + }).Render(rc) + } else { + err = rc.TextResponse(cause.Error(), statusCode) + } - return + if err != nil { + log.Printf("error response error: %v", err) + } +} + +func (d *deps) Panic(rc *atreugo.RequestCtx, data any) { + switch data := data.(type) { + case string, []byte: + d.Error(rc, fmt.Errorf("panic: %s", data), fasthttp.StatusInternalServerError) + case error: + d.Error(rc, fmt.Errorf("panic: %w", data), fasthttp.StatusInternalServerError) } }