func (h *gitHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { var g gitService if r.URL.Path == status.Path { status.HealthyHandler.ServeHTTP(w, r) return } // Look for a matching Git service foundService := false for _, g = range gitServices { if r.Method == g.method && strings.HasSuffix(r.URL.Path, g.suffix) { foundService = true break } } name := strings.TrimSuffix(strings.TrimPrefix(strings.TrimSuffix(r.URL.Path, g.suffix), "/"), ".git") if !foundService || !utils.AppNamePattern.MatchString(name) { // The protocol spec in git/Documentation/technical/http-protocol.txt // says we must return 403 if no matching service is found. http.Error(w, "Forbidden", 403) return } _, password, _ := utils.ParseBasicAuth(r.Header) if !hmac.Equal([]byte(password), h.authKey) { w.Header().Set("WWW-Authenticate", "Basic") http.Error(w, "Authentication required", 401) return } // Lookup app app, err := h.controller.GetApp(name) if err == controller.ErrNotFound { http.Error(w, "unknown app", 404) return } else if err != nil { fail500(w, "getApp", err) return } repoPath, err := prepareRepo(app.ID) if err != nil { fail500(w, "prepareRepo", err) return } defer os.RemoveAll(repoPath) if g.rpc == "git-receive-pack" { defer func() { if err := uploadRepo(repoPath, app.ID); err != nil { logError(w, "uploadRepo", err) } }() } g.handleFunc(gitEnv{App: app.ID}, g.rpc, repoPath, w, r) }
func (s *statusHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if s.k != "" { var addr string if fwdFor := r.Header.Get("X-Forwarded-For"); fwdFor != "" { if v := strings.Split(fwdFor, ", "); len(v) > 0 { addr = strings.TrimSpace(v[len(v)-1]) } } if addr == "" { if clientIP, _, err := net.SplitHostPort(r.RemoteAddr); err == nil { addr = clientIP } } var authed bool if ip := net.ParseIP(addr); ip != nil { for _, v := range s.whitelist { if v.Contains(ip) { authed = true break } } } if !authed { _, password, _ := utils.ParseBasicAuth(r.Header) if password == "" { password = r.URL.Query().Get("key") } authed = len(password) == len(s.k) && subtle.ConstantTimeCompare([]byte(password), []byte(s.k)) == 1 } if !authed { w.WriteHeader(401) return } } s.h.ServeHTTP(w, r) }