X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/d2e546749afaa1ff8fff8cb920b9a54d58154b76..918e16de43e993894dcaffbe0cafa0fc1d2f16b3:/services/arv-git-httpd/auth_handler.go diff --git a/services/arv-git-httpd/auth_handler.go b/services/arv-git-httpd/auth_handler.go index ebda2a4a9b..9f92cd1b72 100644 --- a/services/arv-git-httpd/auth_handler.go +++ b/services/arv-git-httpd/auth_handler.go @@ -3,53 +3,44 @@ package main import ( "log" "net/http" - "net/http/cgi" "os" "strings" "sync" "time" - "git.curoverse.com/arvados.git/sdk/go/auth" "git.curoverse.com/arvados.git/sdk/go/arvadosclient" + "git.curoverse.com/arvados.git/sdk/go/auth" + "git.curoverse.com/arvados.git/sdk/go/httpserver" ) -func newArvadosClient() interface{} { - arv, err := arvadosclient.MakeArvadosClient() - if err != nil { - log.Println("MakeArvadosClient:", err) - return nil - } - return &arv -} - -var connectionPool = &sync.Pool{New: newArvadosClient} - -type spyingResponseWriter struct { - http.ResponseWriter - wroteStatus *int -} - -func (w spyingResponseWriter) WriteHeader(s int) { - *w.wroteStatus = s - w.ResponseWriter.WriteHeader(s) +type authHandler struct { + handler http.Handler + clientPool *arvadosclient.ClientPool + setupOnce sync.Once } -type authHandler struct { - handler *cgi.Handler +func (h *authHandler) setup() { + ac, err := arvadosclient.New(&theConfig.Client) + if err != nil { + log.Fatal(err) + } + h.clientPool = &arvadosclient.ClientPool{Prototype: ac} + log.Printf("%+v", h.clientPool.Prototype) } func (h *authHandler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) { + h.setupOnce.Do(h.setup) + var statusCode int var statusText string var apiToken string var repoName string - var wroteStatus int var validApiToken bool - w := spyingResponseWriter{wOrig, &wroteStatus} + w := httpserver.WrapResponseWriter(wOrig) defer func() { - if wroteStatus == 0 { + if w.WroteStatus() == 0 { // Nobody has called WriteHeader yet: that // must be our job. w.WriteHeader(statusCode) @@ -67,7 +58,7 @@ func (h *authHandler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) { passwordToLog = apiToken[0:10] } - log.Println(quoteStrings(r.RemoteAddr, passwordToLog, wroteStatus, statusText, repoName, r.Method, r.URL.Path)...) + httpserver.Log(r.RemoteAddr, passwordToLog, w.WroteStatus(), statusText, repoName, r.Method, r.URL.Path) }() creds := auth.NewCredentialsFromHTTPRequest(r) @@ -89,12 +80,12 @@ func (h *authHandler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) { repoName = pathParts[0] repoName = strings.TrimRight(repoName, "/") - arv, ok := connectionPool.Get().(*arvadosclient.ArvadosClient) - if !ok || arv == nil { - statusCode, statusText = http.StatusInternalServerError, "connection pool failed" + arv := h.clientPool.Get() + if arv == nil { + statusCode, statusText = http.StatusInternalServerError, "connection pool failed: "+h.clientPool.Err().Error() return } - defer connectionPool.Put(arv) + defer h.clientPool.Put(arv) // Ask API server whether the repository is readable using // this token (by trying to read it!) @@ -150,7 +141,7 @@ func (h *authHandler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) { "/" + repoName + "/.git", } for _, dir := range tryDirs { - if fileInfo, err := os.Stat(theConfig.Root + dir); err != nil { + if fileInfo, err := os.Stat(theConfig.RepoRoot + dir); err != nil { if !os.IsNotExist(err) { statusCode, statusText = http.StatusInternalServerError, err.Error() return @@ -162,7 +153,7 @@ func (h *authHandler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) { } if rewrittenPath == "" { log.Println("WARNING:", repoUUID, - "git directory not found in", theConfig.Root, tryDirs) + "git directory not found in", theConfig.RepoRoot, tryDirs) // We say "content not found" to disambiguate from the // earlier "API says that repo does not exist" error. statusCode, statusText = http.StatusNotFound, "content not found" @@ -170,20 +161,5 @@ func (h *authHandler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) { } r.URL.Path = rewrittenPath - handlerCopy := *h.handler - handlerCopy.Env = append(handlerCopy.Env, "REMOTE_USER="+r.RemoteAddr) // Should be username - handlerCopy.ServeHTTP(&w, r) -} - -var escaper = strings.NewReplacer("\"", "\\\"", "\\", "\\\\", "\n", "\\n") - -// Transform strings so they are safer to write in logs (e.g., -// 'foo"bar' becomes '"foo\"bar"'). Non-string args are left alone. -func quoteStrings(args ...interface{}) []interface{} { - for i, arg := range args { - if s, ok := arg.(string); ok { - args[i] = "\"" + escaper.Replace(s) + "\"" - } - } - return args + h.handler.ServeHTTP(&w, r) }