Skip to content

Commit 8b4d2dc

Browse files
author
Asim Aslam
authored
Merge pull request #6 from dokku/master
Chunked responses and env support
2 parents 2837b10 + 5a58016 commit 8b4d2dc

File tree

1 file changed

+61
-9
lines changed

1 file changed

+61
-9
lines changed

git-http-backend.go

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,13 @@ type Service struct {
2323
}
2424

2525
type Config struct {
26-
ProjectRoot string
27-
GitBinPath string
28-
UploadPack bool
29-
ReceivePack bool
26+
AuthPassEnvVar string
27+
AuthUserEnvVar string
28+
DefaultEnv string
29+
ProjectRoot string
30+
GitBinPath string
31+
UploadPack bool
32+
ReceivePack bool
3033
}
3134

3235
type HandlerReq struct {
@@ -38,10 +41,13 @@ type HandlerReq struct {
3841
}
3942

4043
var config Config = Config{
41-
ProjectRoot: "/tmp",
42-
GitBinPath: "/usr/bin/git",
43-
UploadPack: true,
44-
ReceivePack: true,
44+
AuthPassEnvVar: "",
45+
AuthUserEnvVar: "",
46+
DefaultEnv: "",
47+
ProjectRoot: "/tmp",
48+
GitBinPath: "/usr/bin/git",
49+
UploadPack: true,
50+
ReceivePack: true,
4551
}
4652

4753
var services = map[string]Service{
@@ -63,6 +69,9 @@ var (
6369
)
6470

6571
func init() {
72+
flag.StringVar(&config.AuthPassEnvVar, "auth_pass_env_var", config.AuthPassEnvVar, "set an env var to provide the basic auth pass as")
73+
flag.StringVar(&config.AuthUserEnvVar, "auth_user_env_var", config.AuthUserEnvVar, "set an env var to provide the basic auth user as")
74+
flag.StringVar(&config.DefaultEnv, "default_env", config.DefaultEnv, "set the default env")
6675
flag.StringVar(&config.ProjectRoot, "project_root", config.ProjectRoot, "set project root")
6776
flag.StringVar(&config.GitBinPath, "git_bin_path", config.GitBinPath, "set git bin path")
6877
flag.StringVar(&address, "server_address", address, "set server address")
@@ -117,15 +126,35 @@ func serviceRpc(hr HandlerReq) {
117126
}
118127

119128
w.Header().Set("Content-Type", fmt.Sprintf("application/x-git-%s-result", rpc))
129+
w.Header().Set("Connection", "Keep-Alive")
130+
w.Header().Set("Transfer-Encoding", "chunked")
131+
w.Header().Set("X-Content-Type-Options", "nosniff")
120132
w.WriteHeader(http.StatusOK)
121133

134+
env := []string{}
135+
136+
if config.DefaultEnv != "" {
137+
env = append(env, config.DefaultEnv)
138+
}
139+
140+
user, password, authok := r.BasicAuth()
141+
if authok {
142+
if config.AuthUserEnvVar != "" {
143+
env = append(env, fmt.Sprintf("%s=%s", config.AuthUserEnvVar, user))
144+
}
145+
if config.AuthPassEnvVar != "" {
146+
env = append(env, fmt.Sprintf("%s=%s", config.AuthPassEnvVar, password))
147+
}
148+
}
149+
122150
args := []string{rpc, "--stateless-rpc", dir}
123151
cmd := exec.Command(config.GitBinPath, args...)
124152
version := r.Header.Get("Git-Protocol")
125153
if len(version) != 0 {
126154
cmd.Env = append(os.Environ(), fmt.Sprintf("GIT_PROTOCOL=%s", version))
127155
}
128156
cmd.Dir = dir
157+
cmd.Env = env
129158
in, err := cmd.StdinPipe()
130159
if err != nil {
131160
log.Print(err)
@@ -151,7 +180,30 @@ func serviceRpc(hr HandlerReq) {
151180
}
152181
io.Copy(in, reader)
153182
in.Close()
154-
io.Copy(w, stdout)
183+
184+
flusher, ok := w.(http.Flusher)
185+
if !ok {
186+
panic("expected http.ResponseWriter to be an http.Flusher")
187+
}
188+
189+
p := make([]byte, 1024)
190+
for {
191+
n_read, err := stdout.Read(p)
192+
if err == io.EOF {
193+
break
194+
}
195+
n_write, err := w.Write(p[:n_read])
196+
if err != nil {
197+
fmt.Println(err)
198+
os.Exit(1)
199+
}
200+
if n_read != n_write {
201+
fmt.Printf("failed to write data: %d read, %d written\n", n_read, n_write)
202+
os.Exit(1)
203+
}
204+
flusher.Flush()
205+
}
206+
155207
cmd.Wait()
156208
}
157209

0 commit comments

Comments
 (0)