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
803f74c2
Commit
803f74c2
authored
Mar 01, 2017
by
Pawel Chojnacki
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Do not follow when doing api calls.
+ small code cleanup Make redirects work in go < 1.7
parent
e7a352d9
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
60 additions
and
34 deletions
+60
-34
authorization_test.go
authorization_test.go
+12
-0
internal/api/api.go
internal/api/api.go
+48
-34
No files found.
authorization_test.go
View file @
803f74c2
...
@@ -81,6 +81,18 @@ func TestPreAuthorizeContentTypeFailure(t *testing.T) {
...
@@ -81,6 +81,18 @@ func TestPreAuthorizeContentTypeFailure(t *testing.T) {
200
,
200
)
200
,
200
)
}
}
func
TestPreAuthorizeRedirect
(
t
*
testing
.
T
)
{
ts
:=
httptest
.
NewServer
(
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
http
.
Redirect
(
w
,
r
,
"/"
,
301
)
}))
defer
ts
.
Close
()
runPreAuthorizeHandler
(
t
,
ts
,
"/willredirect"
,
regexp
.
MustCompile
(
`/willredirect\z`
),
""
,
301
,
301
)
}
func
TestPreAuthorizeJWT
(
t
*
testing
.
T
)
{
func
TestPreAuthorizeJWT
(
t
*
testing
.
T
)
{
ts
:=
httptest
.
NewServer
(
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
ts
:=
httptest
.
NewServer
(
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
token
,
err
:=
jwt
.
Parse
(
r
.
Header
.
Get
(
api
.
RequestHeader
),
func
(
token
*
jwt
.
Token
)
(
interface
{},
error
)
{
token
,
err
:=
jwt
.
Parse
(
r
.
Header
.
Get
(
api
.
RequestHeader
),
func
(
token
*
jwt
.
Token
)
(
interface
{},
error
)
{
...
...
internal/api/api.go
View file @
803f74c2
...
@@ -132,7 +132,6 @@ func (api *API) newRequest(r *http.Request, body io.Reader, suffix string) (*htt
...
@@ -132,7 +132,6 @@ func (api *API) newRequest(r *http.Request, body io.Reader, suffix string) (*htt
if
body
!=
nil
{
if
body
!=
nil
{
authReq
.
Body
=
ioutil
.
NopCloser
(
body
)
authReq
.
Body
=
ioutil
.
NopCloser
(
body
)
}
}
// Clean some headers when issuing a new request without body
// Clean some headers when issuing a new request without body
if
body
==
nil
{
if
body
==
nil
{
authReq
.
Header
.
Del
(
"Content-Type"
)
authReq
.
Header
.
Del
(
"Content-Type"
)
...
@@ -186,7 +185,8 @@ func (api *API) PreAuthorize(suffix string, r *http.Request) (httpResponse *http
...
@@ -186,7 +185,8 @@ func (api *API) PreAuthorize(suffix string, r *http.Request) (httpResponse *http
return
nil
,
nil
,
fmt
.
Errorf
(
"preAuthorizeHandler newUpstreamRequest: %v"
,
err
)
return
nil
,
nil
,
fmt
.
Errorf
(
"preAuthorizeHandler newUpstreamRequest: %v"
,
err
)
}
}
httpResponse
,
err
=
api
.
Client
.
Do
(
authReq
)
httpResponse
,
err
=
api
.
clientDoNotFollowRedirects
(
authReq
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
nil
,
fmt
.
Errorf
(
"preAuthorizeHandler: do request: %v"
,
err
)
return
nil
,
nil
,
fmt
.
Errorf
(
"preAuthorizeHandler: do request: %v"
,
err
)
}
}
...
@@ -230,48 +230,62 @@ func (api *API) PreAuthorizeHandler(next HandleFunc, suffix string) http.Handler
...
@@ -230,48 +230,62 @@ func (api *API) PreAuthorizeHandler(next HandleFunc, suffix string) http.Handler
// The response couldn't be interpreted as a valid auth response, so
// The response couldn't be interpreted as a valid auth response, so
// pass it back (mostly) unmodified
// pass it back (mostly) unmodified
if
httpResponse
!=
nil
&&
authResponse
==
nil
{
if
httpResponse
!=
nil
&&
authResponse
==
nil
{
// NGINX response buffering is disabled on this path (with
passResponseBack
(
httpResponse
,
w
,
r
)
// X-Accel-Buffering: no) but we still want to free up the Unicorn worker
// that generated httpResponse as fast as possible. To do this we buffer
// the entire response body in memory before sending it on.
responseBody
,
err
:=
bufferResponse
(
httpResponse
.
Body
)
if
err
!=
nil
{
helper
.
Fail500
(
w
,
r
,
err
)
}
httpResponse
.
Body
.
Close
()
// Free up the Unicorn worker
bytesTotal
.
Add
(
float64
(
responseBody
.
Len
()))
for
k
,
v
:=
range
httpResponse
.
Header
{
// Accomodate broken clients that do case-sensitive header lookup
if
k
==
"Www-Authenticate"
{
w
.
Header
()[
"WWW-Authenticate"
]
=
v
}
else
{
w
.
Header
()[
k
]
=
v
}
}
w
.
WriteHeader
(
httpResponse
.
StatusCode
)
if
_
,
err
:=
io
.
Copy
(
w
,
responseBody
);
err
!=
nil
{
helper
.
LogError
(
r
,
err
)
}
return
return
}
}
httpResponse
.
Body
.
Close
()
// Free up the Unicorn worker
httpResponse
.
Body
.
Close
()
// Free up the Unicorn worker
// Negotiate authentication (Kerberos) may need to return a WWW-Authenticate
copyAuthHeader
(
httpResponse
,
w
)
// header to the client even in case of success as per RFC4559.
for
k
,
v
:=
range
httpResponse
.
Header
{
// Case-insensitive comparison as per RFC7230
if
strings
.
EqualFold
(
k
,
"WWW-Authenticate"
)
{
w
.
Header
()[
k
]
=
v
}
}
next
(
w
,
r
,
authResponse
)
next
(
w
,
r
,
authResponse
)
})
})
}
}
// go < 1.7 compatibility
func
(
api
*
API
)
clientDoNotFollowRedirects
(
authReq
*
http
.
Request
)
(
*
http
.
Response
,
error
)
{
return
api
.
Client
.
Transport
.
RoundTrip
(
authReq
)
}
func
copyAuthHeader
(
httpResponse
*
http
.
Response
,
w
http
.
ResponseWriter
)
{
// Negotiate authentication (Kerberos) may need to return a WWW-Authenticate
// header to the client even in case of success as per RFC4559.
for
k
,
v
:=
range
httpResponse
.
Header
{
// Case-insensitive comparison as per RFC7230
if
strings
.
EqualFold
(
k
,
"WWW-Authenticate"
)
{
w
.
Header
()[
k
]
=
v
}
}
}
func
passResponseBack
(
httpResponse
*
http
.
Response
,
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
// NGINX response buffering is disabled on this path (with
// X-Accel-Buffering: no) but we still want to free up the Unicorn worker
// that generated httpResponse as fast as possible. To do this we buffer
// the entire response body in memory before sending it on.
responseBody
,
err
:=
bufferResponse
(
httpResponse
.
Body
)
if
err
!=
nil
{
helper
.
Fail500
(
w
,
r
,
err
)
return
}
httpResponse
.
Body
.
Close
()
// Free up the Unicorn worker
bytesTotal
.
Add
(
float64
(
responseBody
.
Len
()))
for
k
,
v
:=
range
httpResponse
.
Header
{
// Accomodate broken clients that do case-sensitive header lookup
if
k
==
"Www-Authenticate"
{
w
.
Header
()[
"WWW-Authenticate"
]
=
v
}
else
{
w
.
Header
()[
k
]
=
v
}
}
w
.
WriteHeader
(
httpResponse
.
StatusCode
)
if
_
,
err
:=
io
.
Copy
(
w
,
responseBody
);
err
!=
nil
{
helper
.
LogError
(
r
,
err
)
}
}
func
bufferResponse
(
r
io
.
Reader
)
(
*
bytes
.
Buffer
,
error
)
{
func
bufferResponse
(
r
io
.
Reader
)
(
*
bytes
.
Buffer
,
error
)
{
responseBody
:=
&
bytes
.
Buffer
{}
responseBody
:=
&
bytes
.
Buffer
{}
n
,
err
:=
io
.
Copy
(
responseBody
,
io
.
LimitReader
(
r
,
failureResponseLimit
))
n
,
err
:=
io
.
Copy
(
responseBody
,
io
.
LimitReader
(
r
,
failureResponseLimit
))
...
...
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