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
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
iv
gitlab-workhorse
Commits
86aaa133
Commit
86aaa133
authored
Jan 15, 2016
by
Jacob Vosmaer
2
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Prototype blobs via workhorse
parent
9530b40d
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
107 additions
and
28 deletions
+107
-28
internal/api/api.go
internal/api/api.go
+1
-2
internal/git/blob.go
internal/git/blob.go
+62
-0
internal/helper/helpers.go
internal/helper/helpers.go
+10
-0
internal/proxy/proxy.go
internal/proxy/proxy.go
+4
-12
internal/senddata/sendfile.go
internal/senddata/sendfile.go
+30
-14
No files found.
internal/api/api.go
View file @
86aaa133
...
@@ -3,7 +3,6 @@ package api
...
@@ -3,7 +3,6 @@ package api
import
(
import
(
"../badgateway"
"../badgateway"
"../helper"
"../helper"
"../proxy"
"encoding/json"
"encoding/json"
"fmt"
"fmt"
"io"
"io"
...
@@ -93,7 +92,7 @@ func (api *API) newRequest(r *http.Request, body io.Reader, suffix string) (*htt
...
@@ -93,7 +92,7 @@ func (api *API) newRequest(r *http.Request, body io.Reader, suffix string) (*htt
authReq
:=
&
http
.
Request
{
authReq
:=
&
http
.
Request
{
Method
:
r
.
Method
,
Method
:
r
.
Method
,
URL
:
rebaseUrl
(
r
.
URL
,
api
.
URL
,
suffix
),
URL
:
rebaseUrl
(
r
.
URL
,
api
.
URL
,
suffix
),
Header
:
proxy
.
HeaderClone
(
r
.
Header
),
Header
:
helper
.
HeaderClone
(
r
.
Header
),
}
}
if
body
!=
nil
{
if
body
!=
nil
{
authReq
.
Body
=
ioutil
.
NopCloser
(
body
)
authReq
.
Body
=
ioutil
.
NopCloser
(
body
)
...
...
internal/git/blob.go
0 → 100644
View file @
86aaa133
package
git
import
(
"../helper"
"bufio"
"encoding/base64"
"fmt"
"io"
"net/http"
)
const
blobLine
=
`blob
`
func
SendGitBlob
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
repoPath
string
,
blobId
string
)
{
blobSpec
,
err
:=
base64
.
URLEncoding
.
DecodeString
(
blobId
)
if
err
!=
nil
{
helper
.
Fail500
(
w
,
fmt
.
Errorf
(
"SendGitBlob: decode commit id + path: %v"
,
err
))
return
}
catFileCmd
:=
gitCommand
(
""
,
"git"
,
"--git-dir="
+
repoPath
,
"cat-file"
,
"--batch=%(objecttype)"
)
catFileStdin
,
err
:=
catFileCmd
.
StdinPipe
()
if
err
!=
nil
{
helper
.
Fail500
(
w
,
fmt
.
Errorf
(
"SendGitBlob: git cat-file stdin: %v"
,
err
))
return
}
catFileStdout
,
err
:=
catFileCmd
.
StdoutPipe
()
if
err
!=
nil
{
helper
.
Fail500
(
w
,
fmt
.
Errorf
(
"SendGitBlob: git cat-file stdout: %v"
,
err
))
return
}
if
err
:=
catFileCmd
.
Start
();
err
!=
nil
{
helper
.
Fail500
(
w
,
fmt
.
Errorf
(
"SendGitBlob: start %v: %v"
,
catFileCmd
,
err
))
return
}
defer
cleanUpProcessGroup
(
catFileCmd
)
if
_
,
err
:=
fmt
.
Fprintf
(
catFileStdin
,
"%s
\n
"
,
blobSpec
);
err
!=
nil
{
helper
.
Fail500
(
w
,
fmt
.
Errorf
(
"SendGitBlob: send command to git cat-file: %v"
,
err
))
return
}
if
err
:=
catFileStdin
.
Close
();
err
!=
nil
{
helper
.
Fail500
(
w
,
fmt
.
Errorf
(
"SendGitBlob: close git cat-file stdin: %v"
,
err
))
return
}
out
:=
bufio
.
NewReader
(
catFileStdout
)
if
response
,
err
:=
out
.
ReadString
(
'\n'
);
err
!=
nil
||
response
!=
blobLine
{
helper
.
Fail500
(
w
,
fmt
.
Errorf
(
"SendGitBlob: git cat-file returned %q, error: %v"
,
response
,
err
))
return
}
if
_
,
err
:=
io
.
Copy
(
w
,
catFileStdout
);
err
!=
nil
{
helper
.
LogError
(
fmt
.
Errorf
(
"SendGitBlob: copy git cat-file stdout: %v"
,
err
))
return
}
if
err
:=
catFileCmd
.
Wait
();
err
!=
nil
{
helper
.
LogError
(
fmt
.
Errorf
(
"SendGitBlob: wait for git cat-file: %v"
,
err
))
return
}
}
internal/helper/helpers.go
View file @
86aaa133
...
@@ -69,3 +69,13 @@ func HTTPError(w http.ResponseWriter, r *http.Request, error string, code int) {
...
@@ -69,3 +69,13 @@ func HTTPError(w http.ResponseWriter, r *http.Request, error string, code int) {
http
.
Error
(
w
,
error
,
code
)
http
.
Error
(
w
,
error
,
code
)
}
}
func
HeaderClone
(
h
http
.
Header
)
http
.
Header
{
h2
:=
make
(
http
.
Header
,
len
(
h
))
for
k
,
vv
:=
range
h
{
vv2
:=
make
([]
string
,
len
(
vv
))
copy
(
vv2
,
vv
)
h2
[
k
]
=
vv2
}
return
h2
}
internal/proxy/proxy.go
View file @
86aaa133
...
@@ -2,6 +2,8 @@ package proxy
...
@@ -2,6 +2,8 @@ package proxy
import
(
import
(
"../badgateway"
"../badgateway"
"../helper"
"../senddata"
"net/http"
"net/http"
"net/http/httputil"
"net/http/httputil"
"net/url"
"net/url"
...
@@ -25,24 +27,14 @@ func NewProxy(myURL *url.URL, version string, roundTripper *badgateway.RoundTrip
...
@@ -25,24 +27,14 @@ func NewProxy(myURL *url.URL, version string, roundTripper *badgateway.RoundTrip
return
&
p
return
&
p
}
}
func
HeaderClone
(
h
http
.
Header
)
http
.
Header
{
h2
:=
make
(
http
.
Header
,
len
(
h
))
for
k
,
vv
:=
range
h
{
vv2
:=
make
([]
string
,
len
(
vv
))
copy
(
vv2
,
vv
)
h2
[
k
]
=
vv2
}
return
h2
}
func
(
p
*
Proxy
)
ServeHTTP
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
func
(
p
*
Proxy
)
ServeHTTP
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
// Clone request
// Clone request
req
:=
*
r
req
:=
*
r
req
.
Header
=
HeaderClone
(
r
.
Header
)
req
.
Header
=
helper
.
HeaderClone
(
r
.
Header
)
// Set Workhorse version
// Set Workhorse version
req
.
Header
.
Set
(
"Gitlab-Workhorse"
,
p
.
Version
)
req
.
Header
.
Set
(
"Gitlab-Workhorse"
,
p
.
Version
)
rw
:=
n
ewSendFileResponseWriter
(
w
,
&
req
)
rw
:=
senddata
.
N
ewSendFileResponseWriter
(
w
,
&
req
)
defer
rw
.
Flush
()
defer
rw
.
Flush
()
p
.
reverseProxy
.
ServeHTTP
(
&
rw
,
&
req
)
p
.
reverseProxy
.
ServeHTTP
(
&
rw
,
&
req
)
...
...
internal/
proxy
/sendfile.go
→
internal/
senddata
/sendfile.go
View file @
86aaa133
...
@@ -4,9 +4,10 @@ via the X-Sendfile mechanism. All that is needed in the Rails code is the
...
@@ -4,9 +4,10 @@ via the X-Sendfile mechanism. All that is needed in the Rails code is the
'send_file' method.
'send_file' method.
*/
*/
package
proxy
package
senddata
import
(
import
(
"../git"
"../helper"
"../helper"
"log"
"log"
"net/http"
"net/http"
...
@@ -19,7 +20,7 @@ type sendFileResponseWriter struct {
...
@@ -19,7 +20,7 @@ type sendFileResponseWriter struct {
req
*
http
.
Request
req
*
http
.
Request
}
}
func
n
ewSendFileResponseWriter
(
rw
http
.
ResponseWriter
,
req
*
http
.
Request
)
sendFileResponseWriter
{
func
N
ewSendFileResponseWriter
(
rw
http
.
ResponseWriter
,
req
*
http
.
Request
)
sendFileResponseWriter
{
s
:=
sendFileResponseWriter
{
s
:=
sendFileResponseWriter
{
rw
:
rw
,
rw
:
rw
,
req
:
req
,
req
:
req
,
...
@@ -48,30 +49,45 @@ func (s *sendFileResponseWriter) WriteHeader(status int) {
...
@@ -48,30 +49,45 @@ func (s *sendFileResponseWriter) WriteHeader(status int) {
}
}
s
.
status
=
status
s
.
status
=
status
if
s
.
status
!=
http
.
StatusOK
{
s
.
rw
.
WriteHeader
(
s
.
status
)
return
}
if
file
:=
s
.
Header
()
.
Get
(
"X-Sendfile"
);
file
!=
""
{
s
.
Header
()
.
Del
(
"X-Sendfile"
)
// Mark this connection as hijacked
s
.
hijacked
=
true
// Check X-Sendfile header
// Serve the file
file
:=
s
.
Header
()
.
Get
(
"X-Sendfile"
)
sendFileFromDisk
(
s
.
rw
,
s
.
req
,
file
)
s
.
Header
()
.
Del
(
"X-Sendfile"
)
return
}
else
if
repoPath
:=
s
.
Header
()
.
Get
(
"Gitlab-Workhorse-Repo-Path"
);
repoPath
!=
""
{
s
.
hijacked
=
true
s
.
Header
()
.
Del
(
"Gitlab-Workhorse-Repo-Path"
)
sendBlob
:=
s
.
Header
()
.
Get
(
"Gitlab-Workhorse-Send-Blob"
)
s
.
Header
()
.
Del
(
"Gitlab-Workhorse-Send-Blob"
)
// If file is empty or status is not 200 pass through header
git
.
SendGitBlob
(
s
.
rw
,
s
.
req
,
repoPath
,
sendBlob
)
if
file
==
""
||
s
.
status
!=
http
.
StatusOK
{
return
}
else
{
s
.
rw
.
WriteHeader
(
s
.
status
)
s
.
rw
.
WriteHeader
(
s
.
status
)
return
return
}
}
}
// Mark this connection as hijacked
func
sendFileFromDisk
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
file
string
)
{
s
.
hijacked
=
true
log
.
Printf
(
"Send file %q for %s %q"
,
file
,
r
.
Method
,
r
.
RequestURI
)
// Serve the file
log
.
Printf
(
"Send file %q for %s %q"
,
file
,
s
.
req
.
Method
,
s
.
req
.
RequestURI
)
content
,
fi
,
err
:=
helper
.
OpenFile
(
file
)
content
,
fi
,
err
:=
helper
.
OpenFile
(
file
)
if
err
!=
nil
{
if
err
!=
nil
{
http
.
NotFound
(
s
.
rw
,
s
.
req
)
http
.
NotFound
(
w
,
r
)
return
return
}
}
defer
content
.
Close
()
defer
content
.
Close
()
http
.
ServeContent
(
s
.
rw
,
s
.
req
,
""
,
fi
.
ModTime
(),
content
)
http
.
ServeContent
(
w
,
r
,
""
,
fi
.
ModTime
(),
content
)
}
}
func
(
s
*
sendFileResponseWriter
)
Flush
()
{
func
(
s
*
sendFileResponseWriter
)
Flush
()
{
...
...
Kirill Smelkov
@kirr
mentioned in commit
45bbe40c
·
Jan 12, 2017
mentioned in commit
45bbe40c
mentioned in commit 45bbe40c60c7f0117d66ffcbd8c1f28af8d87d26
Toggle commit list
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