Merge branch '3781-browser-friendly-servers' refs #3781
[arvados.git] / services / keepproxy / keepproxy_test.go
index 5944b2c21d0d27d776c6ab54cc3d444160aaa16f..0ac843f3250c1c5b25d316de424df630c00d0b13 100644 (file)
@@ -14,6 +14,7 @@ import (
        "net/url"
        "os"
        "os/exec"
+       "strings"
        "testing"
        "time"
 )
@@ -34,6 +35,25 @@ func pythonDir() string {
        return fmt.Sprintf("%s/../../sdk/python/tests", cwd)
 }
 
+// Wait (up to 1 second) for keepproxy to listen on a port. This
+// avoids a race condition where we hit a "connection refused" error
+// because we start testing the proxy too soon.
+func waitForListener() {
+       const (ms = 5)
+       for i := 0; listener == nil && i < 1000; i += ms {
+               time.Sleep(ms * time.Millisecond)
+       }
+       if listener == nil {
+               log.Fatalf("Timed out waiting for listener to start")
+       }
+}
+
+func closeListener() {
+       if listener != nil {
+               listener.Close()
+       }
+}
+
 func (s *ServerRequiredSuite) SetUpSuite(c *C) {
        cwd, _ := os.Getwd()
        defer os.Chdir(cwd)
@@ -124,11 +144,14 @@ func runProxy(c *C, args []string, token string, port int) keepclient.KeepClient
        os.Setenv("ARVADOS_KEEP_PROXY", fmt.Sprintf("http://localhost:%v", port))
        os.Setenv("ARVADOS_API_TOKEN", token)
        arv, err := arvadosclient.MakeArvadosClient()
+       c.Assert(err, Equals, nil)
        kc, err := keepclient.MakeKeepClient(&arv)
+       c.Assert(err, Equals, nil)
        c.Check(kc.Using_proxy, Equals, true)
        c.Check(len(kc.ServiceRoots()), Equals, 1)
-       c.Check(kc.ServiceRoots()[0], Equals, fmt.Sprintf("http://localhost:%v", port))
-       c.Check(err, Equals, nil)
+       for _, root := range(kc.ServiceRoots()) {
+               c.Check(root, Equals, fmt.Sprintf("http://localhost:%v", port))
+       }
        os.Setenv("ARVADOS_KEEP_PROXY", "")
        log.Print("keepclient created")
        return kc
@@ -146,16 +169,20 @@ func (s *ServerRequiredSuite) TestPutAskGet(c *C) {
 
        os.Setenv("ARVADOS_EXTERNAL_CLIENT", "true")
        arv, err := arvadosclient.MakeArvadosClient()
+       c.Assert(err, Equals, nil)
        kc, err := keepclient.MakeKeepClient(&arv)
+       c.Assert(err, Equals, nil)
        c.Check(kc.Arvados.External, Equals, true)
        c.Check(kc.Using_proxy, Equals, true)
        c.Check(len(kc.ServiceRoots()), Equals, 1)
-       c.Check(kc.ServiceRoots()[0], Equals, "http://localhost:29950")
-       c.Check(err, Equals, nil)
+       for _, root := range kc.ServiceRoots() {
+               c.Check(root, Equals, "http://localhost:29950")
+       }
        os.Setenv("ARVADOS_EXTERNAL_CLIENT", "")
        log.Print("keepclient created")
 
-       defer listener.Close()
+       waitForListener()
+       defer closeListener()
 
        hash := fmt.Sprintf("%x", md5.Sum([]byte("foo")))
        var hash2 string
@@ -196,10 +223,11 @@ func (s *ServerRequiredSuite) TestPutAskGet(c *C) {
 }
 
 func (s *ServerRequiredSuite) TestPutAskGetForbidden(c *C) {
-       log.Print("TestPutAndGet start")
+       log.Print("TestPutAskGetForbidden start")
 
        kc := runProxy(c, []string{"keepproxy"}, "123abc", 29951)
-       defer listener.Close()
+       waitForListener()
+       defer closeListener()
 
        log.Print("keepclient created")
 
@@ -233,14 +261,15 @@ func (s *ServerRequiredSuite) TestPutAskGetForbidden(c *C) {
                log.Print("Get")
        }
 
-       log.Print("TestPutAndGetForbidden done")
+       log.Print("TestPutAskGetForbidden done")
 }
 
 func (s *ServerRequiredSuite) TestGetDisabled(c *C) {
        log.Print("TestGetDisabled start")
 
        kc := runProxy(c, []string{"keepproxy", "-no-get"}, "4axaw8zxe0qm22wa6urpp5nskcne8z88cvbupv653y1njyi05h", 29952)
-       defer listener.Close()
+       waitForListener()
+       defer closeListener()
 
        hash := fmt.Sprintf("%x", md5.Sum([]byte("baz")))
 
@@ -279,7 +308,8 @@ func (s *ServerRequiredSuite) TestPutDisabled(c *C) {
        log.Print("TestPutDisabled start")
 
        kc := runProxy(c, []string{"keepproxy", "-no-put"}, "4axaw8zxe0qm22wa6urpp5nskcne8z88cvbupv653y1njyi05h", 29953)
-       defer listener.Close()
+       waitForListener()
+       defer closeListener()
 
        {
                hash2, rep, err := kc.PutB([]byte("quux"))
@@ -291,3 +321,56 @@ func (s *ServerRequiredSuite) TestPutDisabled(c *C) {
 
        log.Print("TestPutDisabled done")
 }
+
+func (s *ServerRequiredSuite) TestCorsHeaders(c *C) {
+       runProxy(c, []string{"keepproxy"}, "4axaw8zxe0qm22wa6urpp5nskcne8z88cvbupv653y1njyi05h", 29954)
+       waitForListener()
+       defer closeListener()
+
+       {
+               client := http.Client{}
+               req, err := http.NewRequest("OPTIONS",
+                       fmt.Sprintf("http://localhost:29954/%x+3",
+                               md5.Sum([]byte("foo"))),
+                       nil)
+               req.Header.Add("Access-Control-Request-Method", "PUT")
+               req.Header.Add("Access-Control-Request-Headers", "Authorization, X-Keep-Desired-Replicas")
+               resp, err := client.Do(req)
+               c.Check(err, Equals, nil)
+               c.Check(resp.StatusCode, Equals, 200)
+               body, err := ioutil.ReadAll(resp.Body)
+               c.Check(string(body), Equals, "")
+               c.Check(resp.Header.Get("Access-Control-Allow-Methods"), Equals, "GET, HEAD, POST, PUT, OPTIONS")
+               c.Check(resp.Header.Get("Access-Control-Allow-Origin"), Equals, "*")
+       }
+
+       {
+               resp, err := http.Get(
+                       fmt.Sprintf("http://localhost:29954/%x+3",
+                               md5.Sum([]byte("foo"))))
+               c.Check(err, Equals, nil)
+               c.Check(resp.Header.Get("Access-Control-Allow-Headers"), Equals, "Authorization, Content-Length, Content-Type, X-Keep-Desired-Replicas")
+               c.Check(resp.Header.Get("Access-Control-Allow-Origin"), Equals, "*")
+       }
+}
+
+func (s *ServerRequiredSuite) TestPostWithoutHash(c *C) {
+       runProxy(c, []string{"keepproxy"}, "4axaw8zxe0qm22wa6urpp5nskcne8z88cvbupv653y1njyi05h", 29955)
+       waitForListener()
+       defer closeListener()
+
+       {
+               client := http.Client{}
+               req, err := http.NewRequest("POST",
+                       "http://localhost:29955/",
+                       strings.NewReader("qux"))
+               req.Header.Add("Authorization", "OAuth2 4axaw8zxe0qm22wa6urpp5nskcne8z88cvbupv653y1njyi05h")
+               req.Header.Add("Content-Type", "application/octet-stream")
+               resp, err := client.Do(req)
+               c.Check(err, Equals, nil)
+               body, err := ioutil.ReadAll(resp.Body)
+               c.Check(err, Equals, nil)
+               c.Check(string(body), Equals,
+                       fmt.Sprintf("%x+%d", md5.Sum([]byte("qux")), 3))
+       }
+}