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
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-workhorse
Commits
c99c4302
Commit
c99c4302
authored
Nov 10, 2015
by
Marin Jankovski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement changes requested in feedback. Add download object test.
parent
c165c876
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
121 additions
and
105 deletions
+121
-105
lfs.go
lfs.go
+33
-48
main_test.go
main_test.go
+86
-55
upstream.go
upstream.go
+2
-2
No files found.
lfs.go
View file @
c99c4302
...
@@ -13,7 +13,6 @@ import (
...
@@ -13,7 +13,6 @@ import (
"net/http"
"net/http"
"os"
"os"
"path/filepath"
"path/filepath"
"strconv"
)
)
var
(
var
(
...
@@ -34,7 +33,7 @@ func lfsAuthorizeHandler(handleFunc serviceHandleFunc) serviceHandleFunc {
...
@@ -34,7 +33,7 @@ func lfsAuthorizeHandler(handleFunc serviceHandleFunc) serviceHandleFunc {
return
return
}
}
if
r
.
LfsSize
==
""
{
if
r
.
LfsSize
==
0
{
fail500
(
w
,
"lfsAuthorizeHandler"
,
errors
.
New
(
"Lfs object size not specified."
))
fail500
(
w
,
"lfsAuthorizeHandler"
,
errors
.
New
(
"Lfs object size not specified."
))
return
return
}
}
...
@@ -48,62 +47,47 @@ func lfsAuthorizeHandler(handleFunc serviceHandleFunc) serviceHandleFunc {
...
@@ -48,62 +47,47 @@ func lfsAuthorizeHandler(handleFunc serviceHandleFunc) serviceHandleFunc {
}
}
handleFunc
(
w
,
r
)
handleFunc
(
w
,
r
)
},
""
)
},
"
/authorize
"
)
}
}
func
handleStoreLfsObject
(
handleFunc
serviceHandleFunc
)
serviceHandleFunc
{
func
handleStoreLfsObject
(
w
http
.
ResponseWriter
,
r
*
gitRequest
)
{
return
func
(
w
http
.
ResponseWriter
,
r
*
gitRequest
)
{
var
body
io
.
ReadCloser
oid
:=
r
.
LfsOid
size
:=
r
.
LfsSize
var
body
io
.
ReadCloser
body
=
r
.
Body
defer
body
.
Close
()
body
=
r
.
Body
tmpPath
:=
r
.
StoreLFSPath
defer
body
.
Close
()
file
,
err
:=
ioutil
.
TempFile
(
tmpPath
,
r
.
LfsOid
)
if
err
!=
nil
{
tmpPath
:=
r
.
StoreLFSPath
fail500
(
w
,
"Couldn't open tmp file for writing."
,
err
)
file
,
err
:=
ioutil
.
TempFile
(
tmpPath
,
""
)
return
if
err
!=
nil
{
}
fail500
(
w
,
"Couldn't open tmp file for writing."
,
err
)
defer
os
.
Remove
(
tmpPath
)
return
defer
file
.
Close
()
}
defer
os
.
Remove
(
tmpPath
)
defer
file
.
Close
()
hash
:=
sha256
.
New
()
hw
:=
io
.
MultiWriter
(
hash
,
file
)
written
,
err
:=
io
.
Copy
(
hw
,
body
)
if
err
!=
nil
{
fail500
(
w
,
"Failed to save received LFS object."
,
err
)
return
}
file
.
Close
()
sizeInt
,
err
:=
strconv
.
ParseInt
(
size
,
10
,
64
)
hash
:=
sha256
.
New
()
if
err
!=
nil
{
hw
:=
io
.
MultiWriter
(
hash
,
file
)
fail500
(
w
,
"Couldn't read size: "
,
err
)
return
}
if
written
!=
sizeInt
{
written
,
err
:=
io
.
Copy
(
hw
,
body
)
fail500
(
w
,
"Inconsistent size: "
,
errSizeMismatch
)
if
err
!=
nil
{
return
fail500
(
w
,
"Failed to save received LFS object."
,
err
)
}
return
}
file
.
Close
()
shaStr
:=
hex
.
EncodeToString
(
hash
.
Sum
(
nil
))
if
written
!=
r
.
LfsSize
{
if
shaStr
!=
oid
{
fail500
(
w
,
"Inconsistent size: "
,
errSizeMismatch
)
fail500
(
w
,
"Inconsistent size: "
,
errSizeMismatch
)
return
return
}
}
r
.
Header
.
Set
(
"X-GitLab-Lfs-Tmp"
,
filepath
.
Base
(
file
.
Name
()))
handleFunc
(
w
,
r
)
shaStr
:=
hex
.
EncodeToString
(
hash
.
Sum
(
nil
))
if
shaStr
!=
r
.
LfsOid
{
fail500
(
w
,
"Inconsistent size: "
,
errSizeMismatch
)
return
}
}
}
r
.
Header
.
Set
(
"X-GitLab-Lfs-Tmp"
,
filepath
.
Base
(
file
.
Name
()))
func
lfsCallback
(
w
http
.
ResponseWriter
,
r
*
gitRequest
)
{
authReq
,
err
:=
r
.
u
.
newUpstreamRequest
(
r
.
Request
,
nil
,
""
)
authReq
,
err
:=
r
.
u
.
newUpstreamRequest
(
r
.
Request
,
nil
,
"/authorize"
)
if
err
!=
nil
{
if
err
!=
nil
{
fail500
(
w
,
"newUpstreamRequestlfsCallback"
,
err
)
fail500
(
w
,
"newUpstreamRequestlfsCallback"
,
err
)
return
return
...
@@ -115,5 +99,6 @@ func lfsCallback(w http.ResponseWriter, r *gitRequest) {
...
@@ -115,5 +99,6 @@ func lfsCallback(w http.ResponseWriter, r *gitRequest) {
return
return
}
}
defer
authResponse
.
Body
.
Close
()
defer
authResponse
.
Body
.
Close
()
return
return
}
}
main_test.go
View file @
c99c4302
...
@@ -241,69 +241,18 @@ func TestDownloadCacheCreate(t *testing.T) {
...
@@ -241,69 +241,18 @@ func TestDownloadCacheCreate(t *testing.T) {
func
TestAllowedXSendfileDownload
(
t
*
testing
.
T
)
{
func
TestAllowedXSendfileDownload
(
t
*
testing
.
T
)
{
contentFilename
:=
"my-content"
contentFilename
:=
"my-content"
contentPath
:=
path
.
Join
(
cacheDir
,
contentFilename
)
url
:=
fmt
.
Sprintf
(
"http://%s/foo/uploads/bar"
,
servAddr
)
prepareDownloadDir
(
t
)
prepareDownloadDir
(
t
)
// Prepare test server and backend
allowedXSendfileDownload
(
t
,
contentFilename
,
url
)
ts
:=
httptest
.
NewServer
(
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
if
xSendfileType
:=
r
.
Header
.
Get
(
"X-Sendfile-Type"
);
xSendfileType
!=
"X-Sendfile"
{
t
.
Fatalf
(
`X-Sendfile-Type want "X-Sendfile" got %q`
,
xSendfileType
)
}
w
.
Header
()
.
Set
(
"X-Sendfile"
,
contentPath
)
w
.
Header
()
.
Set
(
"Content-Disposition"
,
fmt
.
Sprintf
(
`attachment; filename="%s"`
,
contentFilename
))
w
.
WriteHeader
(
200
)
}))
defer
ts
.
Close
()
defer
cleanUpProcessGroup
(
startServerOrFail
(
t
,
ts
))
if
err
:=
os
.
MkdirAll
(
cacheDir
,
0755
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
contentBytes
:=
[]
byte
{
'c'
,
'o'
,
'n'
,
't'
,
'e'
,
'n'
,
't'
}
if
err
:=
ioutil
.
WriteFile
(
contentPath
,
contentBytes
,
0644
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
downloadCmd
:=
exec
.
Command
(
"curl"
,
"-J"
,
"-O"
,
fmt
.
Sprintf
(
"http://%s/foo/uploads/bar"
,
servAddr
))
downloadCmd
.
Dir
=
scratchDir
runOrFail
(
t
,
downloadCmd
)
actual
,
err
:=
ioutil
.
ReadFile
(
path
.
Join
(
scratchDir
,
contentFilename
))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
bytes
.
Compare
(
actual
,
contentBytes
)
!=
0
{
t
.
Fatal
(
"Unexpected file contents in download"
)
}
}
}
func
TestDeniedXSendfileDownload
(
t
*
testing
.
T
)
{
func
TestDeniedXSendfileDownload
(
t
*
testing
.
T
)
{
contentFilename
:=
"my-content"
contentFilename
:=
"my-content"
url
:=
fmt
.
Sprintf
(
"http://%s/foo/uploads/bar"
,
servAddr
)
prepareDownloadDir
(
t
)
prepareDownloadDir
(
t
)
// Prepare test server and backend
deniedXSendfileDownload
(
t
,
contentFilename
,
url
)
ts
:=
httptest
.
NewServer
(
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
if
xSendfileType
:=
r
.
Header
.
Get
(
"X-Sendfile-Type"
);
xSendfileType
!=
"X-Sendfile"
{
t
.
Fatalf
(
`X-Sendfile-Type want "X-Sendfile" got %q`
,
xSendfileType
)
}
w
.
Header
()
.
Set
(
"Content-Disposition"
,
fmt
.
Sprintf
(
`attachment; filename="%s"`
,
contentFilename
))
w
.
WriteHeader
(
200
)
fmt
.
Fprint
(
w
,
"Denied"
)
}))
defer
ts
.
Close
()
defer
cleanUpProcessGroup
(
startServerOrFail
(
t
,
ts
))
downloadCmd
:=
exec
.
Command
(
"curl"
,
"-J"
,
"-O"
,
fmt
.
Sprintf
(
"http://%s/foo/uploads/bar"
,
servAddr
))
downloadCmd
.
Dir
=
scratchDir
runOrFail
(
t
,
downloadCmd
)
actual
,
err
:=
ioutil
.
ReadFile
(
path
.
Join
(
scratchDir
,
contentFilename
))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
bytes
.
Compare
(
actual
,
[]
byte
{
'D'
,
'e'
,
'n'
,
'i'
,
'e'
,
'd'
})
!=
0
{
t
.
Fatal
(
"Unexpected file contents in download"
)
}
}
}
func
prepareDownloadDir
(
t
*
testing
.
T
)
{
func
prepareDownloadDir
(
t
*
testing
.
T
)
{
...
@@ -401,3 +350,85 @@ func repoPath(t *testing.T) string {
...
@@ -401,3 +350,85 @@ func repoPath(t *testing.T) string {
}
}
return
path
.
Join
(
cwd
,
testRepoRoot
,
testRepo
)
return
path
.
Join
(
cwd
,
testRepoRoot
,
testRepo
)
}
}
func
TestDeniedLfsDownload
(
t
*
testing
.
T
)
{
contentFilename
:=
"b68143e6463773b1b6c6fd009a76c32aeec041faff32ba2ed42fd7f708a17f80"
url
:=
fmt
.
Sprintf
(
"http://%s/gitlab-lfs/objects/%s"
,
servAddr
,
contentFilename
)
prepareDownloadDir
(
t
)
deniedXSendfileDownload
(
t
,
contentFilename
,
url
)
}
func
TestAllowedLfsDownload
(
t
*
testing
.
T
)
{
contentFilename
:=
"b68143e6463773b1b6c6fd009a76c32aeec041faff32ba2ed42fd7f708a17f80"
url
:=
fmt
.
Sprintf
(
"http://%s/gitlab-lfs/objects/%s"
,
servAddr
,
contentFilename
)
prepareDownloadDir
(
t
)
allowedXSendfileDownload
(
t
,
contentFilename
,
url
)
}
func
allowedXSendfileDownload
(
t
*
testing
.
T
,
contentFilename
string
,
url
string
)
{
contentPath
:=
path
.
Join
(
cacheDir
,
contentFilename
)
prepareDownloadDir
(
t
)
// Prepare test server and backend
ts
:=
httptest
.
NewServer
(
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
if
xSendfileType
:=
r
.
Header
.
Get
(
"X-Sendfile-Type"
);
xSendfileType
!=
"X-Sendfile"
{
t
.
Fatalf
(
`X-Sendfile-Type want "X-Sendfile" got %q`
,
xSendfileType
)
}
w
.
Header
()
.
Set
(
"X-Sendfile"
,
contentPath
)
w
.
Header
()
.
Set
(
"Content-Disposition"
,
fmt
.
Sprintf
(
`attachment; filename="%s"`
,
contentFilename
))
w
.
Header
()
.
Set
(
"Content-Type"
,
fmt
.
Sprintf
(
`application/octet-stream`
))
w
.
WriteHeader
(
200
)
}))
defer
ts
.
Close
()
defer
cleanUpProcessGroup
(
startServerOrFail
(
t
,
ts
))
if
err
:=
os
.
MkdirAll
(
cacheDir
,
0755
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
contentBytes
:=
[]
byte
{
'c'
,
'o'
,
'n'
,
't'
,
'e'
,
'n'
,
't'
}
if
err
:=
ioutil
.
WriteFile
(
contentPath
,
contentBytes
,
0644
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
downloadCmd
:=
exec
.
Command
(
"curl"
,
"-J"
,
"-O"
,
url
)
downloadCmd
.
Dir
=
scratchDir
runOrFail
(
t
,
downloadCmd
)
actual
,
err
:=
ioutil
.
ReadFile
(
path
.
Join
(
scratchDir
,
contentFilename
))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
bytes
.
Compare
(
actual
,
contentBytes
)
!=
0
{
t
.
Fatal
(
"Unexpected file contents in download"
)
}
}
func
deniedXSendfileDownload
(
t
*
testing
.
T
,
contentFilename
string
,
url
string
)
{
prepareDownloadDir
(
t
)
// Prepare test server and backend
ts
:=
httptest
.
NewServer
(
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
if
xSendfileType
:=
r
.
Header
.
Get
(
"X-Sendfile-Type"
);
xSendfileType
!=
"X-Sendfile"
{
t
.
Fatalf
(
`X-Sendfile-Type want "X-Sendfile" got %q`
,
xSendfileType
)
}
w
.
Header
()
.
Set
(
"Content-Disposition"
,
fmt
.
Sprintf
(
`attachment; filename="%s"`
,
contentFilename
))
w
.
WriteHeader
(
200
)
fmt
.
Fprint
(
w
,
"Denied"
)
}))
defer
ts
.
Close
()
defer
cleanUpProcessGroup
(
startServerOrFail
(
t
,
ts
))
downloadCmd
:=
exec
.
Command
(
"curl"
,
"-J"
,
"-O"
,
url
)
downloadCmd
.
Dir
=
scratchDir
runOrFail
(
t
,
downloadCmd
)
actual
,
err
:=
ioutil
.
ReadFile
(
path
.
Join
(
scratchDir
,
contentFilename
))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
bytes
.
Compare
(
actual
,
[]
byte
{
'D'
,
'e'
,
'n'
,
'i'
,
'e'
,
'd'
})
!=
0
{
t
.
Fatal
(
"Unexpected file contents in download"
)
}
}
upstream.go
View file @
c99c4302
...
@@ -50,7 +50,7 @@ type authorizationResponse struct {
...
@@ -50,7 +50,7 @@ type authorizationResponse struct {
// LFS object id
// LFS object id
LfsOid
string
LfsOid
string
// LFS object size
// LFS object size
LfsSize
string
LfsSize
int64
}
}
// A gitReqest is an *http.Request decorated with attributes returned by the
// A gitReqest is an *http.Request decorated with attributes returned by the
...
@@ -72,7 +72,7 @@ var gitServices = [...]gitService{
...
@@ -72,7 +72,7 @@ var gitServices = [...]gitService{
gitService
{
"GET"
,
regexp
.
MustCompile
(
`/repository/archive.tar.gz\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
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
(
`/repository/archive.tar.bz2\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
gitService
{
"GET"
,
regexp
.
MustCompile
(
`/uploads/`
),
handleSendFile
},
gitService
{
"GET"
,
regexp
.
MustCompile
(
`/uploads/`
),
handleSendFile
},
gitService
{
"PUT"
,
regexp
.
MustCompile
(
`/gitlab-lfs/objects/([0-9a-f]{64})/([0-9]+)\z`
),
lfsAuthorizeHandler
(
handleStoreLfsObject
(
lfsCallback
)
)},
gitService
{
"PUT"
,
regexp
.
MustCompile
(
`/gitlab-lfs/objects/([0-9a-f]{64})/([0-9]+)\z`
),
lfsAuthorizeHandler
(
handleStoreLfsObject
)},
gitService
{
"GET"
,
regexp
.
MustCompile
(
`/gitlab-lfs/objects/([0-9a-f]{64})\z`
),
handleSendFile
},
gitService
{
"GET"
,
regexp
.
MustCompile
(
`/gitlab-lfs/objects/([0-9a-f]{64})\z`
),
handleSendFile
},
}
}
...
...
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