21225: Skip clipboard test in firefox
[arvados.git] / services / keepstore / router_test.go
index ee7be4768c91499e667c8ba50aa512c7b3a930a3..215033b48ed9f00054b1da713a890b96691f4610 100644 (file)
@@ -78,22 +78,26 @@ func (s *routerSuite) TestBlockRead_Token(c *C) {
        resp := call(router, "GET", "http://example/"+locSigned, "", nil, nil)
        c.Check(resp.Code, Equals, http.StatusUnauthorized)
        c.Check(resp.Body.String(), Matches, "no token provided in Authorization header\n")
+       checkCORSHeaders(c, resp.Header())
 
        // Different token => invalid signature
        resp = call(router, "GET", "http://example/"+locSigned, "badtoken", nil, nil)
        c.Check(resp.Code, Equals, http.StatusBadRequest)
        c.Check(resp.Body.String(), Equals, "invalid signature\n")
+       checkCORSHeaders(c, resp.Header())
 
        // Correct token
        resp = call(router, "GET", "http://example/"+locSigned, arvadostest.ActiveTokenV2, nil, nil)
        c.Check(resp.Code, Equals, http.StatusOK)
        c.Check(resp.Body.String(), Equals, "foo")
+       checkCORSHeaders(c, resp.Header())
 
        // HEAD
        resp = call(router, "HEAD", "http://example/"+locSigned, arvadostest.ActiveTokenV2, nil, nil)
        c.Check(resp.Code, Equals, http.StatusOK)
        c.Check(resp.Result().ContentLength, Equals, int64(3))
        c.Check(resp.Body.String(), Equals, "")
+       checkCORSHeaders(c, resp.Header())
 }
 
 // As a special case we allow HEAD requests that only provide a hash
@@ -165,13 +169,16 @@ func (s *routerSuite) TestBlockRead_ChecksumMismatch(c *C) {
                }
                c.Check(resp.Body.Len(), Not(Equals), len(gooddata))
                c.Check(resp.Result().ContentLength, Equals, int64(len(gooddata)))
+               checkCORSHeaders(c, resp.Header())
 
                resp = call(router, "HEAD", "http://example/"+locSigned, arvadostest.ActiveTokenV2, nil, nil)
                c.Check(resp.Code, Equals, http.StatusBadGateway)
+               checkCORSHeaders(c, resp.Header())
 
                hashSigned := router.keepstore.signLocator(arvadostest.ActiveTokenV2, hash)
                resp = call(router, "HEAD", "http://example/"+hashSigned, arvadostest.ActiveTokenV2, nil, nil)
                c.Check(resp.Code, Equals, http.StatusBadGateway)
+               checkCORSHeaders(c, resp.Header())
        }
 }
 
@@ -181,6 +188,7 @@ func (s *routerSuite) TestBlockWrite(c *C) {
 
        resp := call(router, "PUT", "http://example/"+fooHash, arvadostest.ActiveTokenV2, []byte("foo"), nil)
        c.Check(resp.Code, Equals, http.StatusOK)
+       checkCORSHeaders(c, resp.Header())
        locator := strings.TrimSpace(resp.Body.String())
 
        resp = call(router, "GET", "http://example/"+locator, arvadostest.ActiveTokenV2, nil, nil)
@@ -192,7 +200,7 @@ func (s *routerSuite) TestBlockWrite_Headers(c *C) {
        router, cancel := testRouter(c, s.cluster, nil)
        defer cancel()
 
-       resp := call(router, "PUT", "http://example/"+fooHash, arvadostest.ActiveTokenV2, []byte("foo"), http.Header{"X-Arvados-Replicas-Desired": []string{"2"}})
+       resp := call(router, "PUT", "http://example/"+fooHash, arvadostest.ActiveTokenV2, []byte("foo"), http.Header{"X-Keep-Desired-Replicas": []string{"2"}})
        c.Check(resp.Code, Equals, http.StatusOK)
        c.Check(resp.Header().Get("X-Keep-Replicas-Stored"), Equals, "1")
        c.Check(sortCommaSeparated(resp.Header().Get("X-Keep-Storage-Classes-Confirmed")), Equals, "testclass1=1")
@@ -373,6 +381,13 @@ func (s *routerSuite) TestVolumeErrorStatusCode(c *C) {
        c.Check(resp.Code, Equals, http.StatusBadGateway)
        c.Check(resp.Body.String(), Equals, "test error\n")
 
+       router.keepstore.mountsW[0].volume.(*stubVolume).blockRead = func(_ context.Context, hash string, w io.WriterAt) error {
+               return errors.New("no http status provided")
+       }
+       resp = call(router, "GET", "http://example/"+locSigned, arvadostest.ActiveTokenV2, nil, nil)
+       c.Check(resp.Code, Equals, http.StatusInternalServerError)
+       c.Check(resp.Body.String(), Equals, "no http status provided\n")
+
        c.Assert(router.keepstore.mountsW[1].volume.BlockWrite(context.Background(), barHash, []byte("bar")), IsNil)
 
        // If the requested block is available on the second volume,
@@ -462,7 +477,6 @@ func (s *routerSuite) TestIndex(c *C) {
                c.Check(resp.Code, Equals, http.StatusOK)
                c.Check(strings.Split(resp.Body.String(), "\n"), HasLen, 5)
        }
-
 }
 
 // Check that the context passed to a volume method gets cancelled
@@ -493,6 +507,19 @@ func (s *routerSuite) TestCancelOnDisconnect(c *C) {
        c.Check(resp.Code, Equals, 499)
 }
 
+func (s *routerSuite) TestCORSPreflight(c *C) {
+       router, cancel := testRouter(c, s.cluster, nil)
+       defer cancel()
+
+       for _, path := range []string{"/", "/whatever", "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+123"} {
+               c.Logf("=== %s", path)
+               resp := call(router, http.MethodOptions, "http://example"+path, arvadostest.ActiveTokenV2, nil, nil)
+               c.Check(resp.Code, Equals, http.StatusOK)
+               c.Check(resp.Body.String(), Equals, "")
+               checkCORSHeaders(c, resp.Header())
+       }
+}
+
 func call(handler http.Handler, method, path, tok string, body []byte, hdr http.Header) *httptest.ResponseRecorder {
        resp := httptest.NewRecorder()
        req, err := http.NewRequest(method, path, bytes.NewReader(body))
@@ -508,3 +535,10 @@ func call(handler http.Handler, method, path, tok string, body []byte, hdr http.
        handler.ServeHTTP(resp, req)
        return resp
 }
+
+func checkCORSHeaders(c *C, h http.Header) {
+       c.Check(h.Get("Access-Control-Allow-Methods"), Equals, "GET, HEAD, PUT, OPTIONS")
+       c.Check(h.Get("Access-Control-Allow-Origin"), Equals, "*")
+       c.Check(h.Get("Access-Control-Allow-Headers"), Equals, "Authorization, Content-Length, Content-Type, X-Keep-Desired-Replicas, X-Keep-Signature, X-Keep-Storage-Classes")
+       c.Check(h.Get("Access-Control-Expose-Headers"), Equals, "X-Keep-Locator, X-Keep-Replicas-Stored, X-Keep-Storage-Classes-Confirmed")
+}