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.
		
		
		
		
		
			
		
			
				
					
					
						
							185 lines
						
					
					
						
							5.7 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							185 lines
						
					
					
						
							5.7 KiB
						
					
					
				| package s3api | |
| 
 | |
| import ( | |
| 	"net/http" | |
| 	"strings" | |
| 	"testing" | |
| 
 | |
| 	"github.com/seaweedfs/seaweedfs/weed/credential" | |
| 	_ "github.com/seaweedfs/seaweedfs/weed/credential/memory" | |
| 	"github.com/seaweedfs/seaweedfs/weed/s3api/s3err" | |
| ) | |
| 
 | |
| func TestGetRequestDataReader_ChunkedEncodingWithoutIAM(t *testing.T) { | |
| 	// Create an S3ApiServer with IAM disabled | |
| 	s3a := &S3ApiServer{ | |
| 		iam: NewIdentityAccessManagementWithStore(&S3ApiServerOption{}, string(credential.StoreTypeMemory)), | |
| 	} | |
| 	// Ensure IAM is disabled for this test | |
| 	s3a.iam.isAuthEnabled = false | |
| 
 | |
| 	tests := []struct { | |
| 		name          string | |
| 		contentSha256 string | |
| 		expectedError s3err.ErrorCode | |
| 		shouldProcess bool | |
| 		description   string | |
| 	}{ | |
| 		{ | |
| 			name:          "RegularRequest", | |
| 			contentSha256: "", | |
| 			expectedError: s3err.ErrNone, | |
| 			shouldProcess: false, | |
| 			description:   "Regular requests without chunked encoding should pass through unchanged", | |
| 		}, | |
| 		{ | |
| 			name:          "StreamingSignedWithoutIAM", | |
| 			contentSha256: "STREAMING-AWS4-HMAC-SHA256-PAYLOAD", | |
| 			expectedError: s3err.ErrAuthNotSetup, | |
| 			shouldProcess: false, | |
| 			description:   "Streaming signed requests should fail when IAM is disabled", | |
| 		}, | |
| 		{ | |
| 			name:          "StreamingUnsignedWithoutIAM", | |
| 			contentSha256: "STREAMING-UNSIGNED-PAYLOAD-TRAILER", | |
| 			expectedError: s3err.ErrNone, | |
| 			shouldProcess: true, | |
| 			description:   "Streaming unsigned requests should be processed even when IAM is disabled", | |
| 		}, | |
| 	} | |
| 
 | |
| 	for _, tt := range tests { | |
| 		t.Run(tt.name, func(t *testing.T) { | |
| 			body := strings.NewReader("test data") | |
| 			req, _ := http.NewRequest("PUT", "/bucket/key", body) | |
| 
 | |
| 			if tt.contentSha256 != "" { | |
| 				req.Header.Set("x-amz-content-sha256", tt.contentSha256) | |
| 			} | |
| 
 | |
| 			dataReader, errCode := getRequestDataReader(s3a, req) | |
| 
 | |
| 			// Check error code | |
| 			if errCode != tt.expectedError { | |
| 				t.Errorf("Expected error code %v, got %v", tt.expectedError, errCode) | |
| 			} | |
| 
 | |
| 			// For successful cases, check if processing occurred | |
| 			if errCode == s3err.ErrNone { | |
| 				if tt.shouldProcess { | |
| 					// For chunked requests, the reader should be different from the original body | |
| 					if dataReader == req.Body { | |
| 						t.Error("Expected dataReader to be processed by newChunkedReader, but got raw request body") | |
| 					} | |
| 				} else { | |
| 					// For regular requests, the reader should be the same as the original body | |
| 					if dataReader != req.Body { | |
| 						t.Error("Expected dataReader to be the same as request body for regular requests") | |
| 					} | |
| 				} | |
| 			} | |
| 
 | |
| 			t.Logf("Test case: %s - %s", tt.name, tt.description) | |
| 		}) | |
| 	} | |
| } | |
| 
 | |
| func TestGetRequestDataReader_AuthTypeDetection(t *testing.T) { | |
| 	// Create an S3ApiServer with IAM disabled | |
| 	s3a := &S3ApiServer{ | |
| 		iam: NewIdentityAccessManagementWithStore(&S3ApiServerOption{}, string(credential.StoreTypeMemory)), | |
| 	} | |
| 	s3a.iam.isAuthEnabled = false | |
| 
 | |
| 	// Test the specific case mentioned in the issue where chunked data | |
| 	// with checksum headers would be stored incorrectly | |
| 	t.Run("ChunkedDataWithChecksum", func(t *testing.T) { | |
| 		// Simulate a request with chunked data and checksum trailer | |
| 		body := strings.NewReader("test content") | |
| 		req, _ := http.NewRequest("PUT", "/bucket/key", body) | |
| 		req.Header.Set("x-amz-content-sha256", "STREAMING-UNSIGNED-PAYLOAD-TRAILER") | |
| 		req.Header.Set("x-amz-trailer", "x-amz-checksum-crc32") | |
| 
 | |
| 		// Verify the auth type is detected correctly | |
| 		authType := getRequestAuthType(req) | |
| 		if authType != authTypeStreamingUnsigned { | |
| 			t.Errorf("Expected authTypeStreamingUnsigned, got %v", authType) | |
| 		} | |
| 
 | |
| 		// Verify the request is processed correctly | |
| 		dataReader, errCode := getRequestDataReader(s3a, req) | |
| 		if errCode != s3err.ErrNone { | |
| 			t.Errorf("Expected no error, got %v", errCode) | |
| 		} | |
| 
 | |
| 		// The dataReader should be processed by newChunkedReader | |
| 		if dataReader == req.Body { | |
| 			t.Error("Expected dataReader to be processed by newChunkedReader to handle chunked encoding") | |
| 		} | |
| 	}) | |
| } | |
| 
 | |
| func TestGetRequestDataReader_IAMEnabled(t *testing.T) { | |
| 	// Create an S3ApiServer with IAM enabled | |
| 	s3a := &S3ApiServer{ | |
| 		iam: NewIdentityAccessManagementWithStore(&S3ApiServerOption{}, string(credential.StoreTypeMemory)), | |
| 	} | |
| 	s3a.iam.isAuthEnabled = true | |
| 
 | |
| 	t.Run("StreamingUnsignedWithIAMEnabled", func(t *testing.T) { | |
| 		body := strings.NewReader("test data") | |
| 		req, _ := http.NewRequest("PUT", "/bucket/key", body) | |
| 		req.Header.Set("x-amz-content-sha256", "STREAMING-UNSIGNED-PAYLOAD-TRAILER") | |
| 
 | |
| 		dataReader, errCode := getRequestDataReader(s3a, req) | |
| 
 | |
| 		// Should succeed and be processed | |
| 		if errCode != s3err.ErrNone { | |
| 			t.Errorf("Expected no error, got %v", errCode) | |
| 		} | |
| 
 | |
| 		// Should be processed by newChunkedReader | |
| 		if dataReader == req.Body { | |
| 			t.Error("Expected dataReader to be processed by newChunkedReader") | |
| 		} | |
| 	}) | |
| } | |
| 
 | |
| // Test helper to verify auth type detection works correctly | |
| func TestAuthTypeDetection(t *testing.T) { | |
| 	tests := []struct { | |
| 		name         string | |
| 		headers      map[string]string | |
| 		expectedType authType | |
| 	}{ | |
| 		{ | |
| 			name:         "StreamingUnsigned", | |
| 			headers:      map[string]string{"x-amz-content-sha256": "STREAMING-UNSIGNED-PAYLOAD-TRAILER"}, | |
| 			expectedType: authTypeStreamingUnsigned, | |
| 		}, | |
| 		{ | |
| 			name:         "StreamingSigned", | |
| 			headers:      map[string]string{"x-amz-content-sha256": "STREAMING-AWS4-HMAC-SHA256-PAYLOAD"}, | |
| 			expectedType: authTypeStreamingSigned, | |
| 		}, | |
| 		{ | |
| 			name:         "Regular", | |
| 			headers:      map[string]string{}, | |
| 			expectedType: authTypeAnonymous, | |
| 		}, | |
| 	} | |
| 
 | |
| 	for _, tt := range tests { | |
| 		t.Run(tt.name, func(t *testing.T) { | |
| 			req, _ := http.NewRequest("PUT", "/bucket/key", strings.NewReader("test")) | |
| 			for key, value := range tt.headers { | |
| 				req.Header.Set(key, value) | |
| 			} | |
| 
 | |
| 			authType := getRequestAuthType(req) | |
| 			if authType != tt.expectedType { | |
| 				t.Errorf("Expected auth type %v, got %v", tt.expectedType, authType) | |
| 			} | |
| 		}) | |
| 	} | |
| }
 |