forked from tangled.org/core
Monorepo for Tangled

knotserver: git: improve protocol handling

- Disable caching of responses as suggested by documentation.
<https://git-scm.com/docs/http-protocol#_smart_server_response>
- Return plain-text errors so the git client will display them.
- Check Content-Type of upload-pack request.

authored by tjh.dev and committed by Tangled 6ec3a3d5 d67e7d07

Changed files
+12 -3
knotserver
+12 -3
knotserver/git.go
··· 39 39 serviceName := r.URL.Query().Get("service") 40 40 switch serviceName { 41 41 case "git-upload-pack": 42 - w.Header().Set("content-type", "application/x-git-upload-pack-advertisement") 42 + w.Header().Set("Content-Type", "application/x-git-upload-pack-advertisement") 43 + w.Header().Set("Connection", "Keep-Alive") 44 + w.Header().Set("Cache-Control", "no-cache, max-age=0, must-revalidate") 43 45 w.WriteHeader(http.StatusOK) 44 46 45 47 if err := cmd.InfoRefs(); err != nil { ··· 59 61 name := chi.URLParam(r, "name") 60 62 repo, err := securejoin.SecureJoin(d.c.Repo.ScanPath, filepath.Join(did, name)) 61 63 if err != nil { 62 - writeError(w, err.Error(), 500) 64 + gitError(w, err.Error(), http.StatusInternalServerError) 63 65 d.l.Error("git: failed to secure join repo path", "handler", "UploadPack", "error", err) 64 66 return 65 67 } 66 68 69 + const expectedContentType = "application/x-git-upload-pack-request" 70 + contentType := r.Header.Get("Content-Type") 71 + if contentType != expectedContentType { 72 + gitError(w, fmt.Sprintf("Expected Content-Type: '%s', but received '%s'.", expectedContentType, contentType), http.StatusUnsupportedMediaType) 73 + } 74 + 67 75 var bodyReader io.ReadCloser = r.Body 68 76 if r.Header.Get("Content-Encoding") == "gzip" { 69 77 gzipReader, err := gzip.NewReader(r.Body) 70 78 if err != nil { 71 - writeError(w, err.Error(), 500) 79 + gitError(w, err.Error(), http.StatusInternalServerError) 72 80 d.l.Error("git: failed to create gzip reader", "handler", "UploadPack", "error", err) 73 81 return 74 82 } ··· 78 86 79 87 w.Header().Set("Content-Type", "application/x-git-upload-pack-result") 80 88 w.Header().Set("Connection", "Keep-Alive") 89 + w.Header().Set("Cache-Control", "no-cache, max-age=0, must-revalidate") 81 90 82 91 d.l.Info("git: executing git-upload-pack", "handler", "UploadPack", "repo", repo) 83 92