[arvados] created: 2.6.0-277-gc18d038b8

git repository hosting git at public.arvados.org
Fri Jun 16 06:10:31 UTC 2023


        at  c18d038b87786aee25da9aac751193219e316c3a (commit)


commit c18d038b87786aee25da9aac751193219e316c3a
Author: Tom Clegg <tom at curii.com>
Date:   Fri Jun 16 02:06:35 2023 -0400

    20647: Test CORS preflight request routing.
    
    Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom at curii.com>

diff --git a/lib/controller/router/router_test.go b/lib/controller/router/router_test.go
index 0a85dcbf6..a8359a440 100644
--- a/lib/controller/router/router_test.go
+++ b/lib/controller/router/router_test.go
@@ -47,14 +47,15 @@ func (s *RouterSuite) SetUpTest(c *check.C) {
 func (s *RouterSuite) TestOptions(c *check.C) {
 	token := arvadostest.ActiveToken
 	for _, trial := range []struct {
-		comment      string // unparsed -- only used to help match test failures to trials
-		method       string
-		path         string
-		header       http.Header
-		body         string
-		shouldStatus int // zero value means 200
-		shouldCall   string
-		withOptions  interface{}
+		comment         string // unparsed -- only used to help match test failures to trials
+		method          string
+		path            string
+		header          http.Header
+		body            string
+		unauthenticated bool
+		shouldStatus    int // zero value means 200
+		shouldCall      string
+		withOptions     interface{}
 	}{
 		{
 			method:      "GET",
@@ -222,6 +223,22 @@ func (s *RouterSuite) TestOptions(c *check.C) {
 					Header: http.Header{"Authorization": {"Bearer " + arvadostest.ActiveToken}},
 					Path:   "/" + arvadostest.CompletedContainerUUID}},
 		},
+		{
+			comment:         "container log webdav OPTIONS for CORS",
+			unauthenticated: true,
+			method:          "OPTIONS",
+			path:            "/arvados/v1/container_requests/" + arvadostest.CompletedContainerRequestUUID + "/log/" + arvadostest.CompletedContainerUUID + "/",
+			header:          http.Header{"Access-Control-Request-Method": {"POST"}},
+			shouldCall:      "ContainerRequestLog",
+			withOptions: arvados.ContainerLogOptions{
+				UUID: arvadostest.CompletedContainerRequestUUID,
+				WebDAVOptions: arvados.WebDAVOptions{
+					Method: "OPTIONS",
+					Header: http.Header{
+						"Access-Control-Request-Method": {"POST"},
+					},
+					Path: "/" + arvadostest.CompletedContainerUUID + "/"}},
+		},
 		{
 			comment:    "container log webdav PROPFIND root",
 			method:     "PROPFIND",
@@ -273,7 +290,7 @@ func (s *RouterSuite) TestOptions(c *check.C) {
 		c.Logf("trial: %+v", trial)
 		comment := check.Commentf("trial comment: %s", trial.comment)
 
-		_, rr := doRequest(c, s.rtr, token, trial.method, trial.path, trial.header, bytes.NewBufferString(trial.body), nil)
+		_, rr := doRequest(c, s.rtr, token, trial.method, trial.path, !trial.unauthenticated, trial.header, bytes.NewBufferString(trial.body), nil)
 		if trial.shouldStatus == 0 {
 			c.Check(rr.Code, check.Equals, http.StatusOK, comment)
 		} else {
@@ -315,7 +332,7 @@ func (s *RouterIntegrationSuite) TestCollectionResponses(c *check.C) {
 
 	// Check "get collection" response has "kind" key
 	jresp := map[string]interface{}{}
-	_, rr := doRequest(c, s.rtr, token, "GET", `/arvados/v1/collections`, nil, bytes.NewBufferString(`{"include_trash":true}`), jresp)
+	_, rr := doRequest(c, s.rtr, token, "GET", `/arvados/v1/collections`, true, nil, bytes.NewBufferString(`{"include_trash":true}`), jresp)
 	c.Check(rr.Code, check.Equals, http.StatusOK)
 	c.Check(jresp["items"], check.FitsTypeOf, []interface{}{})
 	c.Check(jresp["kind"], check.Equals, "arvados#collectionList")
@@ -330,7 +347,7 @@ func (s *RouterIntegrationSuite) TestCollectionResponses(c *check.C) {
 		`,"select":["uuid"]`,
 	} {
 		jresp := map[string]interface{}{}
-		_, rr = doRequest(c, s.rtr, token, "GET", `/arvados/v1/collections`, nil, bytes.NewBufferString(`{"where":{"uuid":["`+arvadostest.FooCollection+`"]}`+selectj+`}`), jresp)
+		_, rr = doRequest(c, s.rtr, token, "GET", `/arvados/v1/collections`, true, nil, bytes.NewBufferString(`{"where":{"uuid":["`+arvadostest.FooCollection+`"]}`+selectj+`}`), jresp)
 		c.Check(rr.Code, check.Equals, http.StatusOK)
 		c.Check(jresp["items"], check.FitsTypeOf, []interface{}{})
 		c.Check(jresp["items_available"], check.FitsTypeOf, float64(0))
@@ -356,7 +373,7 @@ func (s *RouterIntegrationSuite) TestCollectionResponses(c *check.C) {
 
 	// Check "create collection" response has "kind" key
 	jresp = map[string]interface{}{}
-	_, rr = doRequest(c, s.rtr, token, "POST", `/arvados/v1/collections`, http.Header{"Content-Type": {"application/x-www-form-urlencoded"}}, bytes.NewBufferString(`ensure_unique_name=true`), jresp)
+	_, rr = doRequest(c, s.rtr, token, "POST", `/arvados/v1/collections`, true, http.Header{"Content-Type": {"application/x-www-form-urlencoded"}}, bytes.NewBufferString(`ensure_unique_name=true`), jresp)
 	c.Check(rr.Code, check.Equals, http.StatusOK)
 	c.Check(jresp["uuid"], check.FitsTypeOf, "")
 	c.Check(jresp["kind"], check.Equals, "arvados#collection")
@@ -381,11 +398,11 @@ func (s *RouterIntegrationSuite) TestMaxRequestSize(c *check.C) {
 		hdr := http.Header{"Content-Type": {"application/x-www-form-urlencoded"}}
 
 		body := bytes.NewBufferString(url.Values{"foo_bar": {okstr}}.Encode())
-		_, rr := doRequest(c, s.rtr, token, "POST", `/arvados/v1/collections`, hdr, body, nil)
+		_, rr := doRequest(c, s.rtr, token, "POST", `/arvados/v1/collections`, true, hdr, body, nil)
 		c.Check(rr.Code, check.Equals, http.StatusOK)
 
 		body = bytes.NewBufferString(url.Values{"foo_bar": {okstr + okstr}}.Encode())
-		_, rr = doRequest(c, s.rtr, token, "POST", `/arvados/v1/collections`, hdr, body, nil)
+		_, rr = doRequest(c, s.rtr, token, "POST", `/arvados/v1/collections`, true, hdr, body, nil)
 		c.Check(rr.Code, check.Equals, http.StatusRequestEntityTooLarge)
 	}
 }
@@ -394,7 +411,7 @@ func (s *RouterIntegrationSuite) TestContainerList(c *check.C) {
 	token := arvadostest.ActiveTokenV2
 
 	jresp := map[string]interface{}{}
-	_, rr := doRequest(c, s.rtr, token, "GET", `/arvados/v1/containers?limit=0`, nil, nil, jresp)
+	_, rr := doRequest(c, s.rtr, token, "GET", `/arvados/v1/containers?limit=0`, true, nil, nil, jresp)
 	c.Check(rr.Code, check.Equals, http.StatusOK)
 	c.Check(jresp["items_available"], check.FitsTypeOf, float64(0))
 	c.Check(jresp["items_available"].(float64) > 2, check.Equals, true)
@@ -402,14 +419,14 @@ func (s *RouterIntegrationSuite) TestContainerList(c *check.C) {
 	c.Check(jresp["items"], check.HasLen, 0)
 
 	jresp = map[string]interface{}{}
-	_, rr = doRequest(c, s.rtr, token, "GET", `/arvados/v1/containers?filters=[["uuid","in",[]]]`, nil, nil, jresp)
+	_, rr = doRequest(c, s.rtr, token, "GET", `/arvados/v1/containers?filters=[["uuid","in",[]]]`, true, nil, nil, jresp)
 	c.Check(rr.Code, check.Equals, http.StatusOK)
 	c.Check(jresp["items_available"], check.Equals, float64(0))
 	c.Check(jresp["items"], check.NotNil)
 	c.Check(jresp["items"], check.HasLen, 0)
 
 	jresp = map[string]interface{}{}
-	_, rr = doRequest(c, s.rtr, token, "GET", `/arvados/v1/containers?limit=2&select=["uuid","command"]`, nil, nil, jresp)
+	_, rr = doRequest(c, s.rtr, token, "GET", `/arvados/v1/containers?limit=2&select=["uuid","command"]`, true, nil, nil, jresp)
 	c.Check(rr.Code, check.Equals, http.StatusOK)
 	c.Check(jresp["items_available"], check.FitsTypeOf, float64(0))
 	c.Check(jresp["items_available"].(float64) > 2, check.Equals, true)
@@ -421,7 +438,7 @@ func (s *RouterIntegrationSuite) TestContainerList(c *check.C) {
 	c.Check(item0["mounts"], check.IsNil)
 
 	jresp = map[string]interface{}{}
-	_, rr = doRequest(c, s.rtr, token, "GET", `/arvados/v1/containers`, nil, nil, jresp)
+	_, rr = doRequest(c, s.rtr, token, "GET", `/arvados/v1/containers`, true, nil, nil, jresp)
 	c.Check(rr.Code, check.Equals, http.StatusOK)
 	c.Check(jresp["items_available"], check.FitsTypeOf, float64(0))
 	c.Check(jresp["items_available"].(float64) > 2, check.Equals, true)
@@ -439,31 +456,31 @@ func (s *RouterIntegrationSuite) TestContainerLock(c *check.C) {
 	token := arvadostest.AdminToken
 
 	jresp := map[string]interface{}{}
-	_, rr := doRequest(c, s.rtr, token, "POST", "/arvados/v1/containers/"+uuid+"/lock", nil, nil, jresp)
+	_, rr := doRequest(c, s.rtr, token, "POST", "/arvados/v1/containers/"+uuid+"/lock", true, nil, nil, jresp)
 	c.Check(rr.Code, check.Equals, http.StatusOK)
 	c.Check(jresp["uuid"], check.HasLen, 27)
 	c.Check(jresp["state"], check.Equals, "Locked")
 
-	_, rr = doRequest(c, s.rtr, token, "POST", "/arvados/v1/containers/"+uuid+"/lock", nil, nil, nil)
+	_, rr = doRequest(c, s.rtr, token, "POST", "/arvados/v1/containers/"+uuid+"/lock", true, nil, nil, nil)
 	c.Check(rr.Code, check.Equals, http.StatusUnprocessableEntity)
 	c.Check(rr.Body.String(), check.Not(check.Matches), `.*"uuid":.*`)
 
 	jresp = map[string]interface{}{}
-	_, rr = doRequest(c, s.rtr, token, "POST", "/arvados/v1/containers/"+uuid+"/unlock", nil, nil, jresp)
+	_, rr = doRequest(c, s.rtr, token, "POST", "/arvados/v1/containers/"+uuid+"/unlock", true, nil, nil, jresp)
 	c.Check(rr.Code, check.Equals, http.StatusOK)
 	c.Check(jresp["uuid"], check.HasLen, 27)
 	c.Check(jresp["state"], check.Equals, "Queued")
 	c.Check(jresp["environment"], check.IsNil)
 
 	jresp = map[string]interface{}{}
-	_, rr = doRequest(c, s.rtr, token, "POST", "/arvados/v1/containers/"+uuid+"/unlock", nil, nil, jresp)
+	_, rr = doRequest(c, s.rtr, token, "POST", "/arvados/v1/containers/"+uuid+"/unlock", true, nil, nil, jresp)
 	c.Check(rr.Code, check.Equals, http.StatusUnprocessableEntity)
 	c.Check(jresp["uuid"], check.IsNil)
 }
 
 func (s *RouterIntegrationSuite) TestWritableBy(c *check.C) {
 	jresp := map[string]interface{}{}
-	_, rr := doRequest(c, s.rtr, arvadostest.ActiveTokenV2, "GET", `/arvados/v1/users/`+arvadostest.ActiveUserUUID, nil, nil, jresp)
+	_, rr := doRequest(c, s.rtr, arvadostest.ActiveTokenV2, "GET", `/arvados/v1/users/`+arvadostest.ActiveUserUUID, true, nil, nil, jresp)
 	c.Check(rr.Code, check.Equals, http.StatusOK)
 	c.Check(jresp["writable_by"], check.DeepEquals, []interface{}{"zzzzz-tpzed-000000000000000", "zzzzz-tpzed-xurymjxw79nv3jz", "zzzzz-j7d0g-48foin4vonvc2at"})
 }
@@ -473,7 +490,7 @@ func (s *RouterIntegrationSuite) TestFullTimestampsInResponse(c *check.C) {
 	token := arvadostest.ActiveTokenV2
 
 	jresp := map[string]interface{}{}
-	_, rr := doRequest(c, s.rtr, token, "GET", `/arvados/v1/collections/`+uuid, nil, nil, jresp)
+	_, rr := doRequest(c, s.rtr, token, "GET", `/arvados/v1/collections/`+uuid, true, nil, nil, jresp)
 	c.Check(rr.Code, check.Equals, http.StatusOK)
 	c.Check(jresp["uuid"], check.Equals, uuid)
 	expectNS := map[string]int{
@@ -501,7 +518,7 @@ func (s *RouterIntegrationSuite) TestSelectParam(c *check.C) {
 		j, err := json.Marshal(sel)
 		c.Assert(err, check.IsNil)
 		jresp := map[string]interface{}{}
-		_, rr := doRequest(c, s.rtr, token, "GET", "/arvados/v1/containers/"+uuid+"?select="+string(j), nil, nil, jresp)
+		_, rr := doRequest(c, s.rtr, token, "GET", "/arvados/v1/containers/"+uuid+"?select="+string(j), true, nil, nil, jresp)
 		c.Check(rr.Code, check.Equals, http.StatusOK)
 
 		c.Check(jresp["kind"], check.Equals, "arvados#container")
@@ -521,9 +538,9 @@ func (s *RouterIntegrationSuite) TestSelectParam(c *check.C) {
 		jresp := map[string]interface{}{}
 		var rr *httptest.ResponseRecorder
 		if method == "PUT" {
-			_, rr = doRequest(c, s.rtr, token, method, "/arvados/v1/collections/"+uuid+"?select="+string(j), nil, bytes.NewReader([]byte(reqBody)), jresp)
+			_, rr = doRequest(c, s.rtr, token, method, "/arvados/v1/collections/"+uuid+"?select="+string(j), true, nil, bytes.NewReader([]byte(reqBody)), jresp)
 		} else {
-			_, rr = doRequest(c, s.rtr, token, method, "/arvados/v1/collections?select="+string(j), nil, bytes.NewReader([]byte(reqBody)), jresp)
+			_, rr = doRequest(c, s.rtr, token, method, "/arvados/v1/collections?select="+string(j), true, nil, bytes.NewReader([]byte(reqBody)), jresp)
 		}
 		c.Check(rr.Code, check.Equals, http.StatusOK)
 		c.Check(jresp["kind"], check.Equals, "arvados#collection")
@@ -534,7 +551,7 @@ func (s *RouterIntegrationSuite) TestSelectParam(c *check.C) {
 }
 
 func (s *RouterIntegrationSuite) TestHEAD(c *check.C) {
-	_, rr := doRequest(c, s.rtr, arvadostest.ActiveTokenV2, "HEAD", "/arvados/v1/containers/"+arvadostest.QueuedContainerUUID, nil, nil, nil)
+	_, rr := doRequest(c, s.rtr, arvadostest.ActiveTokenV2, "HEAD", "/arvados/v1/containers/"+arvadostest.QueuedContainerUUID, true, nil, nil, nil)
 	c.Check(rr.Code, check.Equals, http.StatusOK)
 }
 
@@ -606,15 +623,21 @@ func (s *RouterIntegrationSuite) TestCORS(c *check.C) {
 	}
 }
 
-func doRequest(c *check.C, rtr http.Handler, token, method, path string, hdrs http.Header, body io.Reader, jresp map[string]interface{}) (*http.Request, *httptest.ResponseRecorder) {
+func doRequest(c *check.C, rtr http.Handler, token, method, path string, auth bool, hdrs http.Header, body io.Reader, jresp map[string]interface{}) (*http.Request, *httptest.ResponseRecorder) {
 	req := httptest.NewRequest(method, path, body)
 	for k, v := range hdrs {
 		req.Header[k] = v
 	}
-	req.Header.Set("Authorization", "Bearer "+token)
+	if auth {
+		req.Header.Set("Authorization", "Bearer "+token)
+	}
 	rr := httptest.NewRecorder()
 	rtr.ServeHTTP(rr, req)
-	c.Logf("response body: %s", rr.Body.String())
+	respbody := rr.Body.String()
+	if len(respbody) > 10000 {
+		respbody = respbody[:10000] + "[...]"
+	}
+	c.Logf("response body: %s", respbody)
 	if jresp != nil {
 		err := json.Unmarshal(rr.Body.Bytes(), &jresp)
 		c.Check(err, check.IsNil)

commit e7c3a477fc4f75321671a6f601cc07a9180e4646
Author: Tom Clegg <tom at curii.com>
Date:   Fri Jun 16 02:05:59 2023 -0400

    20647: Fix CORS preflight request handling.
    
    Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom at curii.com>

diff --git a/lib/controller/localdb/container_gateway.go b/lib/controller/localdb/container_gateway.go
index d17f2e10d..9526c01f8 100644
--- a/lib/controller/localdb/container_gateway.go
+++ b/lib/controller/localdb/container_gateway.go
@@ -31,6 +31,7 @@ import (
 	"git.arvados.org/arvados.git/sdk/go/auth"
 	"git.arvados.org/arvados.git/sdk/go/ctxlog"
 	"git.arvados.org/arvados.git/sdk/go/httpserver"
+	keepweb "git.arvados.org/arvados.git/services/keep-web"
 	"github.com/hashicorp/yamux"
 	"golang.org/x/net/webdav"
 )
@@ -78,6 +79,16 @@ var (
 // ...or the request may be handled locally using an empty-collection
 // stub.
 func (conn *Conn) ContainerRequestLog(ctx context.Context, opts arvados.ContainerLogOptions) (http.Handler, error) {
+	if opts.Method == "OPTIONS" && opts.Header.Get("Access-Control-Request-Method") != "" {
+		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+			if !keepweb.ServeCORSPreflight(w, opts.Header) {
+				// Inconceivable.  We already checked
+				// for the only condition where
+				// ServeCORSPreflight returns false.
+				httpserver.Error(w, "unhandled CORS preflight request", http.StatusInternalServerError)
+			}
+		}), nil
+	}
 	cr, err := conn.railsProxy.ContainerRequestGet(ctx, arvados.GetOptions{UUID: opts.UUID, Select: []string{"uuid", "container_uuid", "log_uuid"}})
 	if err != nil {
 		if se := httpserver.HTTPStatusError(nil); errors.As(err, &se) && se.HTTPStatus() == http.StatusUnauthorized {
diff --git a/lib/controller/localdb/container_gateway_test.go b/lib/controller/localdb/container_gateway_test.go
index dc8a8cea0..f7310e8de 100644
--- a/lib/controller/localdb/container_gateway_test.go
+++ b/lib/controller/localdb/container_gateway_test.go
@@ -6,6 +6,7 @@ package localdb
 
 import (
 	"bytes"
+	"context"
 	"crypto/hmac"
 	"crypto/sha256"
 	"fmt"
@@ -28,6 +29,7 @@ import (
 	"git.arvados.org/arvados.git/sdk/go/arvados"
 	"git.arvados.org/arvados.git/sdk/go/arvadosclient"
 	"git.arvados.org/arvados.git/sdk/go/arvadostest"
+	"git.arvados.org/arvados.git/sdk/go/auth"
 	"git.arvados.org/arvados.git/sdk/go/ctxlog"
 	"git.arvados.org/arvados.git/sdk/go/httpserver"
 	"git.arvados.org/arvados.git/sdk/go/keepclient"
@@ -298,9 +300,16 @@ func (s *ContainerGatewaySuite) TestContainerRequestLogViaTunnel(c *check.C) {
 			defer delete(s.cluster.Services.Controller.InternalURLs, *forceInternalURLForTest)
 		}
 
+		r, err := http.NewRequestWithContext(s.userctx, "GET", "https://controller.example/arvados/v1/container_requests/"+s.reqUUID+"/log/"+s.ctrUUID+"/stderr.txt", nil)
+		c.Assert(err, check.IsNil)
+		r.Header.Set("Authorization", "Bearer "+arvadostest.ActiveTokenV2)
 		handler, err := s.localdb.ContainerRequestLog(s.userctx, arvados.ContainerLogOptions{
-			UUID:          s.reqUUID,
-			WebDAVOptions: arvados.WebDAVOptions{Path: "/" + s.ctrUUID + "/stderr.txt"},
+			UUID: s.reqUUID,
+			WebDAVOptions: arvados.WebDAVOptions{
+				Method: "GET",
+				Header: r.Header,
+				Path:   "/" + s.ctrUUID + "/stderr.txt",
+			},
 		})
 		if broken {
 			c.Check(err, check.ErrorMatches, `.*tunnel endpoint is invalid.*`)
@@ -308,9 +317,6 @@ func (s *ContainerGatewaySuite) TestContainerRequestLogViaTunnel(c *check.C) {
 		}
 		c.Check(err, check.IsNil)
 		c.Assert(handler, check.NotNil)
-		r, err := http.NewRequestWithContext(s.userctx, "GET", "https://controller.example/arvados/v1/container_requests/"+s.reqUUID+"/log/"+s.ctrUUID+"/stderr.txt", nil)
-		c.Assert(err, check.IsNil)
-		r.Header.Set("Authorization", "Bearer "+arvadostest.ActiveTokenV2)
 		rec := httptest.NewRecorder()
 		handler.ServeHTTP(rec, r)
 		resp := rec.Result()
@@ -334,12 +340,13 @@ func (s *ContainerGatewaySuite) TestContainerRequestLogViaKeepWeb(c *check.C) {
 
 func (s *ContainerGatewaySuite) testContainerRequestLog(c *check.C) {
 	for _, trial := range []struct {
-		method       string
-		path         string
-		header       http.Header
-		expectStatus int
-		expectBodyRe string
-		expectHeader http.Header
+		method          string
+		path            string
+		header          http.Header
+		unauthenticated bool
+		expectStatus    int
+		expectBodyRe    string
+		expectHeader    http.Header
 	}{
 		{
 			method:       "GET",
@@ -373,6 +380,22 @@ func (s *ContainerGatewaySuite) testContainerRequestLog(c *check.C) {
 				"Allow": {"OPTIONS, LOCK, GET, HEAD, POST, DELETE, PROPPATCH, COPY, MOVE, UNLOCK, PROPFIND, PUT"},
 			},
 		},
+		{
+			method:          "OPTIONS",
+			path:            s.ctrUUID + "/stderr.txt",
+			unauthenticated: true,
+			header: http.Header{
+				"Access-Control-Request-Method": {"POST"},
+			},
+			expectStatus: http.StatusOK,
+			expectBodyRe: "",
+			expectHeader: http.Header{
+				"Access-Control-Allow-Headers": {"Authorization, Content-Type, Range, Depth, Destination, If, Lock-Token, Overwrite, Timeout, Cache-Control"},
+				"Access-Control-Allow-Methods": {"COPY, DELETE, GET, LOCK, MKCOL, MOVE, OPTIONS, POST, PROPFIND, PROPPATCH, PUT, RMCOL, UNLOCK"},
+				"Access-Control-Allow-Origin":  {"*"},
+				"Access-Control-Max-Age":       {"86400"},
+			},
+		},
 		{
 			method:       "PROPFIND",
 			path:         s.ctrUUID + "/",
@@ -411,17 +434,25 @@ func (s *ContainerGatewaySuite) testContainerRequestLog(c *check.C) {
 		},
 	} {
 		c.Logf("trial %#v", trial)
-		handler, err := s.localdb.ContainerRequestLog(s.userctx, arvados.ContainerLogOptions{
-			UUID:          s.reqUUID,
-			WebDAVOptions: arvados.WebDAVOptions{Path: "/" + trial.path},
-		})
-		c.Assert(err, check.IsNil)
-		c.Assert(handler, check.NotNil)
-		r, err := http.NewRequestWithContext(s.userctx, trial.method, "https://controller.example/arvados/v1/container_requests/"+s.reqUUID+"/log/"+trial.path, nil)
+		ctx := s.userctx
+		if trial.unauthenticated {
+			ctx = auth.NewContext(context.Background(), auth.CredentialsFromRequest(&http.Request{URL: &url.URL{}, Header: http.Header{}}))
+		}
+		r, err := http.NewRequestWithContext(ctx, trial.method, "https://controller.example/arvados/v1/container_requests/"+s.reqUUID+"/log/"+trial.path, nil)
 		c.Assert(err, check.IsNil)
 		for k := range trial.header {
 			r.Header.Set(k, trial.header.Get(k))
 		}
+		handler, err := s.localdb.ContainerRequestLog(ctx, arvados.ContainerLogOptions{
+			UUID: s.reqUUID,
+			WebDAVOptions: arvados.WebDAVOptions{
+				Method: trial.method,
+				Header: r.Header,
+				Path:   "/" + trial.path,
+			},
+		})
+		c.Assert(err, check.IsNil)
+		c.Assert(handler, check.NotNil)
 		rec := httptest.NewRecorder()
 		handler.ServeHTTP(rec, r)
 		resp := rec.Result()
diff --git a/services/keep-web/handler.go b/services/keep-web/handler.go
index 27981c487..3cdaf5d2b 100644
--- a/services/keep-web/handler.go
+++ b/services/keep-web/handler.go
@@ -182,15 +182,7 @@ func (h *handler) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) {
 
 	w := httpserver.WrapResponseWriter(wOrig)
 
-	if method := r.Header.Get("Access-Control-Request-Method"); method != "" && r.Method == "OPTIONS" {
-		if !browserMethod[method] && !webdavMethod[method] {
-			w.WriteHeader(http.StatusMethodNotAllowed)
-			return
-		}
-		w.Header().Set("Access-Control-Allow-Headers", corsAllowHeadersHeader)
-		w.Header().Set("Access-Control-Allow-Methods", "COPY, DELETE, GET, LOCK, MKCOL, MOVE, OPTIONS, POST, PROPFIND, PROPPATCH, PUT, RMCOL, UNLOCK")
-		w.Header().Set("Access-Control-Allow-Origin", "*")
-		w.Header().Set("Access-Control-Max-Age", "86400")
+	if r.Method == "OPTIONS" && ServeCORSPreflight(w, r.Header) {
 		return
 	}
 
@@ -949,3 +941,19 @@ func (h *handler) determineCollection(fs arvados.CustomFileSystem, path string)
 	}
 	return nil, ""
 }
+
+func ServeCORSPreflight(w http.ResponseWriter, header http.Header) bool {
+	method := header.Get("Access-Control-Request-Method")
+	if method == "" {
+		return false
+	}
+	if !browserMethod[method] && !webdavMethod[method] {
+		w.WriteHeader(http.StatusMethodNotAllowed)
+		return true
+	}
+	w.Header().Set("Access-Control-Allow-Headers", corsAllowHeadersHeader)
+	w.Header().Set("Access-Control-Allow-Methods", "COPY, DELETE, GET, LOCK, MKCOL, MOVE, OPTIONS, POST, PROPFIND, PROPPATCH, PUT, RMCOL, UNLOCK")
+	w.Header().Set("Access-Control-Allow-Origin", "*")
+	w.Header().Set("Access-Control-Max-Age", "86400")
+	return true
+}

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list