Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-workhorse
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kirill Smelkov
gitlab-workhorse
Commits
b61e1bf5
Commit
b61e1bf5
authored
Dec 04, 2015
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
1cc37d3f
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
18 additions
and
24 deletions
+18
-24
blob.go
blob.go
+17
-23
upstream.go
upstream.go
+1
-1
No files found.
blob.go
View file @
b61e1bf5
...
...
@@ -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 no
n
-ready entry
// new no
t-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
}
//
p
repare everything and go through preAuthorizeHandler() that will send
// request to auth backend and analyze/parse the reply into r.authorizationResponse
//
P
repare 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 a
nd a
utomatically 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
...
...
upstream.go
View file @
b61e1bf5
...
...
@@ -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
)},
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment