diff --git a/internal/servegit/service.go b/internal/servegit/service.go index d7baafa92d..80acaaa520 100644 --- a/internal/servegit/service.go +++ b/internal/servegit/service.go @@ -1,6 +1,8 @@ package servegit import ( + "compress/gzip" + "fmt" "log" "net/http" "os" @@ -63,6 +65,20 @@ func (s *gitServiceHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } + body := r.Body + defer body.Close() + + if r.Header.Get("Content-Encoding") == "gzip" { + gzipReader, err := gzip.NewReader(body) + if err != nil { + http.Error(w, "malformed payload: "+err.Error(), http.StatusBadRequest) + return + } + defer gzipReader.Close() + + body = gzipReader + } + start := time.Now() defer func() { s.Debug.Printf("git service svc=%s protocol=%s repo=%s duration=%v", svc, r.Header.Get("Git-Protocol"), repo, time.Since(start)) @@ -83,9 +99,6 @@ func (s *gitServiceHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } args = append(args, dir) - body := r.Body - defer body.Close() - env := os.Environ() if protocol := r.Header.Get("Git-Protocol"); protocol != "" { env = append(env, "GIT_PROTOCOL="+protocol) @@ -96,7 +109,9 @@ func (s *gitServiceHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { cmd.Stdout = w cmd.Stdin = body if err := cmd.Run(); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + msg := fmt.Sprintf("error running git service command args=%q: %s", args, err.Error()) + s.Debug.Println(msg) + _, _ = w.Write([]byte("\n" + msg + "\n")) } } diff --git a/internal/servegit/service_test.go b/internal/servegit/service_test.go index 8c6fc34be5..08108d9bea 100644 --- a/internal/servegit/service_test.go +++ b/internal/servegit/service_test.go @@ -2,6 +2,7 @@ package servegit import ( "bytes" + "fmt" "io/ioutil" "net/http/httptest" "os" @@ -11,15 +12,25 @@ import ( "testing" ) +// numTestCommits determines the number of files/commits/tags to create for +// the local test repo. The value of 25 causes clonev1 and clonev2 to use gzip +// compression but shallow to be uncompressed. The value of 10 does not +// trigger this same behavior. +const numTestCommits = 25 + func TestGitServiceHandler(t *testing.T) { root := tmpDir(t) repo := filepath.Join(root, "testrepo") // Setup a repo with a commit so we can add bad refs runCmd(t, root, "git", "init", repo) - runCmd(t, repo, "sh", "-c", "echo hello world > hello.txt") - runCmd(t, repo, "git", "add", "hello.txt") - runCmd(t, repo, "git", "commit", "-m", "hello") + + for i := 0; i < numTestCommits; i++ { + runCmd(t, repo, "sh", "-c", fmt.Sprintf("echo hello world > hello-%d.txt", i+1)) + runCmd(t, repo, "git", "add", fmt.Sprintf("hello-%d.txt", i+1)) + runCmd(t, repo, "git", "commit", "-m", fmt.Sprintf("c%d", i+1)) + runCmd(t, repo, "git", "tag", fmt.Sprintf("v%d", i+1)) + } ts := httptest.NewServer(&gitServiceHandler{ Dir: func(s string) string {