You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							438 lines
						
					
					
						
							11 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							438 lines
						
					
					
						
							11 KiB
						
					
					
				
								package s3api
							 | 
						|
								
							 | 
						|
								import (
							 | 
						|
									"fmt"
							 | 
						|
									"github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
							 | 
						|
									"net/http"
							 | 
						|
									"reflect"
							 | 
						|
									"sort"
							 | 
						|
									"strings"
							 | 
						|
									"testing"
							 | 
						|
								)
							 | 
						|
								
							 | 
						|
								type H map[string]string
							 | 
						|
								
							 | 
						|
								func (h H) String() string {
							 | 
						|
									pairs := make([]string, 0, len(h))
							 | 
						|
									for k, v := range h {
							 | 
						|
										pairs = append(pairs, fmt.Sprintf("%s : %s", k, v))
							 | 
						|
									}
							 | 
						|
									sort.Strings(pairs)
							 | 
						|
									join := strings.Join(pairs, "\n")
							 | 
						|
									return "\n" + join + "\n"
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								var processMetadataTestCases = []struct {
							 | 
						|
									caseId   int
							 | 
						|
									request  H
							 | 
						|
									existing H
							 | 
						|
									getTags  H
							 | 
						|
									want     H
							 | 
						|
								}{
							 | 
						|
									{
							 | 
						|
										201,
							 | 
						|
										H{
							 | 
						|
											"User-Agent":         "firefox",
							 | 
						|
											"X-Amz-Meta-My-Meta": "request",
							 | 
						|
											"X-Amz-Tagging":      "A=B&a=b&type=request",
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"X-Amz-Meta-My-Meta": "existing",
							 | 
						|
											"X-Amz-Tagging-A":    "B",
							 | 
						|
											"X-Amz-Tagging-Type": "existing",
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"A":    "B",
							 | 
						|
											"a":    "b",
							 | 
						|
											"type": "existing",
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"User-Agent":         "firefox",
							 | 
						|
											"X-Amz-Meta-My-Meta": "existing",
							 | 
						|
											"X-Amz-Tagging":      "A=B&a=b&type=existing",
							 | 
						|
										},
							 | 
						|
									},
							 | 
						|
									{
							 | 
						|
										202,
							 | 
						|
										H{
							 | 
						|
											"User-Agent":                      "firefox",
							 | 
						|
											"X-Amz-Meta-My-Meta":              "request",
							 | 
						|
											"X-Amz-Tagging":                   "A=B&a=b&type=request",
							 | 
						|
											s3_constants.AmzUserMetaDirective: DirectiveReplace,
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"X-Amz-Meta-My-Meta": "existing",
							 | 
						|
											"X-Amz-Tagging-A":    "B",
							 | 
						|
											"X-Amz-Tagging-Type": "existing",
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"A":    "B",
							 | 
						|
											"a":    "b",
							 | 
						|
											"type": "existing",
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"User-Agent":                      "firefox",
							 | 
						|
											"X-Amz-Meta-My-Meta":              "request",
							 | 
						|
											"X-Amz-Tagging":                   "A=B&a=b&type=existing",
							 | 
						|
											s3_constants.AmzUserMetaDirective: DirectiveReplace,
							 | 
						|
										},
							 | 
						|
									},
							 | 
						|
								
							 | 
						|
									{
							 | 
						|
										203,
							 | 
						|
										H{
							 | 
						|
											"User-Agent":                           "firefox",
							 | 
						|
											"X-Amz-Meta-My-Meta":                   "request",
							 | 
						|
											"X-Amz-Tagging":                        "A=B&a=b&type=request",
							 | 
						|
											s3_constants.AmzObjectTaggingDirective: DirectiveReplace,
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"X-Amz-Meta-My-Meta": "existing",
							 | 
						|
											"X-Amz-Tagging-A":    "B",
							 | 
						|
											"X-Amz-Tagging-Type": "existing",
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"A":    "B",
							 | 
						|
											"a":    "b",
							 | 
						|
											"type": "existing",
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"User-Agent":                           "firefox",
							 | 
						|
											"X-Amz-Meta-My-Meta":                   "existing",
							 | 
						|
											"X-Amz-Tagging":                        "A=B&a=b&type=request",
							 | 
						|
											s3_constants.AmzObjectTaggingDirective: DirectiveReplace,
							 | 
						|
										},
							 | 
						|
									},
							 | 
						|
								
							 | 
						|
									{
							 | 
						|
										204,
							 | 
						|
										H{
							 | 
						|
											"User-Agent":                           "firefox",
							 | 
						|
											"X-Amz-Meta-My-Meta":                   "request",
							 | 
						|
											"X-Amz-Tagging":                        "A=B&a=b&type=request",
							 | 
						|
											s3_constants.AmzUserMetaDirective:      DirectiveReplace,
							 | 
						|
											s3_constants.AmzObjectTaggingDirective: DirectiveReplace,
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"X-Amz-Meta-My-Meta": "existing",
							 | 
						|
											"X-Amz-Tagging-A":    "B",
							 | 
						|
											"X-Amz-Tagging-a":    "b",
							 | 
						|
											"X-Amz-Tagging-Type": "existing",
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"A":    "B",
							 | 
						|
											"a":    "b",
							 | 
						|
											"type": "existing",
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"User-Agent":                           "firefox",
							 | 
						|
											"X-Amz-Meta-My-Meta":                   "request",
							 | 
						|
											"X-Amz-Tagging":                        "A=B&a=b&type=request",
							 | 
						|
											s3_constants.AmzUserMetaDirective:      DirectiveReplace,
							 | 
						|
											s3_constants.AmzObjectTaggingDirective: DirectiveReplace,
							 | 
						|
										},
							 | 
						|
									},
							 | 
						|
								
							 | 
						|
									{
							 | 
						|
										205,
							 | 
						|
										H{
							 | 
						|
											"User-Agent":                           "firefox",
							 | 
						|
											"X-Amz-Meta-My-Meta":                   "request",
							 | 
						|
											"X-Amz-Tagging":                        "A=B&a=b&type=request",
							 | 
						|
											s3_constants.AmzUserMetaDirective:      DirectiveReplace,
							 | 
						|
											s3_constants.AmzObjectTaggingDirective: DirectiveReplace,
							 | 
						|
										},
							 | 
						|
										H{},
							 | 
						|
										H{},
							 | 
						|
										H{
							 | 
						|
											"User-Agent":                           "firefox",
							 | 
						|
											"X-Amz-Meta-My-Meta":                   "request",
							 | 
						|
											"X-Amz-Tagging":                        "A=B&a=b&type=request",
							 | 
						|
											s3_constants.AmzUserMetaDirective:      DirectiveReplace,
							 | 
						|
											s3_constants.AmzObjectTaggingDirective: DirectiveReplace,
							 | 
						|
										},
							 | 
						|
									},
							 | 
						|
								
							 | 
						|
									{
							 | 
						|
										206,
							 | 
						|
										H{
							 | 
						|
											"User-Agent":                           "firefox",
							 | 
						|
											s3_constants.AmzUserMetaDirective:      DirectiveReplace,
							 | 
						|
											s3_constants.AmzObjectTaggingDirective: DirectiveReplace,
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"X-Amz-Meta-My-Meta": "existing",
							 | 
						|
											"X-Amz-Tagging-A":    "B",
							 | 
						|
											"X-Amz-Tagging-a":    "b",
							 | 
						|
											"X-Amz-Tagging-Type": "existing",
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"A":    "B",
							 | 
						|
											"a":    "b",
							 | 
						|
											"type": "existing",
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"User-Agent":                           "firefox",
							 | 
						|
											s3_constants.AmzUserMetaDirective:      DirectiveReplace,
							 | 
						|
											s3_constants.AmzObjectTaggingDirective: DirectiveReplace,
							 | 
						|
										},
							 | 
						|
									},
							 | 
						|
								
							 | 
						|
									{
							 | 
						|
										207,
							 | 
						|
										H{
							 | 
						|
											"User-Agent":                           "firefox",
							 | 
						|
											"X-Amz-Meta-My-Meta":                   "request",
							 | 
						|
											s3_constants.AmzUserMetaDirective:      DirectiveReplace,
							 | 
						|
											s3_constants.AmzObjectTaggingDirective: DirectiveReplace,
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"X-Amz-Meta-My-Meta": "existing",
							 | 
						|
											"X-Amz-Tagging-A":    "B",
							 | 
						|
											"X-Amz-Tagging-a":    "b",
							 | 
						|
											"X-Amz-Tagging-Type": "existing",
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"A":    "B",
							 | 
						|
											"a":    "b",
							 | 
						|
											"type": "existing",
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"User-Agent":                           "firefox",
							 | 
						|
											"X-Amz-Meta-My-Meta":                   "request",
							 | 
						|
											s3_constants.AmzUserMetaDirective:      DirectiveReplace,
							 | 
						|
											s3_constants.AmzObjectTaggingDirective: DirectiveReplace,
							 | 
						|
										},
							 | 
						|
									},
							 | 
						|
								}
							 | 
						|
								var processMetadataBytesTestCases = []struct {
							 | 
						|
									caseId   int
							 | 
						|
									request  H
							 | 
						|
									existing H
							 | 
						|
									want     H
							 | 
						|
								}{
							 | 
						|
									{
							 | 
						|
										101,
							 | 
						|
										H{
							 | 
						|
											"User-Agent":         "firefox",
							 | 
						|
											"X-Amz-Meta-My-Meta": "request",
							 | 
						|
											"X-Amz-Tagging":      "A=B&a=b&type=request",
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"X-Amz-Meta-My-Meta": "existing",
							 | 
						|
											"X-Amz-Tagging-A":    "B",
							 | 
						|
											"X-Amz-Tagging-a":    "b",
							 | 
						|
											"X-Amz-Tagging-type": "existing",
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"X-Amz-Meta-My-Meta": "existing",
							 | 
						|
											"X-Amz-Tagging-A":    "B",
							 | 
						|
											"X-Amz-Tagging-a":    "b",
							 | 
						|
											"X-Amz-Tagging-type": "existing",
							 | 
						|
										},
							 | 
						|
									},
							 | 
						|
								
							 | 
						|
									{
							 | 
						|
										102,
							 | 
						|
										H{
							 | 
						|
											"User-Agent":                      "firefox",
							 | 
						|
											"X-Amz-Meta-My-Meta":              "request",
							 | 
						|
											"X-Amz-Tagging":                   "A=B&a=b&type=request",
							 | 
						|
											s3_constants.AmzUserMetaDirective: DirectiveReplace,
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"X-Amz-Meta-My-Meta": "existing",
							 | 
						|
											"X-Amz-Tagging-A":    "B",
							 | 
						|
											"X-Amz-Tagging-a":    "b",
							 | 
						|
											"X-Amz-Tagging-type": "existing",
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"X-Amz-Meta-My-Meta": "request",
							 | 
						|
											"X-Amz-Tagging-A":    "B",
							 | 
						|
											"X-Amz-Tagging-a":    "b",
							 | 
						|
											"X-Amz-Tagging-type": "existing",
							 | 
						|
										},
							 | 
						|
									},
							 | 
						|
								
							 | 
						|
									{
							 | 
						|
										103,
							 | 
						|
										H{
							 | 
						|
											"User-Agent":                           "firefox",
							 | 
						|
											"X-Amz-Meta-My-Meta":                   "request",
							 | 
						|
											"X-Amz-Tagging":                        "A=B&a=b&type=request",
							 | 
						|
											s3_constants.AmzObjectTaggingDirective: DirectiveReplace,
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"X-Amz-Meta-My-Meta": "existing",
							 | 
						|
											"X-Amz-Tagging-A":    "B",
							 | 
						|
											"X-Amz-Tagging-a":    "b",
							 | 
						|
											"X-Amz-Tagging-type": "existing",
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"X-Amz-Meta-My-Meta": "existing",
							 | 
						|
											"X-Amz-Tagging-A":    "B",
							 | 
						|
											"X-Amz-Tagging-a":    "b",
							 | 
						|
											"X-Amz-Tagging-type": "request",
							 | 
						|
										},
							 | 
						|
									},
							 | 
						|
								
							 | 
						|
									{
							 | 
						|
										104,
							 | 
						|
										H{
							 | 
						|
											"User-Agent":                           "firefox",
							 | 
						|
											"X-Amz-Meta-My-Meta":                   "request",
							 | 
						|
											"X-Amz-Tagging":                        "A=B&a=b&type=request",
							 | 
						|
											s3_constants.AmzUserMetaDirective:      DirectiveReplace,
							 | 
						|
											s3_constants.AmzObjectTaggingDirective: DirectiveReplace,
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"X-Amz-Meta-My-Meta": "existing",
							 | 
						|
											"X-Amz-Tagging-A":    "B",
							 | 
						|
											"X-Amz-Tagging-a":    "b",
							 | 
						|
											"X-Amz-Tagging-type": "existing",
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"X-Amz-Meta-My-Meta": "request",
							 | 
						|
											"X-Amz-Tagging-A":    "B",
							 | 
						|
											"X-Amz-Tagging-a":    "b",
							 | 
						|
											"X-Amz-Tagging-type": "request",
							 | 
						|
										},
							 | 
						|
									},
							 | 
						|
								
							 | 
						|
									{
							 | 
						|
										105,
							 | 
						|
										H{
							 | 
						|
											"User-Agent":                           "firefox",
							 | 
						|
											s3_constants.AmzUserMetaDirective:      DirectiveReplace,
							 | 
						|
											s3_constants.AmzObjectTaggingDirective: DirectiveReplace,
							 | 
						|
										},
							 | 
						|
										H{
							 | 
						|
											"X-Amz-Meta-My-Meta": "existing",
							 | 
						|
											"X-Amz-Tagging-A":    "B",
							 | 
						|
											"X-Amz-Tagging-a":    "b",
							 | 
						|
											"X-Amz-Tagging-type": "existing",
							 | 
						|
										},
							 | 
						|
										H{},
							 | 
						|
									},
							 | 
						|
								
							 | 
						|
									{
							 | 
						|
										107,
							 | 
						|
										H{
							 | 
						|
											"User-Agent":                           "firefox",
							 | 
						|
											"X-Amz-Meta-My-Meta":                   "request",
							 | 
						|
											"X-Amz-Tagging":                        "A=B&a=b&type=request",
							 | 
						|
											s3_constants.AmzUserMetaDirective:      DirectiveReplace,
							 | 
						|
											s3_constants.AmzObjectTaggingDirective: DirectiveReplace,
							 | 
						|
										},
							 | 
						|
										H{},
							 | 
						|
										H{
							 | 
						|
											"X-Amz-Meta-My-Meta": "request",
							 | 
						|
											"X-Amz-Tagging-A":    "B",
							 | 
						|
											"X-Amz-Tagging-a":    "b",
							 | 
						|
											"X-Amz-Tagging-type": "request",
							 | 
						|
										},
							 | 
						|
									},
							 | 
						|
								
							 | 
						|
									{
							 | 
						|
										108,
							 | 
						|
										H{
							 | 
						|
											"User-Agent":                           "firefox",
							 | 
						|
											"X-Amz-Meta-My-Meta":                   "request",
							 | 
						|
											"X-Amz-Tagging":                        "A=B&a=b&type=request*",
							 | 
						|
											s3_constants.AmzUserMetaDirective:      DirectiveReplace,
							 | 
						|
											s3_constants.AmzObjectTaggingDirective: DirectiveReplace,
							 | 
						|
										},
							 | 
						|
										H{},
							 | 
						|
										H{},
							 | 
						|
									},
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func TestProcessMetadata(t *testing.T) {
							 | 
						|
									for _, tc := range processMetadataTestCases {
							 | 
						|
										reqHeader := transferHToHeader(tc.request)
							 | 
						|
										existing := transferHToHeader(tc.existing)
							 | 
						|
										replaceMeta, replaceTagging := replaceDirective(reqHeader)
							 | 
						|
										err := processMetadata(reqHeader, existing, replaceMeta, replaceTagging, func(_ string, _ string) (tags map[string]string, err error) {
							 | 
						|
											return tc.getTags, nil
							 | 
						|
										}, "", "")
							 | 
						|
										if err != nil {
							 | 
						|
											t.Error(err)
							 | 
						|
										}
							 | 
						|
								
							 | 
						|
										result := transferHeaderToH(reqHeader)
							 | 
						|
										fmtTagging(result, tc.want)
							 | 
						|
								
							 | 
						|
										if !reflect.DeepEqual(result, tc.want) {
							 | 
						|
											t.Error(fmt.Errorf("\n### CaseID: %d ###"+
							 | 
						|
												"\nRequest:%v"+
							 | 
						|
												"\nExisting:%v"+
							 | 
						|
												"\nGetTags:%v"+
							 | 
						|
												"\nWant:%v"+
							 | 
						|
												"\nActual:%v",
							 | 
						|
												tc.caseId, tc.request, tc.existing, tc.getTags, tc.want, result))
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func TestProcessMetadataBytes(t *testing.T) {
							 | 
						|
									for _, tc := range processMetadataBytesTestCases {
							 | 
						|
										reqHeader := transferHToHeader(tc.request)
							 | 
						|
										existing := transferHToBytesArr(tc.existing)
							 | 
						|
										replaceMeta, replaceTagging := replaceDirective(reqHeader)
							 | 
						|
										extends, _ := processMetadataBytes(reqHeader, existing, replaceMeta, replaceTagging)
							 | 
						|
								
							 | 
						|
										result := transferBytesArrToH(extends)
							 | 
						|
										fmtTagging(result, tc.want)
							 | 
						|
								
							 | 
						|
										if !reflect.DeepEqual(result, tc.want) {
							 | 
						|
											t.Error(fmt.Errorf("\n### CaseID: %d ###"+
							 | 
						|
												"\nRequest:%v"+
							 | 
						|
												"\nExisting:%v"+
							 | 
						|
												"\nWant:%v"+
							 | 
						|
												"\nActual:%v",
							 | 
						|
												tc.caseId, tc.request, tc.existing, tc.want, result))
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func fmtTagging(maps ...map[string]string) {
							 | 
						|
									for _, m := range maps {
							 | 
						|
										if tagging := m[s3_constants.AmzObjectTagging]; len(tagging) > 0 {
							 | 
						|
											split := strings.Split(tagging, "&")
							 | 
						|
											sort.Strings(split)
							 | 
						|
											m[s3_constants.AmzObjectTagging] = strings.Join(split, "&")
							 | 
						|
										}
							 | 
						|
									}
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func transferHToHeader(data map[string]string) http.Header {
							 | 
						|
									header := http.Header{}
							 | 
						|
									for k, v := range data {
							 | 
						|
										header.Add(k, v)
							 | 
						|
									}
							 | 
						|
									return header
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func transferHToBytesArr(data map[string]string) map[string][]byte {
							 | 
						|
									m := make(map[string][]byte, len(data))
							 | 
						|
									for k, v := range data {
							 | 
						|
										m[k] = []byte(v)
							 | 
						|
									}
							 | 
						|
									return m
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func transferBytesArrToH(data map[string][]byte) H {
							 | 
						|
									m := make(map[string]string, len(data))
							 | 
						|
									for k, v := range data {
							 | 
						|
										m[k] = string(v)
							 | 
						|
									}
							 | 
						|
									return m
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								func transferHeaderToH(data map[string][]string) H {
							 | 
						|
									m := make(map[string]string, len(data))
							 | 
						|
									for k, v := range data {
							 | 
						|
										m[k] = v[len(v)-1]
							 | 
						|
									}
							 | 
						|
									return m
							 | 
						|
								}
							 |