10690: Add -dump-config to arv-git-httpd, crunch-dispatch-slurm, keep-balance, keep...
[arvados.git] / services / arv-git-httpd / git_handler.go
1 package main
2
3 import (
4         "log"
5         "net"
6         "net/http"
7         "net/http/cgi"
8         "os"
9 )
10
11 // gitHandler is an http.Handler that invokes git-http-backend (or
12 // whatever backend is configured) via CGI, with appropriate
13 // environment variables in place for git-http-backend or
14 // gitolite-shell.
15 type gitHandler struct {
16         cgi.Handler
17 }
18
19 func newGitHandler() http.Handler {
20         const glBypass = "GL_BYPASS_ACCESS_CHECKS"
21         const glHome = "GITOLITE_HTTP_HOME"
22         var env []string
23         path := os.Getenv("PATH")
24         if theConfig.GitoliteHome != "" {
25                 env = append(env,
26                         glHome+"="+theConfig.GitoliteHome,
27                         glBypass+"=1")
28                 path = path + ":" + theConfig.GitoliteHome + "/bin"
29         } else if home, bypass := os.Getenv(glHome), os.Getenv(glBypass); home != "" || bypass != "" {
30                 env = append(env, glHome+"="+home, glBypass+"="+bypass)
31                 log.Printf("DEPRECATED: Passing through %s and %s environment variables. Use GitoliteHome configuration instead.", glHome, glBypass)
32         }
33         env = append(env,
34                 "GIT_PROJECT_ROOT="+theConfig.RepoRoot,
35                 "GIT_HTTP_EXPORT_ALL=",
36                 "SERVER_ADDR="+theConfig.Listen,
37                 "PATH="+path)
38         return &gitHandler{
39                 Handler: cgi.Handler{
40                         Path: theConfig.GitCommand,
41                         Dir:  theConfig.RepoRoot,
42                         Env:  env,
43                         Args: []string{"http-backend"},
44                 },
45         }
46 }
47
48 func (h *gitHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
49         remoteHost, remotePort, err := net.SplitHostPort(r.RemoteAddr)
50         if err != nil {
51                 log.Printf("Internal error: SplitHostPort(r.RemoteAddr==%q): %s", r.RemoteAddr, err)
52                 w.WriteHeader(http.StatusInternalServerError)
53                 return
54         }
55
56         // Copy the wrapped cgi.Handler, so these request-specific
57         // variables don't leak into the next request.
58         handlerCopy := h.Handler
59         handlerCopy.Env = append(handlerCopy.Env,
60                 // In Go1.5 we can skip this, net/http/cgi will do it for us:
61                 "REMOTE_HOST="+remoteHost,
62                 "REMOTE_ADDR="+remoteHost,
63                 "REMOTE_PORT="+remotePort,
64                 // Ideally this would be a real username:
65                 "REMOTE_USER="+r.RemoteAddr,
66         )
67         handlerCopy.ServeHTTP(w, r)
68 }