use correct xml package for custom MarshalXML() (#16421)

This commit is contained in:
Harshavardhana 2023-01-17 05:08:33 +05:30 committed by GitHub
parent 5a9f7516d6
commit 3db658e51e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 36 additions and 15 deletions

View File

@ -20,6 +20,7 @@ package cmd
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"encoding/xml"
"fmt" "fmt"
"net/http" "net/http"
"net/url" "net/url"
@ -64,15 +65,31 @@ func setCommonHeaders(w http.ResponseWriter) {
// Encodes the response headers into XML format. // Encodes the response headers into XML format.
func encodeResponse(response interface{}) []byte { func encodeResponse(response interface{}) []byte {
var bytesBuffer bytes.Buffer var buf bytes.Buffer
bytesBuffer.WriteString(xxml.Header) buf.WriteString(xml.Header)
buf, err := xxml.Marshal(response) if err := xml.NewEncoder(&buf).Encode(response); err != nil {
if err != nil {
logger.LogIf(GlobalContext, err) logger.LogIf(GlobalContext, err)
return nil return nil
} }
bytesBuffer.Write(buf) return buf.Bytes()
return bytesBuffer.Bytes() }
// Use this encodeResponseList() to support control characters
// this function must be used by only ListObjects() for objects
// with control characters, this is a specialized extension
// to support AWS S3 compatible behavior.
//
// Do not use this function for anything other than ListObjects()
// variants, please open a github discussion if you wish to use
// this in other places.
func encodeResponseList(response interface{}) []byte {
var buf bytes.Buffer
buf.WriteString(xxml.Header)
if err := xxml.NewEncoder(&buf).Encode(response); err != nil {
logger.LogIf(GlobalContext, err)
return nil
}
return buf.Bytes()
} }
// Encodes the response headers into JSON format. // Encodes the response headers into JSON format.

View File

@ -314,12 +314,12 @@ func (s *Metadata) Set(k, v string) {
} }
type xmlKeyEntry struct { type xmlKeyEntry struct {
XMLName xml.Name XMLName xxml.Name
Value string `xml:",chardata"` Value string `xml:",chardata"`
} }
// MarshalXML - StringMap marshals into XML. // MarshalXML - StringMap marshals into XML.
func (s *Metadata) MarshalXML(e *xml.Encoder, start xml.StartElement) error { func (s *Metadata) MarshalXML(e *xxml.Encoder, start xxml.StartElement) error {
if s == nil { if s == nil {
return nil return nil
} }
@ -334,7 +334,7 @@ func (s *Metadata) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
for _, item := range s.Items { for _, item := range s.Items {
if err := e.Encode(xmlKeyEntry{ if err := e.Encode(xmlKeyEntry{
XMLName: xml.Name{Local: item.Key}, XMLName: xxml.Name{Local: item.Key},
Value: item.Value, Value: item.Value,
}); err != nil { }); err != nil {
return err return err

View File

@ -115,7 +115,7 @@ func (api objectAPIHandlers) ListObjectVersionsHandler(w http.ResponseWriter, r
response := generateListVersionsResponse(bucket, prefix, marker, versionIDMarker, delimiter, encodingType, maxkeys, listObjectVersionsInfo) response := generateListVersionsResponse(bucket, prefix, marker, versionIDMarker, delimiter, encodingType, maxkeys, listObjectVersionsInfo)
// Write success response. // Write success response.
writeSuccessResponseXML(w, encodeResponse(response)) writeSuccessResponseXML(w, encodeResponseList(response))
} }
// ListObjectsV2MHandler - GET Bucket (List Objects) Version 2 with metadata. // ListObjectsV2MHandler - GET Bucket (List Objects) Version 2 with metadata.
@ -185,7 +185,7 @@ func (api objectAPIHandlers) ListObjectsV2MHandler(w http.ResponseWriter, r *htt
maxKeys, listObjectsV2Info.Objects, listObjectsV2Info.Prefixes, true) maxKeys, listObjectsV2Info.Objects, listObjectsV2Info.Prefixes, true)
// Write success response. // Write success response.
writeSuccessResponseXML(w, encodeResponse(response)) writeSuccessResponseXML(w, encodeResponseList(response))
} }
// ListObjectsV2Handler - GET Bucket (List Objects) Version 2. // ListObjectsV2Handler - GET Bucket (List Objects) Version 2.
@ -260,7 +260,7 @@ func (api objectAPIHandlers) ListObjectsV2Handler(w http.ResponseWriter, r *http
maxKeys, listObjectsV2Info.Objects, listObjectsV2Info.Prefixes, false) maxKeys, listObjectsV2Info.Objects, listObjectsV2Info.Prefixes, false)
// Write success response. // Write success response.
writeSuccessResponseXML(w, encodeResponse(response)) writeSuccessResponseXML(w, encodeResponseList(response))
} }
func parseRequestToken(token string) (subToken string, nodeIndex int) { func parseRequestToken(token string) (subToken string, nodeIndex int) {
@ -357,5 +357,5 @@ func (api objectAPIHandlers) ListObjectsV1Handler(w http.ResponseWriter, r *http
response := generateListObjectsV1Response(bucket, prefix, marker, delimiter, encodingType, maxKeys, listObjectsInfo) response := generateListObjectsV1Response(bucket, prefix, marker, delimiter, encodingType, maxKeys, listObjectsInfo)
// Write success response. // Write success response.
writeSuccessResponseXML(w, encodeResponse(response)) writeSuccessResponseXML(w, encodeResponseList(response))
} }

View File

@ -23,7 +23,10 @@ import (
) )
// RFC3339 a subset of the ISO8601 timestamp format. e.g 2014-04-29T18:30:38Z // RFC3339 a subset of the ISO8601 timestamp format. e.g 2014-04-29T18:30:38Z
const iso8601TimeFormat = "2006-01-02T15:04:05.000Z" // Reply date format with nanosecond precision. const (
iso8601TimeFormat = "2006-01-02T15:04:05.000Z" // Reply date format with millisecond precision.
iso8601TimeFormatLong = "2006-01-02T15:04:05.000000Z" // Reply date format with nanosecond precision.
)
// ISO8601Format converts time 't' into ISO8601 time format expected in AWS S3 spec. // ISO8601Format converts time 't' into ISO8601 time format expected in AWS S3 spec.
// //
@ -43,6 +46,7 @@ func ISO8601Format(t time.Time) string {
func ISO8601Parse(iso8601 string) (t time.Time, err error) { func ISO8601Parse(iso8601 string) (t time.Time, err error) {
for _, layout := range []string{ for _, layout := range []string{
iso8601TimeFormat, iso8601TimeFormat,
iso8601TimeFormatLong,
time.RFC3339, time.RFC3339,
} { } {
t, err = time.Parse(layout, iso8601) t, err = time.Parse(layout, iso8601)

View File

@ -320,7 +320,7 @@ func (rDate *RetentionDate) UnmarshalXML(d *xml.Decoder, startElement xml.StartE
// MarshalXML encodes expiration date if it is non-zero and encodes // MarshalXML encodes expiration date if it is non-zero and encodes
// empty string otherwise // empty string otherwise
func (rDate *RetentionDate) MarshalXML(e *xml.Encoder, startElement xml.StartElement) error { func (rDate RetentionDate) MarshalXML(e *xml.Encoder, startElement xml.StartElement) error {
if rDate.IsZero() { if rDate.IsZero() {
return nil return nil
} }