Commit b61e1bf5 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 1cc37d3f
......@@ -34,11 +34,11 @@ type AuthReply struct {
// Entry in authorization reply cache
type AuthCacheEntry struct {
// FIXME we need to lock the entry only to "correctly" update Nhit on
// read side but we can tolerate some looses in Nhit and update it
// read side, but we can tolerate some looses in Nhit and update it
// without mutex or atomic. Only -race complains...
// (we could use atomic.Value for atomic cache entry updates from
// refresher withot need for locks on readers side, but the need to do
// .Nhit++ on readers side ruins that)
// ( we could use atomic.Value for atomic whole cache entry updates from
// refresher withot need for locks on readers side, but the need to do
// .Nhit++ on readers side ruins that )
sync.Mutex
AuthReply
......@@ -54,8 +54,8 @@ type AuthCacheEntry struct {
//
// XXX should be not only project (privateToken etc...)
type AuthCache struct {
mu sync.RWMutex // guards .cached
cached map[string]*AuthCacheEntry
mu sync.RWMutex // guards .cached
cached map[string]*AuthCacheEntry
}
var authCache = AuthCache{cached: make(map[string]*AuthCacheEntry)}
......@@ -98,7 +98,7 @@ have_entry:
goto have_entry
}
// new non-ready entry
// new not-yet-ready entry
auth = &AuthCacheEntry{ready: make(chan struct{})}
c.cached[project] = auth
c.mu.Unlock()
......@@ -135,9 +135,9 @@ func (c *AuthCache) refreshEntry(auth *AuthCacheEntry, u *upstream, project stri
auth.Unlock()
// clear cache entry if it is not used
log.Printf("AUTH refresh - %v #hit: %v", project, nhit)
//log.Printf("AUTH refresh - %v #hit: %v", project, nhit)
if nhit == 0 { // not used - we can remove and stop refreshing
log.Printf("AUTH - removing %v", project)
//log.Printf("AUTH - removing %v", project)
// NOTE it is ok even if someone gets this auth in this time window
// and use it for some time
c.mu.Lock()
......@@ -146,8 +146,7 @@ func (c *AuthCache) refreshEntry(auth *AuthCacheEntry, u *upstream, project stri
break
}
log.Printf("AUTH - refreshing %v", project)
// XXX what if it stucks?
//log.Printf("AUTH - refreshing %v", project)
authReply := askAuthBackend(u, project)
auth.Lock()
......@@ -160,7 +159,7 @@ func (c *AuthCache) refreshEntry(auth *AuthCacheEntry, u *upstream, project stri
// Ask auth backend about whether download is ok for a project.
// Authorization is approved if AuthReply.RepoPath != "" on return
// In case of errors, diagnostic is emitted to AuthReply.RawReply XXX not only diagnostic
// Raw auth backend response is emitted to AuthReply.RawReply
func askAuthBackend(u *upstream, project string) AuthReply {
authReply := AuthReply{
RawReply: httptest.NewRecorder(),
......@@ -169,15 +168,14 @@ func askAuthBackend(u *upstream, project string) AuthReply {
// Request to auth backend to verify whether download is possible via
// asking as `git fetch` would do.
// XXX privateToken not propagated, etc ...
reqDownloadAccess, err := http.NewRequest("GET",
project+".git/info/refs?service=git-upload-pack", nil)
reqDownloadAccess, err := http.NewRequest("GET", project+".git/info/refs?service=git-upload-pack", nil)
if err != nil {
fail500(authReply.RawReply, "GET git-upload-pack", err)
return authReply
}
// prepare everything and go through preAuthorizeHandler() that will send
// request to auth backend and analyze/parse the reply into r.authorizationResponse
// Prepare everything and go through preAuthorizeHandler() that will send
// request to auth backend and analyze/parse the reply into r.authorizationResponse.
// it also logs/emits output in case of errors - we do not have to do it here
r := &gitRequest{
Request: reqDownloadAccess,
......@@ -235,7 +233,6 @@ func handleGetBlobRaw(w http.ResponseWriter, r *gitRequest) {
emitBlob(w, authReply.RepoPath, refpath)
}
// Emit content of blob located at <ref>/path (jointly denoted as 'refpath') to output
func emitBlob(w http.ResponseWriter, repopath string, refpath string) {
// Communicate with `git cat-file --batch` trying refs from longest
......@@ -275,7 +272,6 @@ func emitBlob(w http.ResponseWriter, repopath string, refpath string) {
for i := len(refpathv); i > 0; i-- {
ref := strings.Join(refpathv[:i], "/")
path := strings.Join(refpathv[i:], "/")
//log.Printf("Trying %v %v", ref, path)
_, err := fmt.Fprintf(queryStdin, "%s:%s\n", ref, path)
if err != nil {
fail500(w, "git cat-file --batch; write", err)
......@@ -288,8 +284,6 @@ func emitBlob(w http.ResponseWriter, repopath string, refpath string) {
return
}
//log.Printf("<- %s", reply)
// <object> SP missing LF
if strings.HasSuffix(reply, " missing\n") {
continue
......@@ -304,10 +298,10 @@ func emitBlob(w http.ResponseWriter, repopath string, refpath string) {
if type_ != "blob" {
log.Printf("git cat-file --batch-check; %v is not blob (is %v)", sha1, type_)
sha1 = "" // so it will return 404
sha1 = "" // so it will return 404
}
// so we found this blob object
// git object found
break
}
......@@ -322,7 +316,7 @@ func emitBlob(w http.ResponseWriter, repopath string, refpath string) {
w.Header().Set("Content-Transfer-Encoding", "binary")
w.Header().Set("Content-Length", fmt.Sprintf("%d", size))
w.Header().Set("X-Content-Type-Options", "nosniff")
// net/http sniffs stream and and automatically detects and sets
// net/http sniffs stream and automatically detects and sets
// Content-Type header. We do not have to do it ourselves.
w.Header().Set("Cache-Control", "private") // Rails sets this for IE compatibility
......
......@@ -66,7 +66,6 @@ type gitRequest struct {
// Routing table
var gitServices = [...]gitService{
gitService{"GET", regexp.MustCompile(`/raw/.+\z`), handleGetBlobRaw},
gitService{"GET", regexp.MustCompile(`/info/refs\z`), repoPreAuthorizeHandler(handleGetInfoRefs)},
gitService{"POST", regexp.MustCompile(`/git-upload-pack\z`), repoPreAuthorizeHandler(contentEncodingHandler(handlePostRPC))},
gitService{"POST", regexp.MustCompile(`/git-receive-pack\z`), repoPreAuthorizeHandler(contentEncodingHandler(handlePostRPC))},
......@@ -76,6 +75,7 @@ var gitServices = [...]gitService{
gitService{"GET", regexp.MustCompile(`/repository/archive.tar.gz\z`), repoPreAuthorizeHandler(handleGetArchive)},
gitService{"GET", regexp.MustCompile(`/repository/archive.tar.bz2\z`), repoPreAuthorizeHandler(handleGetArchive)},
gitService{"GET", regexp.MustCompile(`/uploads/`), handleSendFile},
gitService{"GET", regexp.MustCompile(`/raw/.+\z`), handleGetBlobRaw},
// Git LFS
gitService{"PUT", regexp.MustCompile(`/gitlab-lfs/objects/([0-9a-f]{64})/([0-9]+)\z`), lfsAuthorizeHandler(handleStoreLfsObject)},
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment