Skip to content

Commit 08d62c7

Browse files
keegancsmithefritz
andauthored
servegit: decompress input to git-upload-pack (#547)
Ensure that if the Content-Encoding of a servegit request is gzip then we read it as a compressed input. git-upload-pack does not accept gzipped input and fails. This is only sometimes gzipped and I'm not sure of the conditions so we can't rely on it being always or never encoded. This is a port of sourcegraph/sourcegraph 8e1e58c. Co-authored-by: Eric Fritz <eric@sourcegraph.com>
1 parent e5f28d4 commit 08d62c7

File tree

2 files changed

+33
-7
lines changed

2 files changed

+33
-7
lines changed

internal/servegit/service.go

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package servegit
22

33
import (
4+
"compress/gzip"
5+
"fmt"
46
"log"
57
"net/http"
68
"os"
@@ -63,6 +65,20 @@ func (s *gitServiceHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
6365
return
6466
}
6567

68+
body := r.Body
69+
defer body.Close()
70+
71+
if r.Header.Get("Content-Encoding") == "gzip" {
72+
gzipReader, err := gzip.NewReader(body)
73+
if err != nil {
74+
http.Error(w, "malformed payload: "+err.Error(), http.StatusBadRequest)
75+
return
76+
}
77+
defer gzipReader.Close()
78+
79+
body = gzipReader
80+
}
81+
6682
start := time.Now()
6783
defer func() {
6884
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) {
8399
}
84100
args = append(args, dir)
85101

86-
body := r.Body
87-
defer body.Close()
88-
89102
env := os.Environ()
90103
if protocol := r.Header.Get("Git-Protocol"); protocol != "" {
91104
env = append(env, "GIT_PROTOCOL="+protocol)
@@ -96,7 +109,9 @@ func (s *gitServiceHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
96109
cmd.Stdout = w
97110
cmd.Stdin = body
98111
if err := cmd.Run(); err != nil {
99-
http.Error(w, err.Error(), http.StatusInternalServerError)
112+
msg := fmt.Sprintf("error running git service command args=%q: %s", args, err.Error())
113+
s.Debug.Println(msg)
114+
_, _ = w.Write([]byte("\n" + msg + "\n"))
100115
}
101116
}
102117

internal/servegit/service_test.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package servegit
22

33
import (
44
"bytes"
5+
"fmt"
56
"io/ioutil"
67
"net/http/httptest"
78
"os"
@@ -11,15 +12,25 @@ import (
1112
"testing"
1213
)
1314

15+
// numTestCommits determines the number of files/commits/tags to create for
16+
// the local test repo. The value of 25 causes clonev1 and clonev2 to use gzip
17+
// compression but shallow to be uncompressed. The value of 10 does not
18+
// trigger this same behavior.
19+
const numTestCommits = 25
20+
1421
func TestGitServiceHandler(t *testing.T) {
1522
root := tmpDir(t)
1623
repo := filepath.Join(root, "testrepo")
1724

1825
// Setup a repo with a commit so we can add bad refs
1926
runCmd(t, root, "git", "init", repo)
20-
runCmd(t, repo, "sh", "-c", "echo hello world > hello.txt")
21-
runCmd(t, repo, "git", "add", "hello.txt")
22-
runCmd(t, repo, "git", "commit", "-m", "hello")
27+
28+
for i := 0; i < numTestCommits; i++ {
29+
runCmd(t, repo, "sh", "-c", fmt.Sprintf("echo hello world > hello-%d.txt", i+1))
30+
runCmd(t, repo, "git", "add", fmt.Sprintf("hello-%d.txt", i+1))
31+
runCmd(t, repo, "git", "commit", "-m", fmt.Sprintf("c%d", i+1))
32+
runCmd(t, repo, "git", "tag", fmt.Sprintf("v%d", i+1))
33+
}
2334

2435
ts := httptest.NewServer(&gitServiceHandler{
2536
Dir: func(s string) string {

0 commit comments

Comments
 (0)