forked from TrueCloudLab/frostfs-s3-gw
[#641] Rework CORS bucket behaviour
Signed-off-by: Marina Biryukova <m.biryukova@yadro.com>
This commit is contained in:
parent
1fac8e3ef2
commit
9edec7d573
16 changed files with 490 additions and 138 deletions
|
@ -1,12 +1,19 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
@ -37,26 +44,14 @@ func TestCORSOriginWildcard(t *testing.T) {
|
|||
hc.Handler().CreateBucketHandler(w, r)
|
||||
assertStatus(t, w, http.StatusOK)
|
||||
|
||||
w, r = prepareTestPayloadRequest(hc, bktName, "", strings.NewReader(body))
|
||||
ctx = middleware.SetBox(r.Context(), &middleware.Box{AccessBox: box})
|
||||
r = r.WithContext(ctx)
|
||||
hc.Handler().PutBucketCorsHandler(w, r)
|
||||
assertStatus(t, w, http.StatusOK)
|
||||
putBucketCORS(hc, bktName, body)
|
||||
|
||||
w, r = prepareTestPayloadRequest(hc, bktName, "", nil)
|
||||
hc.Handler().GetBucketCorsHandler(w, r)
|
||||
assertStatus(t, w, http.StatusOK)
|
||||
getBucketCORS(hc, bktName)
|
||||
|
||||
hc.config.useDefaultXMLNS = true
|
||||
w, r = prepareTestPayloadRequest(hc, bktName, "", strings.NewReader(bodyNoXmlns))
|
||||
ctx = middleware.SetBox(r.Context(), &middleware.Box{AccessBox: box})
|
||||
r = r.WithContext(ctx)
|
||||
hc.Handler().PutBucketCorsHandler(w, r)
|
||||
assertStatus(t, w, http.StatusOK)
|
||||
putBucketCORS(hc, bktName, bodyNoXmlns)
|
||||
|
||||
w, r = prepareTestPayloadRequest(hc, bktName, "", nil)
|
||||
hc.Handler().GetBucketCorsHandler(w, r)
|
||||
assertStatus(t, w, http.StatusOK)
|
||||
getBucketCORS(hc, bktName)
|
||||
}
|
||||
|
||||
func TestPreflight(t *testing.T) {
|
||||
|
@ -170,11 +165,7 @@ func TestPreflightWildcardOrigin(t *testing.T) {
|
|||
hc.Handler().CreateBucketHandler(w, r)
|
||||
assertStatus(t, w, http.StatusOK)
|
||||
|
||||
w, r = prepareTestPayloadRequest(hc, bktName, "", strings.NewReader(body))
|
||||
ctx = middleware.SetBox(r.Context(), &middleware.Box{AccessBox: box})
|
||||
r = r.WithContext(ctx)
|
||||
hc.Handler().PutBucketCorsHandler(w, r)
|
||||
assertStatus(t, w, http.StatusOK)
|
||||
putBucketCORS(hc, bktName, body)
|
||||
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
|
@ -236,3 +227,183 @@ func TestPreflightWildcardOrigin(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteAllCORSVersions(t *testing.T) {
|
||||
body := `
|
||||
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
|
||||
<CORSRule>
|
||||
<AllowedMethod>GET</AllowedMethod>
|
||||
<AllowedMethod>PUT</AllowedMethod>
|
||||
<AllowedOrigin>*</AllowedOrigin>
|
||||
<AllowedHeader>*</AllowedHeader>
|
||||
</CORSRule>
|
||||
</CORSConfiguration>
|
||||
`
|
||||
hc := prepareHandlerContext(t)
|
||||
|
||||
bktName := "bucket-delete-all-cors-version"
|
||||
createBucket(hc, bktName)
|
||||
require.Len(t, hc.tp.Objects(), 0)
|
||||
|
||||
for range 5 {
|
||||
putBucketCORS(hc, bktName, body)
|
||||
}
|
||||
|
||||
require.Len(t, hc.tp.Objects(), 5)
|
||||
|
||||
deleteBucketCORS(hc, bktName)
|
||||
require.Len(t, hc.tp.Objects(), 0)
|
||||
}
|
||||
|
||||
func TestGetLatestCORSVersion(t *testing.T) {
|
||||
bodyTree := `
|
||||
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
|
||||
<CORSRule>
|
||||
<AllowedMethod>GET</AllowedMethod>
|
||||
<AllowedMethod>PUT</AllowedMethod>
|
||||
<AllowedOrigin>*</AllowedOrigin>
|
||||
<AllowedHeader>*</AllowedHeader>
|
||||
</CORSRule>
|
||||
</CORSConfiguration>
|
||||
`
|
||||
body := `
|
||||
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
|
||||
<CORSRule>
|
||||
<AllowedMethod>DELETE</AllowedMethod>
|
||||
<AllowedOrigin>*</AllowedOrigin>
|
||||
<AllowedHeader>*</AllowedHeader>
|
||||
</CORSRule>
|
||||
</CORSConfiguration>
|
||||
`
|
||||
hc := prepareHandlerContextWithMinCache(t)
|
||||
|
||||
bktName := "bucket-get-latest-cors"
|
||||
info := createBucket(hc, bktName)
|
||||
|
||||
addCORSToTree(hc, bodyTree, info.BktInfo, info.BktInfo.CID)
|
||||
|
||||
w := getBucketCORS(hc, bktName)
|
||||
requireEqualCORS(hc.t, bodyTree, w.Body.String())
|
||||
|
||||
hc.tp.AddCORSObject(info.BktInfo, hc.corsCnrID, body)
|
||||
|
||||
w = getBucketCORS(hc, bktName)
|
||||
requireEqualCORS(hc.t, body, w.Body.String())
|
||||
|
||||
hc.tp.AddCORSObject(info.BktInfo, hc.corsCnrID, bodyTree)
|
||||
w = getBucketCORS(hc, bktName)
|
||||
requireEqualCORS(hc.t, bodyTree, w.Body.String())
|
||||
}
|
||||
|
||||
func TestDeleteTreeCORSVersions(t *testing.T) {
|
||||
body := `
|
||||
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
|
||||
<CORSRule>
|
||||
<AllowedMethod>GET</AllowedMethod>
|
||||
<AllowedMethod>PUT</AllowedMethod>
|
||||
<AllowedOrigin>*</AllowedOrigin>
|
||||
<AllowedHeader>*</AllowedHeader>
|
||||
</CORSRule>
|
||||
</CORSConfiguration>
|
||||
`
|
||||
hc := prepareHandlerContext(t)
|
||||
|
||||
bktName := "bucket-delete-tree-cors-versions"
|
||||
info := createBucket(hc, bktName)
|
||||
|
||||
addCORSToTree(hc, body, info.BktInfo, info.BktInfo.CID)
|
||||
addCORSToTree(hc, body, info.BktInfo, hc.corsCnrID)
|
||||
require.Len(t, hc.tp.Objects(), 2)
|
||||
|
||||
putBucketCORS(hc, bktName, body)
|
||||
require.Len(t, hc.tp.Objects(), 1)
|
||||
|
||||
addCORSToTree(hc, body, info.BktInfo, info.BktInfo.CID)
|
||||
addCORSToTree(hc, body, info.BktInfo, hc.corsCnrID)
|
||||
require.Len(t, hc.tp.Objects(), 3)
|
||||
|
||||
deleteBucketCORS(hc, bktName)
|
||||
require.Len(t, hc.tp.Objects(), 0)
|
||||
}
|
||||
|
||||
func TestDeleteCORSInDeleteBucket(t *testing.T) {
|
||||
body := `
|
||||
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
|
||||
<CORSRule>
|
||||
<AllowedMethod>GET</AllowedMethod>
|
||||
<AllowedMethod>PUT</AllowedMethod>
|
||||
<AllowedOrigin>*</AllowedOrigin>
|
||||
<AllowedHeader>*</AllowedHeader>
|
||||
</CORSRule>
|
||||
</CORSConfiguration>
|
||||
`
|
||||
|
||||
hc := prepareHandlerContext(t)
|
||||
|
||||
bktName := "bucket-delete-cors-in-delete-bucket"
|
||||
info := createBucket(hc, bktName)
|
||||
|
||||
addCORSToTree(hc, body, info.BktInfo, hc.corsCnrID)
|
||||
addCORSToTree(hc, body, info.BktInfo, info.BktInfo.CID)
|
||||
hc.tp.AddCORSObject(info.BktInfo, hc.corsCnrID, body)
|
||||
require.Len(t, hc.tp.Objects(), 3)
|
||||
|
||||
hc.owner = info.BktInfo.Owner
|
||||
deleteBucket(t, hc, bktName, http.StatusNoContent)
|
||||
require.Len(t, hc.tp.Objects(), 1) // CORS object in bucket container is not deleted
|
||||
}
|
||||
|
||||
func addCORSToTree(hc *handlerContext, cors string, bkt *data.BucketInfo, corsCnrID cid.ID) {
|
||||
var addr oid.Address
|
||||
addr.SetContainer(corsCnrID)
|
||||
addr.SetObject(oidtest.ID())
|
||||
|
||||
var obj object.Object
|
||||
obj.SetPayload([]byte(cors))
|
||||
obj.SetPayloadSize(uint64(len(cors)))
|
||||
|
||||
hc.tp.SetObject(addr, &obj)
|
||||
|
||||
meta := make(map[string]string)
|
||||
meta["FileName"] = "bucket-cors"
|
||||
meta["OID"] = addr.Object().EncodeToString()
|
||||
meta["CID"] = addr.Container().EncodeToString()
|
||||
|
||||
_, err := hc.treeMock.AddNode(hc.context, bkt, "system", 0, meta)
|
||||
require.NoError(hc.t, err)
|
||||
}
|
||||
|
||||
func requireEqualCORS(t *testing.T, expected string, actual string) {
|
||||
expectedCORS := &data.CORSConfiguration{}
|
||||
err := xml.NewDecoder(strings.NewReader(expected)).Decode(expectedCORS)
|
||||
require.NoError(t, err)
|
||||
|
||||
actualCORS := &data.CORSConfiguration{}
|
||||
err = xml.NewDecoder(strings.NewReader(actual)).Decode(actualCORS)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, expectedCORS, actualCORS)
|
||||
}
|
||||
|
||||
func putBucketCORS(hc *handlerContext, bktName string, body string) {
|
||||
w, r := prepareTestPayloadRequest(hc, bktName, "", strings.NewReader(body))
|
||||
box, _ := createAccessBox(hc.t)
|
||||
r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: box}))
|
||||
hc.Handler().PutBucketCorsHandler(w, r)
|
||||
assertStatus(hc.t, w, http.StatusOK)
|
||||
}
|
||||
|
||||
func deleteBucketCORS(hc *handlerContext, bktName string) {
|
||||
w, r := prepareTestPayloadRequest(hc, bktName, "", nil)
|
||||
box, _ := createAccessBox(hc.t)
|
||||
r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: box}))
|
||||
hc.Handler().DeleteBucketCorsHandler(w, r)
|
||||
assertStatus(hc.t, w, http.StatusNoContent)
|
||||
}
|
||||
|
||||
func getBucketCORS(hc *handlerContext, bktName string) *httptest.ResponseRecorder {
|
||||
w, r := prepareTestPayloadRequest(hc, bktName, "", nil)
|
||||
hc.Handler().GetBucketCorsHandler(w, r)
|
||||
assertStatus(hc.t, w, http.StatusOK)
|
||||
return w
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue