I have a small web server written in
Go. I wanted to serve Git repositories from this server. It turned out to be surprisingly easy since
git-http-backend and the
cgi package do all the hard work.
First, define a function for handling Git's HTTP requests:
func git(w http.ResponseWriter, r *http.Request) {
username, password, ok := r.BasicAuth()
if !ok || username != "john" || password != "secret" {
w.Header().Set("Content-Type", "text/plain")
w.Header().Set("WWW-Authenticate", "Basic realm=\"example.com git\"")
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprintln(w, "Not authorized")
return
}
const gitRoot = "/path/to/git/repositories/"
h := &cgi.Handler{
Path: "/usr/lib/git-core/git-http-backend",
Root: "/git",
Dir: gitRoot,
Env: []string{
"GIT_PROJECT_ROOT=" + gitRoot,
"GIT_HTTP_EXPORT_ALL=", // we require auth above
"REMOTE_USER=" + username,
},
}
h.ServeHTTP(w, r)
}
Second, connect that function to the mux you're already using:
mux.HandleFunc("/git/", git)
Now I can clone from and push to my little Go server.
Performing a large "git push" with this setup gives an error like:
ReplyDeleteerror: RPC failed; result=22, HTTP code = 400
That's because Git uses chunked encoding for large uploads but http/cgi doesn't support chunked encoding.
As a workaround, you can run "git config http.postBuffer 2000000" (with a sufficiently large number) before running "git push". That avoids the chunked encoding.