From bc975989dea0b4728478327629c21c42224014e3 Mon Sep 17 00:00:00 2001 From: Pavel Pogodaev Date: Wed, 15 Jan 2025 12:07:39 +0300 Subject: [PATCH] [#594] Fix unmarshal cors: expected element in name space error Signed-off-by: Pavel Pogodaev --- api/handler/cors.go | 6 +++--- api/handler/cors_test.go | 20 +++++++++++++++++++- api/handler/handlers_test.go | 7 ++++++- api/layer/cors.go | 5 +++-- api/layer/system_object.go | 5 +++-- 5 files changed, 34 insertions(+), 9 deletions(-) diff --git a/api/handler/cors.go b/api/handler/cors.go index 6a671a5..dcdaa52 100644 --- a/api/handler/cors.go +++ b/api/handler/cors.go @@ -29,7 +29,7 @@ func (h *handler) GetBucketCorsHandler(w http.ResponseWriter, r *http.Request) { return } - cors, err := h.obj.GetBucketCORS(ctx, bktInfo) + cors, err := h.obj.GetBucketCORS(ctx, bktInfo, h.cfg.NewXMLDecoder) if err != nil { h.logAndSendError(ctx, w, "could not get cors", reqInfo, err) return @@ -112,7 +112,7 @@ func (h *handler) AppendCORSHeaders(w http.ResponseWriter, r *http.Request) { return } - cors, err := h.obj.GetBucketCORS(ctx, bktInfo) + cors, err := h.obj.GetBucketCORS(ctx, bktInfo, h.cfg.NewXMLDecoder) if err != nil { h.reqLogger(ctx).Warn(logs.GetBucketCors, zap.Error(err)) return @@ -178,7 +178,7 @@ func (h *handler) Preflight(w http.ResponseWriter, r *http.Request) { headers = strings.Split(requestHeaders, ", ") } - cors, err := h.obj.GetBucketCORS(ctx, bktInfo) + cors, err := h.obj.GetBucketCORS(ctx, bktInfo, h.cfg.NewXMLDecoder) if err != nil { h.logAndSendError(ctx, w, "could not get cors", reqInfo, err) return diff --git a/api/handler/cors_test.go b/api/handler/cors_test.go index 42008d7..595bff7 100644 --- a/api/handler/cors_test.go +++ b/api/handler/cors_test.go @@ -19,7 +19,14 @@ func TestCORSOriginWildcard(t *testing.T) { ` - hc := prepareHandlerContext(t) + bodyNoXmlns := ` + + + GET + * + +` + hc := prepareHandlerContextWithMinCache(t) bktName := "bucket-for-cors" box, _ := createAccessBox(t) @@ -39,6 +46,17 @@ func TestCORSOriginWildcard(t *testing.T) { w, r = prepareTestPayloadRequest(hc, bktName, "", nil) hc.Handler().GetBucketCorsHandler(w, r) assertStatus(t, w, http.StatusOK) + + 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) + + w, r = prepareTestPayloadRequest(hc, bktName, "", nil) + hc.Handler().GetBucketCorsHandler(w, r) + assertStatus(t, w, http.StatusOK) } func TestPreflight(t *testing.T) { diff --git a/api/handler/handlers_test.go b/api/handler/handlers_test.go index dae87fc..7b73e51 100644 --- a/api/handler/handlers_test.go +++ b/api/handler/handlers_test.go @@ -79,6 +79,7 @@ type configMock struct { bypassContentEncodingInChunks bool md5Enabled bool tlsTerminationHeader string + useDefaultXMLNS bool } func (c *configMock) DefaultPlacementPolicy(_ string) netmap.PlacementPolicy { @@ -99,7 +100,11 @@ func (c *configMock) DefaultCopiesNumbers(_ string) []uint32 { } func (c *configMock) NewXMLDecoder(r io.Reader, _ string) *xml.Decoder { - return xml.NewDecoder(r) + dec := xml.NewDecoder(r) + if c.useDefaultXMLNS { + dec.DefaultSpace = "http://s3.amazonaws.com/doc/2006-03-01/" + } + return dec } func (c *configMock) BypassContentEncodingInChunks(_ string) bool { diff --git a/api/layer/cors.go b/api/layer/cors.go index ebf0a19..925f8ed 100644 --- a/api/layer/cors.go +++ b/api/layer/cors.go @@ -3,6 +3,7 @@ package layer import ( "bytes" "context" + "encoding/xml" "errors" "fmt" "io" @@ -95,8 +96,8 @@ func (n *Layer) deleteCORSObject(ctx context.Context, bktInfo *data.BucketInfo, } } -func (n *Layer) GetBucketCORS(ctx context.Context, bktInfo *data.BucketInfo) (*data.CORSConfiguration, error) { - cors, err := n.getCORS(ctx, bktInfo) +func (n *Layer) GetBucketCORS(ctx context.Context, bktInfo *data.BucketInfo, decoder func(io.Reader, string) *xml.Decoder) (*data.CORSConfiguration, error) { + cors, err := n.getCORS(ctx, bktInfo, decoder) if err != nil { return nil, err } diff --git a/api/layer/system_object.go b/api/layer/system_object.go index 19e58f0..4f7f40e 100644 --- a/api/layer/system_object.go +++ b/api/layer/system_object.go @@ -5,6 +5,7 @@ import ( "encoding/xml" "errors" "fmt" + "io" "math" "strconv" "time" @@ -161,7 +162,7 @@ func (n *Layer) GetLockInfo(ctx context.Context, objVersion *data.ObjectVersion) return lockInfo, nil } -func (n *Layer) getCORS(ctx context.Context, bkt *data.BucketInfo) (*data.CORSConfiguration, error) { +func (n *Layer) getCORS(ctx context.Context, bkt *data.BucketInfo, decoder func(io.Reader, string) *xml.Decoder) (*data.CORSConfiguration, error) { owner := n.BearerOwner(ctx) if cors := n.cache.GetCORS(owner, bkt); cors != nil { return cors, nil @@ -190,7 +191,7 @@ func (n *Layer) getCORS(ctx context.Context, bkt *data.BucketInfo) (*data.CORSCo } cors := &data.CORSConfiguration{} - if err = xml.NewDecoder(obj.Payload).Decode(&cors); err != nil { + if err = decoder(obj.Payload, "").Decode(&cors); err != nil { return nil, fmt.Errorf("unmarshal cors: %w", err) }