Skip to content

Commit

Permalink
rest/request: skip empty strings in values of Access-Control-Request-…
Browse files Browse the repository at this point in the history
…Headers

WebKit browsers may send a preflight CORS request setting
Access-Control-Request-Headers to an empty value, what is in turn interpreted as
an empty string on Golang's http server side. An example scenario that triggers
this behavior in Chrome is doing a xhr POST request and setting progress
callback. Request headers reported by browser's developer tools are then the
following:

:authority:docker.mender.io:8080
:method:OPTIONS
:path:/api/integrations/0.1/deployments/images
:scheme:https
accept:*/*
accept-encoding:gzip, deflate, sdch, br
accept-language:en-US,en;q=0.8,pl;q=0.6
access-control-request-headers:      <--- empty value here
access-control-request-method:POST
dnt:1
origin:http://localhost:9999
referer:http://localhost:9999/test.html
user-agent:Mozilla/5.0 (X11; Linux x86_64) ...

It is unclear whether in such case, the client wants to send no headers in the
actual request or just a bug in client's code.

Since the original request is cured and repacked into CorsInfo it makes sense to
skip Access-Control-Request-Headers values that are empty.

Signed-off-by: Maciej Borzecki <maciej.borzecki@rndity.com>
  • Loading branch information
bboozzoo committed Nov 30, 2016
1 parent 709bbe3 commit 9ec7f2b
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 0 deletions.
3 changes: 3 additions & 0 deletions rest/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ func (r *Request) GetCorsInfo() *CorsInfo {
reqHeaders := []string{}
rawReqHeaders := r.Header[http.CanonicalHeaderKey("Access-Control-Request-Headers")]
for _, rawReqHeader := range rawReqHeaders {
if len(rawReqHeader) == 0 {
continue
}
// net/http does not handle comma delimited headers for us
for _, reqHeader := range strings.Split(rawReqHeader, ",") {
reqHeaders = append(reqHeaders, http.CanonicalHeaderKey(strings.TrimSpace(reqHeader)))
Expand Down
38 changes: 38 additions & 0 deletions rest/request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,41 @@ func TestCorsInfoPreflightCors(t *testing.T) {
t.Error("OriginUrl must be set")
}
}

func TestCorsInfoEmptyAccessControlRequestHeaders(t *testing.T) {
req := defaultRequest("OPTIONS", "http://localhost", nil, t)
req.Request.Header.Set("Origin", "http://another.host")

// make it a preflight request
req.Request.Header.Set("Access-Control-Request-Method", "PUT")

// WebKit based browsers may send `Access-Control-Request-Headers:` with
// no value, in which case, the header will be present in requests
// Header map, but its value is an empty string.
req.Request.Header.Set("Access-Control-Request-Headers", "")
corsInfo := req.GetCorsInfo()
if corsInfo == nil {
t.Error("Expected non nil CorsInfo")
}
if corsInfo.IsCors == false {
t.Error("This is a CORS request")
}
if len(corsInfo.AccessControlRequestHeaders) > 0 {
t.Error("Access-Control-Request-Headers should have been removed")
}

req.Request.Header.Set("Access-Control-Request-Headers", "")
corsInfo = req.GetCorsInfo()
if corsInfo == nil {
t.Error("Expected non nil CorsInfo")
}
if corsInfo.IsCors == false {
t.Error("This is a CORS request")
}
if corsInfo.IsPreflight == false {
t.Error("This is a Preflight request")
}
if len(corsInfo.AccessControlRequestHeaders) > 0 {
t.Error("Empty Access-Control-Request-Headers header should have been removed")
}
}

0 comments on commit 9ec7f2b

Please sign in to comment.