14475: Fix Content-Type header parsing.
authorTom Clegg <tclegg@veritasgenetics.com>
Tue, 13 Nov 2018 20:49:31 +0000 (15:49 -0500)
committerTom Clegg <tclegg@veritasgenetics.com>
Tue, 13 Nov 2018 20:49:31 +0000 (15:49 -0500)
"Content-Type: application/x-www-form-urlencoded; charset=UTF-8", for
example, means we should parse the request body as a form.

See https://github.com/golang/go/blob/master/src/net/http/request.go
-> parsePostForm().

Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tclegg@veritasgenetics.com>

lib/controller/federation.go
lib/controller/federation_test.go

index 1a0b78be2b394c5f2de7a094cb45480fee38e988..557c7c3563d59c23644370765f466e63517f4d5a 100644 (file)
@@ -11,6 +11,7 @@ import (
        "fmt"
        "io"
        "io/ioutil"
+       "mime"
        "net/http"
        "net/url"
        "regexp"
@@ -61,7 +62,11 @@ func (h *Handler) remoteClusterRequest(remoteID string, req *http.Request) (*htt
 // downstream proxy steps.
 func loadParamsFromForm(req *http.Request) error {
        var postBody *bytes.Buffer
-       if req.Body != nil && req.Header.Get("Content-Type") == "application/x-www-form-urlencoded" {
+       if ct := req.Header.Get("Content-Type"); ct == "" {
+               // Assume application/octet-stream, i.e., no form to parse.
+       } else if ct, _, err := mime.ParseMediaType(ct); err != nil {
+               return err
+       } else if ct == "application/x-www-form-urlencoded" && req.Body != nil {
                var cl int64
                if req.ContentLength > 0 {
                        cl = req.ContentLength
index da640071c523bc388af98fa3214d7328cf715359..5ea5748b04bef0ed7b90757fa8bbd6ab03026cbe 100644 (file)
@@ -347,6 +347,8 @@ func (s *FederationSuite) TestGetLocalCollection(c *check.C) {
        s.testHandler.Cluster.NodeProfiles["*"] = np
        s.testHandler.NodeProfile = &np
 
+       // HTTP GET
+
        req := httptest.NewRequest("GET", "/arvados/v1/collections/"+arvadostest.UserAgreementCollection, nil)
        req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
        resp := s.testRequest(req)
@@ -358,6 +360,23 @@ func (s *FederationSuite) TestGetLocalCollection(c *check.C) {
        c.Check(col.ManifestText, check.Matches,
                `\. 6a4ff0499484c6c79c95cd8c566bd25f\+249025\+A[0-9a-f]{40}@[0-9a-f]{8} 0:249025:GNU_General_Public_License,_version_3.pdf
 `)
+
+       // HTTP POST with _method=GET as a form parameter
+
+       req = httptest.NewRequest("POST", "/arvados/v1/collections/"+arvadostest.UserAgreementCollection, bytes.NewBufferString((url.Values{
+               "_method": {"GET"},
+       }).Encode()))
+       req.Header.Set("Authorization", "Bearer "+arvadostest.ActiveToken)
+       req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
+       resp = s.testRequest(req)
+
+       c.Check(resp.StatusCode, check.Equals, http.StatusOK)
+       col = arvados.Collection{}
+       c.Check(json.NewDecoder(resp.Body).Decode(&col), check.IsNil)
+       c.Check(col.UUID, check.Equals, arvadostest.UserAgreementCollection)
+       c.Check(col.ManifestText, check.Matches,
+               `\. 6a4ff0499484c6c79c95cd8c566bd25f\+249025\+A[0-9a-f]{40}@[0-9a-f]{8} 0:249025:GNU_General_Public_License,_version_3.pdf
+`)
 }
 
 func (s *FederationSuite) TestGetRemoteCollection(c *check.C) {