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
afcae9ed
Commit
afcae9ed
authored
Dec 10, 2015
by
Kamil Trzcinski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make golint happy and introduce proxying tests covering proxyRoundTripper
parent
0fa72053
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
166 additions
and
92 deletions
+166
-92
deploy_page_test.go
deploy_page_test.go
+2
-6
error_pages_test.go
error_pages_test.go
+4
-12
helpers_test.go
helpers_test.go
+6
-0
main.go
main.go
+41
-30
proxy.go
proxy.go
+4
-3
proxy_test.go
proxy_test.go
+88
-7
servefile.go
servefile.go
+1
-1
servefile_test.go
servefile_test.go
+10
-18
upstream.go
upstream.go
+10
-15
No files found.
deploy_page_test.go
View file @
afcae9ed
...
@@ -48,10 +48,6 @@ func TestIfDeployPageExist(t *testing.T) {
...
@@ -48,10 +48,6 @@ func TestIfDeployPageExist(t *testing.T) {
}
}
w
.
Flush
()
w
.
Flush
()
if
w
.
Code
!=
200
{
assertResponseCode
(
t
,
w
,
200
)
t
.
Error
(
"Page should be 200"
)
assertResponseBody
(
t
,
w
,
deployPage
)
}
if
w
.
Body
.
String
()
!=
deployPage
{
t
.
Error
(
"Page should be deploy: "
,
w
.
Body
.
String
())
}
}
}
error_pages_test.go
View file @
afcae9ed
...
@@ -28,12 +28,8 @@ func TestIfErrorPageIsPresented(t *testing.T) {
...
@@ -28,12 +28,8 @@ func TestIfErrorPageIsPresented(t *testing.T) {
})(
w
,
nil
)
})(
w
,
nil
)
w
.
Flush
()
w
.
Flush
()
if
w
.
Code
!=
404
{
assertResponseCode
(
t
,
w
,
404
)
t
.
Error
(
"Page should be 404"
)
assertResponseBody
(
t
,
w
,
errorPage
)
}
if
w
.
Body
.
String
()
!=
errorPage
{
t
.
Error
(
"Page should be custom error page: "
,
w
.
Body
.
String
())
}
}
}
func
TestIfErrorPassedIfNoErrorPageIsFound
(
t
*
testing
.
T
)
{
func
TestIfErrorPassedIfNoErrorPageIsFound
(
t
*
testing
.
T
)
{
...
@@ -52,10 +48,6 @@ func TestIfErrorPassedIfNoErrorPageIsFound(t *testing.T) {
...
@@ -52,10 +48,6 @@ func TestIfErrorPassedIfNoErrorPageIsFound(t *testing.T) {
})(
w
,
nil
)
})(
w
,
nil
)
w
.
Flush
()
w
.
Flush
()
if
w
.
Code
!=
404
{
assertResponseCode
(
t
,
w
,
404
)
t
.
Error
(
"Page should be 400"
)
assertResponseBody
(
t
,
w
,
errorResponse
)
}
if
w
.
Body
.
String
()
!=
errorResponse
{
t
.
Error
(
"Page should be response error: "
,
w
.
Body
.
String
())
}
}
}
helpers_test.go
View file @
afcae9ed
...
@@ -10,3 +10,9 @@ func assertResponseCode(t *testing.T, response *httptest.ResponseRecorder, expec
...
@@ -10,3 +10,9 @@ func assertResponseCode(t *testing.T, response *httptest.ResponseRecorder, expec
t
.
Fatalf
(
"for HTTP request expected to get %d, got %d instead"
,
expectedCode
,
response
.
Code
)
t
.
Fatalf
(
"for HTTP request expected to get %d, got %d instead"
,
expectedCode
,
response
.
Code
)
}
}
}
}
func
assertResponseBody
(
t
*
testing
.
T
,
response
*
httptest
.
ResponseRecorder
,
expectedBody
string
)
{
if
response
.
Body
.
String
()
!=
expectedBody
{
t
.
Fatalf
(
"for HTTP request expected to receive %q, got %q instead as body"
,
expectedBody
,
response
.
Body
.
String
())
}
}
main.go
View file @
afcae9ed
...
@@ -26,6 +26,7 @@ import (
...
@@ -26,6 +26,7 @@ import (
"time"
"time"
)
)
// Current version of GitLab Workhorse
var
Version
=
"(unknown version)"
// Set at build time in the Makefile
var
Version
=
"(unknown version)"
// Set at build time in the Makefile
var
printVersion
=
flag
.
Bool
(
"version"
,
false
,
"Print version and exit"
)
var
printVersion
=
flag
.
Bool
(
"version"
,
false
,
"Print version and exit"
)
...
@@ -35,9 +36,9 @@ var listenUmask = flag.Int("listenUmask", 022, "Umask for Unix socket, default:
...
@@ -35,9 +36,9 @@ var listenUmask = flag.Int("listenUmask", 022, "Umask for Unix socket, default:
var
authBackend
=
flag
.
String
(
"authBackend"
,
"http://localhost:8080"
,
"Authentication/authorization backend"
)
var
authBackend
=
flag
.
String
(
"authBackend"
,
"http://localhost:8080"
,
"Authentication/authorization backend"
)
var
authSocket
=
flag
.
String
(
"authSocket"
,
""
,
"Optional: Unix domain socket to dial authBackend at"
)
var
authSocket
=
flag
.
String
(
"authSocket"
,
""
,
"Optional: Unix domain socket to dial authBackend at"
)
var
pprofListenAddr
=
flag
.
String
(
"pprofListenAddr"
,
""
,
"pprof listening address, e.g. 'localhost:6060'"
)
var
pprofListenAddr
=
flag
.
String
(
"pprofListenAddr"
,
""
,
"pprof listening address, e.g. 'localhost:6060'"
)
var
relativeU
rlRoot
=
flag
.
String
(
"relativeUrl
Root"
,
"/"
,
"GitLab relative URL root"
)
var
relativeU
RLRoot
=
flag
.
String
(
"relativeURL
Root"
,
"/"
,
"GitLab relative URL root"
)
var
documentRoot
=
flag
.
String
(
"documentRoot"
,
"public"
,
"Path to static files content"
)
var
documentRoot
=
flag
.
String
(
"documentRoot"
,
"public"
,
"Path to static files content"
)
var
proxyTimeout
=
flag
.
Duration
(
"proxyTimeout"
,
5
*
time
.
Minute
,
"Proxy request timeou
t"
)
var
responseHeadersTimeout
=
flag
.
Duration
(
"proxyHeadersTimeout"
,
time
.
Minute
,
"How long to wait for response headers when proxying the reques
t"
)
type
httpRoute
struct
{
type
httpRoute
struct
{
method
string
method
string
...
@@ -45,36 +46,46 @@ type httpRoute struct {
...
@@ -45,36 +46,46 @@ type httpRoute struct {
handleFunc
serviceHandleFunc
handleFunc
serviceHandleFunc
}
}
const
projectPattern
=
`^/[^/]+/[^/]+/`
const
gitProjectPattern
=
`^/[^/]+/[^/]+\.git/`
const
apiPattern
=
`^/api/`
const
projectsAPIPattern
=
`^/api/v3/projects/[^/]+/`
const
ciAPIPattern
=
`^/ci/api/`
// Routing table
// Routing table
// We match against URI not containing the relativeUrlRoot:
// We match against URI not containing the relativeUrlRoot:
// see upstream.ServeHTTP
// see upstream.ServeHTTP
var
httpRoutes
=
[
...
]
httpRoute
{
var
httpRoutes
=
[
...
]
httpRoute
{
// Git Clone
// Git Clone
httpRoute
{
"GET"
,
regexp
.
MustCompile
(
`^/[^/]+/[^/]+\.git/info/refs\z`
),
repoPreAuthorizeHandler
(
handleGetInfoRefs
)},
httpRoute
{
"GET"
,
regexp
.
MustCompile
(
gitProjectPattern
+
`info/refs\z`
),
repoPreAuthorizeHandler
(
handleGetInfoRefs
)},
httpRoute
{
"POST"
,
regexp
.
MustCompile
(
`/[^/]+/[^/]+\.git/git-upload-pack\z`
),
repoPreAuthorizeHandler
(
contentEncodingHandler
(
handlePostRPC
))},
httpRoute
{
"POST"
,
regexp
.
MustCompile
(
gitProjectPattern
+
`git-upload-pack\z`
),
repoPreAuthorizeHandler
(
contentEncodingHandler
(
handlePostRPC
))},
httpRoute
{
"POST"
,
regexp
.
MustCompile
(
`/[^/]+/[^/]+\.git/git-receive-pack\z`
),
repoPreAuthorizeHandler
(
contentEncodingHandler
(
handlePostRPC
))},
httpRoute
{
"POST"
,
regexp
.
MustCompile
(
gitProjectPattern
+
`git-receive-pack\z`
),
repoPreAuthorizeHandler
(
contentEncodingHandler
(
handlePostRPC
))},
httpRoute
{
"GET"
,
regexp
.
MustCompile
(
`/[^/]+/[^/]+/repository/archive\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
httpRoute
{
"PUT"
,
regexp
.
MustCompile
(
gitProjectPattern
+
`gitlab-lfs/objects/([0-9a-f]{64})/([0-9]+)\z`
),
lfsAuthorizeHandler
(
handleStoreLfsObject
)},
httpRoute
{
"GET"
,
regexp
.
MustCompile
(
`/[^/]+/[^/]+/repository/archive.zip\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
httpRoute
{
"GET"
,
regexp
.
MustCompile
(
`/[^/]+/[^/]+/repository/archive.tar\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
// Repository Archive
httpRoute
{
"GET"
,
regexp
.
MustCompile
(
`/[^/]+/[^/]+/repository/archive.tar.gz\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
httpRoute
{
"GET"
,
regexp
.
MustCompile
(
projectPattern
+
`repository/archive\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
httpRoute
{
"GET"
,
regexp
.
MustCompile
(
`/[^/]+/[^/]+/repository/archive.tar.bz2\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
httpRoute
{
"GET"
,
regexp
.
MustCompile
(
projectPattern
+
`repository/archive.zip\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
httpRoute
{
"GET"
,
regexp
.
MustCompile
(
`/api/v3/projects/[^/]+/repository/archive\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
httpRoute
{
"GET"
,
regexp
.
MustCompile
(
projectPattern
+
`repository/archive.tar\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
httpRoute
{
"GET"
,
regexp
.
MustCompile
(
`/api/v3/projects/[^/]+/repository/archive.zip\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
httpRoute
{
"GET"
,
regexp
.
MustCompile
(
projectPattern
+
`repository/archive.tar.gz\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
httpRoute
{
"GET"
,
regexp
.
MustCompile
(
`/api/v3/projects/[^/]+/repository/archive.tar\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
httpRoute
{
"GET"
,
regexp
.
MustCompile
(
projectPattern
+
`repository/archive.tar.bz2\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
httpRoute
{
"GET"
,
regexp
.
MustCompile
(
`/api/v3/projects/[^/]+/repository/archive.tar.gz\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
httpRoute
{
"GET"
,
regexp
.
MustCompile
(
`/api/v3/projects/[^/]+/repository/archive.tar.bz2\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
// Repository Archive API
httpRoute
{
"GET"
,
regexp
.
MustCompile
(
projectsAPIPattern
+
`repository/archive\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
// Git LFS
httpRoute
{
"GET"
,
regexp
.
MustCompile
(
projectsAPIPattern
+
`repository/archive.zip\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
httpRoute
{
"PUT"
,
regexp
.
MustCompile
(
`/[^/]+/[^/]+\.git/gitlab-lfs/objects/([0-9a-f]{64})/([0-9]+)\z`
),
lfsAuthorizeHandler
(
handleStoreLfsObject
)},
httpRoute
{
"GET"
,
regexp
.
MustCompile
(
projectsAPIPattern
+
`repository/archive.tar\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
httpRoute
{
"GET"
,
regexp
.
MustCompile
(
projectsAPIPattern
+
`repository/archive.tar.gz\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
// CI artifacts
httpRoute
{
"GET"
,
regexp
.
MustCompile
(
projectsAPIPattern
+
`repository/archive.tar.bz2\z`
),
repoPreAuthorizeHandler
(
handleGetArchive
)},
httpRoute
{
"POST"
,
regexp
.
MustCompile
(
`^/ci/api/v1/builds/[0-9]+/artifacts\z`
),
artifactsAuthorizeHandler
(
contentEncodingHandler
(
handleFileUploads
))},
// CI Artifacts API
// Explicitly proxy API
httpRoute
{
"POST"
,
regexp
.
MustCompile
(
ciAPIPattern
+
`v1/builds/[0-9]+/artifacts\z`
),
artifactsAuthorizeHandler
(
contentEncodingHandler
(
handleFileUploads
))},
httpRoute
{
""
,
regexp
.
MustCompile
(
`^/api/`
),
proxyRequest
},
httpRoute
{
""
,
regexp
.
MustCompile
(
`^/ci/api/`
),
proxyRequest
},
// Explicitly proxy API requests
httpRoute
{
""
,
regexp
.
MustCompile
(
apiPattern
),
proxyRequest
},
// Serve static files and forward otherwise
httpRoute
{
""
,
regexp
.
MustCompile
(
ciAPIPattern
),
proxyRequest
},
// Serve static files or forward the requests
httpRoute
{
""
,
nil
,
handleServeFile
(
documentRoot
,
httpRoute
{
""
,
nil
,
handleServeFile
(
documentRoot
,
handleDeployPage
(
documentRoot
,
handleDeployPage
(
documentRoot
,
handleRailsError
(
documentRoot
,
handleRailsError
(
documentRoot
,
...
@@ -125,6 +136,7 @@ func main() {
...
@@ -125,6 +136,7 @@ func main() {
Dial
:
func
(
_
,
_
string
)
(
net
.
Conn
,
error
)
{
Dial
:
func
(
_
,
_
string
)
(
net
.
Conn
,
error
)
{
return
dialer
.
Dial
(
"unix"
,
*
authSocket
)
return
dialer
.
Dial
(
"unix"
,
*
authSocket
)
},
},
ResponseHeaderTimeout
:
*
responseHeadersTimeout
,
}
}
}
}
proxyTransport
:=
&
proxyRoundTripper
{
transport
:
authTransport
}
proxyTransport
:=
&
proxyRoundTripper
{
transport
:
authTransport
}
...
@@ -140,12 +152,11 @@ func main() {
...
@@ -140,12 +152,11 @@ func main() {
}
}
upstream
:=
newUpstream
(
*
authBackend
,
proxyTransport
)
upstream
:=
newUpstream
(
*
authBackend
,
proxyTransport
)
upstream
.
SetRelativeUrlRoot
(
*
relativeUrlRoot
)
upstream
.
SetRelativeURLRoot
(
*
relativeURLRoot
)
upstream
.
SetProxyTimeout
(
*
proxyTimeout
)
// Because net/http/pprof installs itself in the DefaultServeMux
// Because net/http/pprof installs itself in the DefaultServeMux
// we create a fresh one for the Git server.
// we create a fresh one for the Git server.
serveMux
:=
http
.
NewServeMux
()
serveMux
:=
http
.
NewServeMux
()
serveMux
.
Handle
(
upstream
.
relativeU
rl
Root
,
upstream
)
serveMux
.
Handle
(
upstream
.
relativeU
RL
Root
,
upstream
)
log
.
Fatal
(
http
.
Serve
(
listener
,
serveMux
))
log
.
Fatal
(
http
.
Serve
(
listener
,
serveMux
))
}
}
proxy.go
View file @
afcae9ed
...
@@ -16,8 +16,8 @@ func (p *proxyRoundTripper) RoundTrip(r *http.Request) (res *http.Response, err
...
@@ -16,8 +16,8 @@ func (p *proxyRoundTripper) RoundTrip(r *http.Request) (res *http.Response, err
// Map error to 502 response
// Map error to 502 response
if
err
!=
nil
{
if
err
!=
nil
{
res
=
&
http
.
Response
{
res
=
&
http
.
Response
{
StatusCode
:
502
,
StatusCode
:
http
.
StatusBadGateway
,
Status
:
err
.
Error
(
),
Status
:
http
.
StatusText
(
http
.
StatusBadGateway
),
Request
:
r
,
Request
:
r
,
ProtoMajor
:
r
.
ProtoMajor
,
ProtoMajor
:
r
.
ProtoMajor
,
...
@@ -25,8 +25,9 @@ func (p *proxyRoundTripper) RoundTrip(r *http.Request) (res *http.Response, err
...
@@ -25,8 +25,9 @@ func (p *proxyRoundTripper) RoundTrip(r *http.Request) (res *http.Response, err
Proto
:
r
.
Proto
,
Proto
:
r
.
Proto
,
Header
:
make
(
http
.
Header
),
Header
:
make
(
http
.
Header
),
Trailer
:
make
(
http
.
Header
),
Trailer
:
make
(
http
.
Header
),
Body
:
ioutil
.
NopCloser
(
&
bytes
.
Buffer
{}
),
Body
:
ioutil
.
NopCloser
(
bytes
.
NewBufferString
(
err
.
Error
())
),
}
}
res
.
Header
.
Set
(
"Content-Type"
,
"text/plain"
)
err
=
nil
err
=
nil
}
}
return
return
...
...
proxy_test.go
View file @
afcae9ed
...
@@ -4,10 +4,12 @@ import (
...
@@ -4,10 +4,12 @@ import (
"bytes"
"bytes"
"fmt"
"fmt"
"io"
"io"
"net"
"net/http"
"net/http"
"net/http/httptest"
"net/http/httptest"
"regexp"
"regexp"
"testing"
"testing"
"time"
)
)
func
TestProxyRequest
(
t
*
testing
.
T
)
{
func
TestProxyRequest
(
t
*
testing
.
T
)
{
...
@@ -42,15 +44,94 @@ func TestProxyRequest(t *testing.T) {
...
@@ -42,15 +44,94 @@ func TestProxyRequest(t *testing.T) {
u
:
newUpstream
(
ts
.
URL
,
nil
),
u
:
newUpstream
(
ts
.
URL
,
nil
),
}
}
response
:=
httptest
.
NewRecorder
()
w
:=
httptest
.
NewRecorder
()
proxyRequest
(
response
,
&
request
)
proxyRequest
(
w
,
&
request
)
assertResponseCode
(
t
,
response
,
202
)
assertResponseCode
(
t
,
w
,
202
)
assertResponseBody
(
t
,
w
,
"RESPONSE"
)
if
response
.
Body
.
String
()
!=
"RESPONSE
"
{
if
w
.
Header
()
.
Get
(
"Custom-Response-Header"
)
!=
"test
"
{
t
.
Fatal
(
"Expected
RESPONSE in response body:"
,
response
.
Body
.
String
()
)
t
.
Fatal
(
"Expected
custom response header"
)
}
}
}
if
response
.
Header
()
.
Get
(
"Custom-Response-Header"
)
!=
"test"
{
func
TestProxyError
(
t
*
testing
.
T
)
{
t
.
Fatal
(
"Expected custom response header"
)
httpRequest
,
err
:=
http
.
NewRequest
(
"POST"
,
"/url/path"
,
bytes
.
NewBufferString
(
"REQUEST"
))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
httpRequest
.
Header
.
Set
(
"Custom-Header"
,
"test"
)
transport
:=
proxyRoundTripper
{
transport
:
http
.
DefaultTransport
,
}
request
:=
gitRequest
{
Request
:
httpRequest
,
u
:
newUpstream
(
"http://localhost:655575/"
,
&
transport
),
}
w
:=
httptest
.
NewRecorder
()
proxyRequest
(
w
,
&
request
)
assertResponseCode
(
t
,
w
,
502
)
assertResponseBody
(
t
,
w
,
"dial tcp: invalid port 655575"
)
}
func
TestProxyReadTimeout
(
t
*
testing
.
T
)
{
ts
:=
testServerWithHandler
(
nil
,
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
time
.
Sleep
(
time
.
Minute
)
})
httpRequest
,
err
:=
http
.
NewRequest
(
"POST"
,
"http://localhost/url/path"
,
nil
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
}
transport
:=
&
proxyRoundTripper
{
transport
:
&
http
.
Transport
{
Proxy
:
http
.
ProxyFromEnvironment
,
Dial
:
(
&
net
.
Dialer
{
Timeout
:
30
*
time
.
Second
,
KeepAlive
:
30
*
time
.
Second
,
})
.
Dial
,
TLSHandshakeTimeout
:
10
*
time
.
Second
,
ResponseHeaderTimeout
:
time
.
Millisecond
,
},
}
request
:=
gitRequest
{
Request
:
httpRequest
,
u
:
newUpstream
(
ts
.
URL
,
transport
),
}
w
:=
httptest
.
NewRecorder
()
proxyRequest
(
w
,
&
request
)
assertResponseCode
(
t
,
w
,
502
)
assertResponseBody
(
t
,
w
,
"net/http: timeout awaiting response headers"
)
}
func
TestProxyHandlerTimeout
(
t
*
testing
.
T
)
{
ts
:=
testServerWithHandler
(
nil
,
http
.
TimeoutHandler
(
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
time
.
Sleep
(
time
.
Second
)
}),
time
.
Millisecond
,
"Request took too long"
)
.
ServeHTTP
,
)
httpRequest
,
err
:=
http
.
NewRequest
(
"POST"
,
"http://localhost/url/path"
,
nil
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
transport
:=
&
proxyRoundTripper
{
transport
:
http
.
DefaultTransport
,
}
request
:=
gitRequest
{
Request
:
httpRequest
,
u
:
newUpstream
(
ts
.
URL
,
transport
),
}
w
:=
httptest
.
NewRecorder
()
proxyRequest
(
w
,
&
request
)
assertResponseCode
(
t
,
w
,
503
)
assertResponseBody
(
t
,
w
,
"Request took too long"
)
}
}
servefile.go
View file @
afcae9ed
...
@@ -10,7 +10,7 @@ import (
...
@@ -10,7 +10,7 @@ import (
func
handleServeFile
(
documentRoot
*
string
,
notFoundHandler
serviceHandleFunc
)
serviceHandleFunc
{
func
handleServeFile
(
documentRoot
*
string
,
notFoundHandler
serviceHandleFunc
)
serviceHandleFunc
{
return
func
(
w
http
.
ResponseWriter
,
r
*
gitRequest
)
{
return
func
(
w
http
.
ResponseWriter
,
r
*
gitRequest
)
{
file
:=
filepath
.
Join
(
*
documentRoot
,
r
.
relativeU
ri
Path
)
file
:=
filepath
.
Join
(
*
documentRoot
,
r
.
relativeU
RI
Path
)
// The filepath.Join does Clean traversing directories up
// The filepath.Join does Clean traversing directories up
if
!
strings
.
HasPrefix
(
file
,
*
documentRoot
)
{
if
!
strings
.
HasPrefix
(
file
,
*
documentRoot
)
{
...
...
servefile_test.go
View file @
afcae9ed
...
@@ -12,14 +12,12 @@ import (
...
@@ -12,14 +12,12 @@ import (
func
TestServingNonExistingFile
(
t
*
testing
.
T
)
{
func
TestServingNonExistingFile
(
t
*
testing
.
T
)
{
dir
:=
"/path/to/non/existing/directory"
dir
:=
"/path/to/non/existing/directory"
request
:=
&
gitRequest
{
request
:=
&
gitRequest
{
relativeU
ri
Path
:
"/static/file"
,
relativeU
RI
Path
:
"/static/file"
,
}
}
w
:=
httptest
.
NewRecorder
()
w
:=
httptest
.
NewRecorder
()
handleServeFile
(
&
dir
,
nil
)(
w
,
request
)
handleServeFile
(
&
dir
,
nil
)(
w
,
request
)
if
w
.
Code
!=
404
{
assertResponseCode
(
t
,
w
,
404
)
t
.
Fatal
(
"Expected to receive 404, since no default handler is provided"
)
}
}
}
func
TestServingDirectory
(
t
*
testing
.
T
)
{
func
TestServingDirectory
(
t
*
testing
.
T
)
{
...
@@ -30,33 +28,29 @@ func TestServingDirectory(t *testing.T) {
...
@@ -30,33 +28,29 @@ func TestServingDirectory(t *testing.T) {
defer
os
.
RemoveAll
(
dir
)
defer
os
.
RemoveAll
(
dir
)
request
:=
&
gitRequest
{
request
:=
&
gitRequest
{
relativeU
ri
Path
:
"/"
,
relativeU
RI
Path
:
"/"
,
}
}
w
:=
httptest
.
NewRecorder
()
w
:=
httptest
.
NewRecorder
()
handleServeFile
(
&
dir
,
nil
)(
w
,
request
)
handleServeFile
(
&
dir
,
nil
)(
w
,
request
)
if
w
.
Code
!=
404
{
assertResponseCode
(
t
,
w
,
404
)
t
.
Fatal
(
"Expected to receive 404, since we will serve the directory"
)
}
}
}
func
TestServingMalformedUri
(
t
*
testing
.
T
)
{
func
TestServingMalformedUri
(
t
*
testing
.
T
)
{
dir
:=
"/path/to/non/existing/directory"
dir
:=
"/path/to/non/existing/directory"
request
:=
&
gitRequest
{
request
:=
&
gitRequest
{
relativeU
ri
Path
:
"/../../../static/file"
,
relativeU
RI
Path
:
"/../../../static/file"
,
}
}
w
:=
httptest
.
NewRecorder
()
w
:=
httptest
.
NewRecorder
()
handleServeFile
(
&
dir
,
nil
)(
w
,
request
)
handleServeFile
(
&
dir
,
nil
)(
w
,
request
)
if
w
.
Code
!=
500
{
assertResponseCode
(
t
,
w
,
500
)
t
.
Fatal
(
"Expected to receive 500, since client provided invalid URI"
)
}
}
}
func
TestExecutingHandlerWhenNoFileFound
(
t
*
testing
.
T
)
{
func
TestExecutingHandlerWhenNoFileFound
(
t
*
testing
.
T
)
{
dir
:=
"/path/to/non/existing/directory"
dir
:=
"/path/to/non/existing/directory"
request
:=
&
gitRequest
{
request
:=
&
gitRequest
{
relativeU
ri
Path
:
"/static/file"
,
relativeU
RI
Path
:
"/static/file"
,
}
}
executed
:=
false
executed
:=
false
...
@@ -78,17 +72,15 @@ func TestServingTheActualFile(t *testing.T) {
...
@@ -78,17 +72,15 @@ func TestServingTheActualFile(t *testing.T) {
httpRequest
,
_
:=
http
.
NewRequest
(
"GET"
,
"/file"
,
nil
)
httpRequest
,
_
:=
http
.
NewRequest
(
"GET"
,
"/file"
,
nil
)
request
:=
&
gitRequest
{
request
:=
&
gitRequest
{
Request
:
httpRequest
,
Request
:
httpRequest
,
relativeU
ri
Path
:
"/file"
,
relativeU
RI
Path
:
"/file"
,
}
}
fileContent
:=
"
DEPLOY
"
fileContent
:=
"
STATIC
"
ioutil
.
WriteFile
(
filepath
.
Join
(
dir
,
"file"
),
[]
byte
(
fileContent
),
0600
)
ioutil
.
WriteFile
(
filepath
.
Join
(
dir
,
"file"
),
[]
byte
(
fileContent
),
0600
)
w
:=
httptest
.
NewRecorder
()
w
:=
httptest
.
NewRecorder
()
handleServeFile
(
&
dir
,
nil
)(
w
,
request
)
handleServeFile
(
&
dir
,
nil
)(
w
,
request
)
if
w
.
Code
!=
200
{
assertResponseCode
(
t
,
w
,
200
)
t
.
Fatal
(
"Expected to receive 200, since we serve existing file"
)
}
if
w
.
Body
.
String
()
!=
fileContent
{
if
w
.
Body
.
String
()
!=
fileContent
{
t
.
Error
(
"We should serve the file: "
,
w
.
Body
.
String
())
t
.
Error
(
"We should serve the file: "
,
w
.
Body
.
String
())
}
}
...
...
upstream.go
View file @
afcae9ed
...
@@ -12,7 +12,6 @@ import (
...
@@ -12,7 +12,6 @@ import (
"net/http/httputil"
"net/http/httputil"
"net/url"
"net/url"
"strings"
"strings"
"time"
)
)
type
serviceHandleFunc
func
(
w
http
.
ResponseWriter
,
r
*
gitRequest
)
type
serviceHandleFunc
func
(
w
http
.
ResponseWriter
,
r
*
gitRequest
)
...
@@ -21,7 +20,7 @@ type upstream struct {
...
@@ -21,7 +20,7 @@ type upstream struct {
httpClient
*
http
.
Client
httpClient
*
http
.
Client
httpProxy
*
httputil
.
ReverseProxy
httpProxy
*
httputil
.
ReverseProxy
authBackend
string
authBackend
string
relativeU
rl
Root
string
relativeU
RL
Root
string
}
}
type
authorizationResponse
struct
{
type
authorizationResponse
struct
{
...
@@ -60,7 +59,7 @@ type gitRequest struct {
...
@@ -60,7 +59,7 @@ type gitRequest struct {
u
*
upstream
u
*
upstream
// This field contains the URL.Path stripped from RelativeUrlRoot
// This field contains the URL.Path stripped from RelativeUrlRoot
relativeU
ri
Path
string
relativeU
RI
Path
string
}
}
func
newUpstream
(
authBackend
string
,
authTransport
http
.
RoundTripper
)
*
upstream
{
func
newUpstream
(
authBackend
string
,
authTransport
http
.
RoundTripper
)
*
upstream
{
...
@@ -73,24 +72,20 @@ func newUpstream(authBackend string, authTransport http.RoundTripper) *upstream
...
@@ -73,24 +72,20 @@ func newUpstream(authBackend string, authTransport http.RoundTripper) *upstream
authBackend
:
authBackend
,
authBackend
:
authBackend
,
httpClient
:
&
http
.
Client
{
Transport
:
authTransport
},
httpClient
:
&
http
.
Client
{
Transport
:
authTransport
},
httpProxy
:
httputil
.
NewSingleHostReverseProxy
(
u
),
httpProxy
:
httputil
.
NewSingleHostReverseProxy
(
u
),
relativeU
rl
Root
:
"/"
,
relativeU
RL
Root
:
"/"
,
}
}
up
.
httpProxy
.
Transport
=
authTransport
up
.
httpProxy
.
Transport
=
authTransport
return
up
return
up
}
}
func
(
u
*
upstream
)
SetRelativeU
rlRoot
(
relativeUrl
Root
string
)
{
func
(
u
*
upstream
)
SetRelativeU
RLRoot
(
relativeURL
Root
string
)
{
u
.
relativeU
rlRoot
=
relativeUrl
Root
u
.
relativeU
RLRoot
=
relativeURL
Root
if
!
strings
.
HasSuffix
(
u
.
relativeU
rl
Root
,
"/"
)
{
if
!
strings
.
HasSuffix
(
u
.
relativeU
RL
Root
,
"/"
)
{
u
.
relativeU
rl
Root
+=
"/"
u
.
relativeU
RL
Root
+=
"/"
}
}
}
}
func
(
u
*
upstream
)
SetProxyTimeout
(
timeout
time
.
Duration
)
{
u
.
httpClient
.
Timeout
=
timeout
}
func
(
u
*
upstream
)
ServeHTTP
(
ow
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
func
(
u
*
upstream
)
ServeHTTP
(
ow
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
var
g
httpRoute
var
g
httpRoute
...
@@ -100,7 +95,7 @@ func (u *upstream) ServeHTTP(ow http.ResponseWriter, r *http.Request) {
...
@@ -100,7 +95,7 @@ func (u *upstream) ServeHTTP(ow http.ResponseWriter, r *http.Request) {
// Strip prefix and add "/"
// Strip prefix and add "/"
// To match against non-relative URL
// To match against non-relative URL
// Making it simpler for our matcher
// Making it simpler for our matcher
relativeU
riPath
:=
"/"
+
strings
.
TrimPrefix
(
r
.
URL
.
Path
,
u
.
relativeUrl
Root
)
relativeU
RIPath
:=
"/"
+
strings
.
TrimPrefix
(
r
.
URL
.
Path
,
u
.
relativeURL
Root
)
// Look for a matching Git service
// Look for a matching Git service
foundService
:=
false
foundService
:=
false
...
@@ -109,7 +104,7 @@ func (u *upstream) ServeHTTP(ow http.ResponseWriter, r *http.Request) {
...
@@ -109,7 +104,7 @@ func (u *upstream) ServeHTTP(ow http.ResponseWriter, r *http.Request) {
continue
continue
}
}
if
g
.
regex
==
nil
||
g
.
regex
.
MatchString
(
relativeU
ri
Path
)
{
if
g
.
regex
==
nil
||
g
.
regex
.
MatchString
(
relativeU
RI
Path
)
{
foundService
=
true
foundService
=
true
break
break
}
}
...
@@ -123,7 +118,7 @@ func (u *upstream) ServeHTTP(ow http.ResponseWriter, r *http.Request) {
...
@@ -123,7 +118,7 @@ func (u *upstream) ServeHTTP(ow http.ResponseWriter, r *http.Request) {
request
:=
gitRequest
{
request
:=
gitRequest
{
Request
:
r
,
Request
:
r
,
relativeU
riPath
:
relativeUri
Path
,
relativeU
RIPath
:
relativeURI
Path
,
u
:
u
,
u
:
u
,
}
}
...
...
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