From f0d62ea064d32b980f723e37972788cbd693c2ff Mon Sep 17 00:00:00 2001 From: Tom Clegg Date: Thu, 12 Jul 2018 16:50:59 -0400 Subject: [PATCH] 13497: Avoid misdirecting POST to GET when request has double slash. Arvados-DCO-1.1-Signed-off-by: Tom Clegg --- lib/controller/handler.go | 14 ++++++++++++++ services/keep-web/cache.go | 2 +- services/keep-web/cadaver_test.go | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/controller/handler.go b/lib/controller/handler.go index 30994130d5..a1a69a88e4 100644 --- a/lib/controller/handler.go +++ b/lib/controller/handler.go @@ -30,6 +30,20 @@ type Handler struct { func (h *Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) { h.setupOnce.Do(h.setup) + if req.Method != "GET" && req.Method != "HEAD" { + // http.ServeMux returns 301 with a cleaned path if + // the incoming request has a double slash. Some + // clients (including the Go standard library) change + // the request method to GET when following a 301 + // redirect if the original method was not HEAD + // (RFC7231 6.4.2 specifically allows this in the case + // of POST). Thus "POST //foo" gets misdirected to + // "GET /foo". To avoid this, eliminate double slashes + // before passing the request to ServeMux. + for strings.Contains(req.URL.Path, "//") { + req.URL.Path = strings.Replace(req.URL.Path, "//", "/", -1) + } + } h.handlerStack.ServeHTTP(w, req) } diff --git a/services/keep-web/cache.go b/services/keep-web/cache.go index 9ee99903c8..59e8de3bc9 100644 --- a/services/keep-web/cache.go +++ b/services/keep-web/cache.go @@ -99,7 +99,7 @@ func (c *cache) Update(client *arvados.Client, coll arvados.Collection, fs arvad } var updated arvados.Collection defer c.pdhs.Remove(coll.UUID) - err := client.RequestAndDecode(&updated, "PATCH", "/arvados/v1/collections/"+coll.UUID, client.UpdateBody(coll), nil) + err := client.RequestAndDecode(&updated, "PATCH", "arvados/v1/collections/"+coll.UUID, client.UpdateBody(coll), nil) if err == nil { c.collections.Add(client.AuthToken+"\000"+coll.PortableDataHash, &cachedCollection{ expire: time.Now().Add(time.Duration(c.TTL)), diff --git a/services/keep-web/cadaver_test.go b/services/keep-web/cadaver_test.go index 3814a459d5..0e2f17c35b 100644 --- a/services/keep-web/cadaver_test.go +++ b/services/keep-web/cadaver_test.go @@ -74,7 +74,7 @@ func (s *IntegrationSuite) testCadaver(c *check.C, password string, pathFunc fun var newCollection arvados.Collection arv := arvados.NewClientFromEnv() arv.AuthToken = arvadostest.ActiveToken - err = arv.RequestAndDecode(&newCollection, "POST", "/arvados/v1/collections", bytes.NewBufferString(url.Values{"collection": {"{}"}}.Encode()), nil) + err = arv.RequestAndDecode(&newCollection, "POST", "arvados/v1/collections", bytes.NewBufferString(url.Values{"collection": {"{}"}}.Encode()), nil) c.Assert(err, check.IsNil) readPath, writePath, pdhPath := pathFunc(newCollection) -- 2.30.2