From 2955aae8e43170b29575237b704f00deefae6049 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Mon, 20 Jul 2020 12:52:49 -0700 Subject: [PATCH] feat: Add notification support for bucketCreates and removal (#10075) --- cmd/api-router.go | 8 +- cmd/auth-handler_test.go | 30 +-- cmd/bucket-handlers.go | 28 +++ cmd/bucket-handlers_test.go | 44 ++-- cmd/bucket-lifecycle-handlers_test.go | 24 +- cmd/bucket-notification-handlers.go | 137 ------------ cmd/bucket-policy-handlers_test.go | 32 +-- cmd/erasure-bucket.go | 4 +- cmd/erasure-sets.go | 4 +- cmd/erasure-zones.go | 4 +- cmd/fs-v1.go | 4 +- cmd/gateway-unsupported.go | 4 +- cmd/gateway/nas/gateway-nas.go | 4 +- cmd/listen-notification-handlers.go | 177 +++++++++++++++ cmd/notification.go | 2 +- cmd/object-api-interface.go | 2 +- cmd/object-handlers_test.go | 120 +++++----- cmd/peer-rest-server.go | 6 +- cmd/post-policy_test.go | 4 +- cmd/server_test.go | 308 +++++++++++++------------- cmd/signature-v4-utils_test.go | 6 +- cmd/test-utils_test.go | 76 +++---- cmd/utils_test.go | 4 +- cmd/web-handlers.go | 18 ++ cmd/web-handlers_test.go | 16 +- cmd/web-router.go | 8 +- pkg/bucket/policy/action.go | 9 + pkg/event/name.go | 21 +- pkg/event/name_test.go | 7 +- pkg/iam/policy/action.go | 7 + 30 files changed, 624 insertions(+), 494 deletions(-) create mode 100644 cmd/listen-notification-handlers.go diff --git a/cmd/api-router.go b/cmd/api-router.go index 1074e3a96..1626c208d 100644 --- a/cmd/api-router.go +++ b/cmd/api-router.go @@ -214,8 +214,8 @@ func registerAPIRouter(router *mux.Router, encryptionEnabled, allowSSEKMS bool) // GetBucketNotification bucket.Methods(http.MethodGet).HandlerFunc( maxClients(collectAPIStats("getbucketnotification", httpTraceAll(api.GetBucketNotificationHandler)))).Queries("notification", "") - // ListenBucketNotification - bucket.Methods(http.MethodGet).HandlerFunc(collectAPIStats("listenbucketnotification", httpTraceAll(api.ListenBucketNotificationHandler))).Queries("events", "{events:.*}") + // ListenNotification + bucket.Methods(http.MethodGet).HandlerFunc(collectAPIStats("listennotification", httpTraceAll(api.ListenNotificationHandler))).Queries("events", "{events:.*}") // ListMultipartUploads bucket.Methods(http.MethodGet).HandlerFunc( maxClients(collectAPIStats("listmultipartuploads", httpTraceAll(api.ListMultipartUploadsHandler)))).Queries("uploads", "") @@ -282,6 +282,10 @@ func registerAPIRouter(router *mux.Router, encryptionEnabled, allowSSEKMS bool) /// Root operation + // ListenNotification + apiRouter.Methods(http.MethodGet).Path(SlashSeparator).HandlerFunc( + collectAPIStats("listennotification", httpTraceAll(api.ListenNotificationHandler))).Queries("events", "{events:.*}") + // ListBuckets apiRouter.Methods(http.MethodGet).Path(SlashSeparator).HandlerFunc( maxClients(collectAPIStats("listbuckets", httpTraceAll(api.ListBucketsHandler)))) diff --git a/cmd/auth-handler_test.go b/cmd/auth-handler_test.go index 92e72e851..bf27ccfe6 100644 --- a/cmd/auth-handler_test.go +++ b/cmd/auth-handler_test.go @@ -52,7 +52,7 @@ func TestGetRequestAuthType(t *testing.T) { "X-Amz-Content-Sha256": []string{streamingContentSHA256}, "Content-Encoding": []string{streamingContentEncoding}, }, - Method: "PUT", + Method: http.MethodPut, }, authT: authTypeStreamingSigned, }, @@ -111,7 +111,7 @@ func TestGetRequestAuthType(t *testing.T) { Header: http.Header{ "Content-Type": []string{"multipart/form-data"}, }, - Method: "POST", + Method: http.MethodPost, }, authT: authTypePostPolicy, }, @@ -212,7 +212,7 @@ func TestIsRequestPresignedSignatureV2(t *testing.T) { for i, testCase := range testCases { // creating an input HTTP request. // Only the query parameters are relevant for this particular test. - inputReq, err := http.NewRequest("GET", "http://example.com", nil) + inputReq, err := http.NewRequest(http.MethodGet, "http://example.com", nil) if err != nil { t.Fatalf("Error initializing input HTTP request: %v", err) } @@ -246,7 +246,7 @@ func TestIsRequestPresignedSignatureV4(t *testing.T) { for i, testCase := range testCases { // creating an input HTTP request. // Only the query parameters are relevant for this particular test. - inputReq, err := http.NewRequest("GET", "http://example.com", nil) + inputReq, err := http.NewRequest(http.MethodGet, "http://example.com", nil) if err != nil { t.Fatalf("Error initializing input HTTP request: %v", err) } @@ -369,15 +369,15 @@ func TestIsReqAuthenticated(t *testing.T) { s3Error APIErrorCode }{ // When request is unsigned, access denied is returned. - {mustNewRequest("GET", "http://127.0.0.1:9000", 0, nil, t), ErrAccessDenied}, + {mustNewRequest(http.MethodGet, "http://127.0.0.1:9000", 0, nil, t), ErrAccessDenied}, // Empty Content-Md5 header. - {mustNewSignedEmptyMD5Request("PUT", "http://127.0.0.1:9000/", 5, bytes.NewReader([]byte("hello")), t), ErrInvalidDigest}, + {mustNewSignedEmptyMD5Request(http.MethodPut, "http://127.0.0.1:9000/", 5, bytes.NewReader([]byte("hello")), t), ErrInvalidDigest}, // Short Content-Md5 header. - {mustNewSignedShortMD5Request("PUT", "http://127.0.0.1:9000/", 5, bytes.NewReader([]byte("hello")), t), ErrInvalidDigest}, + {mustNewSignedShortMD5Request(http.MethodPut, "http://127.0.0.1:9000/", 5, bytes.NewReader([]byte("hello")), t), ErrInvalidDigest}, // When request is properly signed, but has bad Content-MD5 header. - {mustNewSignedBadMD5Request("PUT", "http://127.0.0.1:9000/", 5, bytes.NewReader([]byte("hello")), t), ErrBadDigest}, + {mustNewSignedBadMD5Request(http.MethodPut, "http://127.0.0.1:9000/", 5, bytes.NewReader([]byte("hello")), t), ErrBadDigest}, // When request is properly signed, error is none. - {mustNewSignedRequest("GET", "http://127.0.0.1:9000", 0, nil, t), ErrNone}, + {mustNewSignedRequest(http.MethodGet, "http://127.0.0.1:9000", 0, nil, t), ErrNone}, } ctx := context.Background() @@ -413,11 +413,11 @@ func TestCheckAdminRequestAuthType(t *testing.T) { Request *http.Request ErrCode APIErrorCode }{ - {Request: mustNewRequest("GET", "http://127.0.0.1:9000", 0, nil, t), ErrCode: ErrAccessDenied}, - {Request: mustNewSignedRequest("GET", "http://127.0.0.1:9000", 0, nil, t), ErrCode: ErrNone}, - {Request: mustNewSignedV2Request("GET", "http://127.0.0.1:9000", 0, nil, t), ErrCode: ErrAccessDenied}, - {Request: mustNewPresignedV2Request("GET", "http://127.0.0.1:9000", 0, nil, t), ErrCode: ErrAccessDenied}, - {Request: mustNewPresignedRequest("GET", "http://127.0.0.1:9000", 0, nil, t), ErrCode: ErrAccessDenied}, + {Request: mustNewRequest(http.MethodGet, "http://127.0.0.1:9000", 0, nil, t), ErrCode: ErrAccessDenied}, + {Request: mustNewSignedRequest(http.MethodGet, "http://127.0.0.1:9000", 0, nil, t), ErrCode: ErrNone}, + {Request: mustNewSignedV2Request(http.MethodGet, "http://127.0.0.1:9000", 0, nil, t), ErrCode: ErrAccessDenied}, + {Request: mustNewPresignedV2Request(http.MethodGet, "http://127.0.0.1:9000", 0, nil, t), ErrCode: ErrAccessDenied}, + {Request: mustNewPresignedRequest(http.MethodGet, "http://127.0.0.1:9000", 0, nil, t), ErrCode: ErrAccessDenied}, } ctx := context.Background() for i, testCase := range testCases { @@ -461,7 +461,7 @@ func TestValidateAdminSignature(t *testing.T) { } for i, testCase := range testCases { - req := mustNewRequest("GET", "http://localhost:9000/", 0, nil, t) + req := mustNewRequest(http.MethodGet, "http://localhost:9000/", 0, nil, t) if err := signRequestV4(req, testCase.AccessKey, testCase.SecretKey); err != nil { t.Fatalf("Unable to inititalized new signed http request %s", err) } diff --git a/cmd/bucket-handlers.go b/cmd/bucket-handlers.go index 6f0c40ce5..bb861a9ae 100644 --- a/cmd/bucket-handlers.go +++ b/cmd/bucket-handlers.go @@ -578,6 +578,16 @@ func (api objectAPIHandlers) PutBucketHandler(w http.ResponseWriter, r *http.Req getObjectLocation(r, globalDomainNames, bucket, "")) writeSuccessResponseHeadersOnly(w) + + sendEvent(eventArgs{ + EventName: event.BucketCreated, + BucketName: bucket, + ReqParams: extractReqParams(r), + RespElements: extractRespElements(w), + UserAgent: r.UserAgent(), + Host: handlers.GetSourceIP(r), + }) + return } writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r)) @@ -610,6 +620,15 @@ func (api objectAPIHandlers) PutBucketHandler(w http.ResponseWriter, r *http.Req w.Header().Set(xhttp.Location, path.Clean(r.URL.Path)) // Clean any trailing slashes. writeSuccessResponseHeadersOnly(w) + + sendEvent(eventArgs{ + EventName: event.BucketCreated, + BucketName: bucket, + ReqParams: extractReqParams(r), + RespElements: extractRespElements(w), + UserAgent: r.UserAgent(), + Host: handlers.GetSourceIP(r), + }) } // PostPolicyBucketHandler - POST policy @@ -984,6 +1003,15 @@ func (api objectAPIHandlers) DeleteBucketHandler(w http.ResponseWriter, r *http. // Write success response. writeSuccessNoContent(w) + + sendEvent(eventArgs{ + EventName: event.BucketRemoved, + BucketName: bucket, + ReqParams: extractReqParams(r), + RespElements: extractRespElements(w), + UserAgent: r.UserAgent(), + Host: handlers.GetSourceIP(r), + }) } // PutBucketObjectLockConfigHandler - PUT Bucket object lock configuration. diff --git a/cmd/bucket-handlers_test.go b/cmd/bucket-handlers_test.go index 87e351ac8..a0df1724f 100644 --- a/cmd/bucket-handlers_test.go +++ b/cmd/bucket-handlers_test.go @@ -45,7 +45,7 @@ func testRemoveBucketHandler(obj ObjectLayer, instanceType, bucketName string, a // initialize httptest Recorder, this records any mutations to response writer inside the handler. rec := httptest.NewRecorder() // construct HTTP request for DELETE bucket. - req, err := newTestSignedRequestV4("DELETE", getBucketLocationURL("", bucketName), 0, nil, credentials.AccessKey, credentials.SecretKey, nil) + req, err := newTestSignedRequestV4(http.MethodDelete, getBucketLocationURL("", bucketName), 0, nil, credentials.AccessKey, credentials.SecretKey, nil) if err != nil { t.Fatalf("Test %s: Failed to create HTTP request for RemoveBucketHandler: %v", instanceType, err) } @@ -61,7 +61,7 @@ func testRemoveBucketHandler(obj ObjectLayer, instanceType, bucketName string, a // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. recV2 := httptest.NewRecorder() // construct HTTP request for DELETE bucket. - reqV2, err := newTestSignedRequestV2("DELETE", getBucketLocationURL("", bucketName), 0, nil, credentials.AccessKey, credentials.SecretKey, nil) + reqV2, err := newTestSignedRequestV2(http.MethodDelete, getBucketLocationURL("", bucketName), 0, nil, credentials.AccessKey, credentials.SecretKey, nil) if err != nil { t.Fatalf("Test %s: Failed to create HTTP request for RemoveBucketHandler: %v", instanceType, err) } @@ -129,7 +129,7 @@ func testGetBucketLocationHandler(obj ObjectLayer, instanceType, bucketName stri // initialize httptest Recorder, this records any mutations to response writer inside the handler. rec := httptest.NewRecorder() // construct HTTP request for Get bucket location. - req, err := newTestSignedRequestV4("GET", getBucketLocationURL("", testCase.bucketName), 0, nil, testCase.accessKey, testCase.secretKey, nil) + req, err := newTestSignedRequestV4(http.MethodGet, getBucketLocationURL("", testCase.bucketName), 0, nil, testCase.accessKey, testCase.secretKey, nil) if err != nil { t.Fatalf("Test %d: %s: Failed to create HTTP request for GetBucketLocationHandler: %v", i+1, instanceType, err) } @@ -161,7 +161,7 @@ func testGetBucketLocationHandler(obj ObjectLayer, instanceType, bucketName stri // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. recV2 := httptest.NewRecorder() // construct HTTP request for PUT bucket policy endpoint. - reqV2, err := newTestSignedRequestV2("GET", getBucketLocationURL("", testCase.bucketName), 0, nil, testCase.accessKey, testCase.secretKey, nil) + reqV2, err := newTestSignedRequestV2(http.MethodGet, getBucketLocationURL("", testCase.bucketName), 0, nil, testCase.accessKey, testCase.secretKey, nil) if err != nil { t.Fatalf("Test %d: %s: Failed to create HTTP request for PutBucketPolicyHandler: %v", i+1, instanceType, err) @@ -192,7 +192,7 @@ func testGetBucketLocationHandler(obj ObjectLayer, instanceType, bucketName stri // Test for Anonymous/unsigned http request. // ListBucketsHandler doesn't support bucket policies, setting the policies shouldn't make any difference. - anonReq, err := newTestRequest("GET", getBucketLocationURL("", bucketName), 0, nil) + anonReq, err := newTestRequest(http.MethodGet, getBucketLocationURL("", bucketName), 0, nil) if err != nil { t.Fatalf("MinIO %s: Failed to create an anonymous request.", instanceType) } @@ -208,7 +208,7 @@ func testGetBucketLocationHandler(obj ObjectLayer, instanceType, bucketName stri // The only aim is to generate an HTTP request in a way that the relevant/registered end point is evoked/called. nilBucket := "dummy-bucket" - nilReq, err := newTestRequest("GET", getBucketLocationURL("", nilBucket), 0, nil) + nilReq, err := newTestRequest(http.MethodGet, getBucketLocationURL("", nilBucket), 0, nil) if err != nil { t.Errorf("MinIO %s: Failed to create HTTP request for testing the response when object Layer is set to `nil`.", instanceType) @@ -265,7 +265,7 @@ func testHeadBucketHandler(obj ObjectLayer, instanceType, bucketName string, api // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. rec := httptest.NewRecorder() // construct HTTP request for HEAD bucket. - req, err := newTestSignedRequestV4("HEAD", getHEADBucketURL("", testCase.bucketName), 0, nil, testCase.accessKey, testCase.secretKey, nil) + req, err := newTestSignedRequestV4(http.MethodHead, getHEADBucketURL("", testCase.bucketName), 0, nil, testCase.accessKey, testCase.secretKey, nil) if err != nil { t.Fatalf("Test %d: %s: Failed to create HTTP request for HeadBucketHandler: %v", i+1, instanceType, err) } @@ -280,7 +280,7 @@ func testHeadBucketHandler(obj ObjectLayer, instanceType, bucketName string, api // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. recV2 := httptest.NewRecorder() // construct HTTP request for PUT bucket policy endpoint. - reqV2, err := newTestSignedRequestV2("HEAD", getHEADBucketURL("", testCase.bucketName), 0, nil, testCase.accessKey, testCase.secretKey, nil) + reqV2, err := newTestSignedRequestV2(http.MethodHead, getHEADBucketURL("", testCase.bucketName), 0, nil, testCase.accessKey, testCase.secretKey, nil) if err != nil { t.Fatalf("Test %d: %s: Failed to create HTTP request for PutBucketPolicyHandler: %v", i+1, instanceType, err) @@ -295,7 +295,7 @@ func testHeadBucketHandler(obj ObjectLayer, instanceType, bucketName string, api } // Test for Anonymous/unsigned http request. - anonReq, err := newTestRequest("HEAD", getHEADBucketURL("", bucketName), 0, nil) + anonReq, err := newTestRequest(http.MethodHead, getHEADBucketURL("", bucketName), 0, nil) if err != nil { t.Fatalf("MinIO %s: Failed to create an anonymous request for bucket \"%s\": %v", @@ -313,7 +313,7 @@ func testHeadBucketHandler(obj ObjectLayer, instanceType, bucketName string, api // The only aim is to generate an HTTP request in a way that the relevant/registered end point is evoked/called. nilBucket := "dummy-bucket" - nilReq, err := newTestRequest("HEAD", getHEADBucketURL("", nilBucket), 0, nil) + nilReq, err := newTestRequest(http.MethodHead, getHEADBucketURL("", nilBucket), 0, nil) if err != nil { t.Errorf("MinIO %s: Failed to create HTTP request for testing the response when object Layer is set to `nil`.", instanceType) @@ -482,7 +482,7 @@ func testListMultipartUploadsHandler(obj ObjectLayer, instanceType, bucketName s // construct HTTP request for List multipart uploads endpoint. u := getListMultipartUploadsURLWithParams("", testCase.bucket, testCase.prefix, testCase.keyMarker, testCase.uploadIDMarker, testCase.delimiter, testCase.maxUploads) - req, gerr := newTestSignedRequestV4("GET", u, 0, nil, testCase.accessKey, testCase.secretKey, nil) + req, gerr := newTestSignedRequestV4(http.MethodGet, u, 0, nil, testCase.accessKey, testCase.secretKey, nil) if gerr != nil { t.Fatalf("Test %d: %s: Failed to create HTTP request for ListMultipartUploadsHandler: %v", i+1, instanceType, gerr) } @@ -499,7 +499,7 @@ func testListMultipartUploadsHandler(obj ObjectLayer, instanceType, bucketName s // construct HTTP request for PUT bucket policy endpoint. // verify response for V2 signed HTTP request. - reqV2, err := newTestSignedRequestV2("GET", u, 0, nil, testCase.accessKey, testCase.secretKey, nil) + reqV2, err := newTestSignedRequestV2(http.MethodGet, u, 0, nil, testCase.accessKey, testCase.secretKey, nil) if err != nil { t.Fatalf("Test %d: %s: Failed to create HTTP request for PutBucketPolicyHandler: %v", i+1, instanceType, err) } @@ -516,7 +516,7 @@ func testListMultipartUploadsHandler(obj ObjectLayer, instanceType, bucketName s // construct HTTP request for List multipart uploads endpoint. u := getListMultipartUploadsURLWithParams("", bucketName, "", "", "", "", "") - req, err := newTestSignedRequestV4("GET", u, 0, nil, "", "", nil) // Generate an anonymous request. + req, err := newTestSignedRequestV4(http.MethodGet, u, 0, nil, "", "", nil) // Generate an anonymous request. if err != nil { t.Fatalf("Test %s: Failed to create HTTP request for ListMultipartUploadsHandler: %v", instanceType, err) } @@ -530,7 +530,7 @@ func testListMultipartUploadsHandler(obj ObjectLayer, instanceType, bucketName s url := getListMultipartUploadsURLWithParams("", testCases[6].bucket, testCases[6].prefix, testCases[6].keyMarker, testCases[6].uploadIDMarker, testCases[6].delimiter, testCases[6].maxUploads) // Test for Anonymous/unsigned http request. - anonReq, err := newTestRequest("GET", url, 0, nil) + anonReq, err := newTestRequest(http.MethodGet, url, 0, nil) if err != nil { t.Fatalf("MinIO %s: Failed to create an anonymous request for bucket \"%s\": %v", instanceType, bucketName, err) @@ -550,7 +550,7 @@ func testListMultipartUploadsHandler(obj ObjectLayer, instanceType, bucketName s url = getListMultipartUploadsURLWithParams("", nilBucket, "dummy-prefix", testCases[6].keyMarker, testCases[6].uploadIDMarker, testCases[6].delimiter, testCases[6].maxUploads) - nilReq, err := newTestRequest("GET", url, 0, nil) + nilReq, err := newTestRequest(http.MethodGet, url, 0, nil) if err != nil { t.Errorf("MinIO %s: Failed to create HTTP request for testing the response when object Layer is set to `nil`.", instanceType) @@ -596,7 +596,7 @@ func testListBucketsHandler(obj ObjectLayer, instanceType, bucketName string, ap for i, testCase := range testCases { // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. rec := httptest.NewRecorder() - req, lerr := newTestSignedRequestV4("GET", getListBucketURL(""), 0, nil, testCase.accessKey, testCase.secretKey, nil) + req, lerr := newTestSignedRequestV4(http.MethodGet, getListBucketURL(""), 0, nil, testCase.accessKey, testCase.secretKey, nil) if lerr != nil { t.Fatalf("Test %d: %s: Failed to create HTTP request for ListBucketsHandler: %v", i+1, instanceType, lerr) } @@ -613,7 +613,7 @@ func testListBucketsHandler(obj ObjectLayer, instanceType, bucketName string, ap // construct HTTP request for PUT bucket policy endpoint. // verify response for V2 signed HTTP request. - reqV2, err := newTestSignedRequestV2("GET", getListBucketURL(""), 0, nil, testCase.accessKey, testCase.secretKey, nil) + reqV2, err := newTestSignedRequestV2(http.MethodGet, getListBucketURL(""), 0, nil, testCase.accessKey, testCase.secretKey, nil) if err != nil { t.Fatalf("Test %d: %s: Failed to create HTTP request for PutBucketPolicyHandler: %v", i+1, instanceType, err) @@ -628,7 +628,7 @@ func testListBucketsHandler(obj ObjectLayer, instanceType, bucketName string, ap // Test for Anonymous/unsigned http request. // ListBucketsHandler doesn't support bucket policies, setting the policies shouldn't make a difference. - anonReq, err := newTestRequest("GET", getListBucketURL(""), 0, nil) + anonReq, err := newTestRequest(http.MethodGet, getListBucketURL(""), 0, nil) if err != nil { t.Fatalf("MinIO %s: Failed to create an anonymous request.", instanceType) @@ -644,7 +644,7 @@ func testListBucketsHandler(obj ObjectLayer, instanceType, bucketName string, ap // since the `objectLayer==nil` check is performed before any other checks inside the handlers. // The only aim is to generate an HTTP request in a way that the relevant/registered end point is evoked/called. - nilReq, err := newTestRequest("GET", getListBucketURL(""), 0, nil) + nilReq, err := newTestRequest(http.MethodGet, getListBucketURL(""), 0, nil) if err != nil { t.Errorf("MinIO %s: Failed to create HTTP request for testing the response when object Layer is set to `nil`.", instanceType) @@ -808,10 +808,10 @@ func testAPIDeleteMultipleObjectsHandler(obj ObjectLayer, instanceType, bucketNa // Generate a signed or anonymous request based on the testCase if testCase.accessKey != "" { - req, err = newTestSignedRequestV4("POST", getDeleteMultipleObjectsURL("", bucketName), + req, err = newTestSignedRequestV4(http.MethodPost, getDeleteMultipleObjectsURL("", bucketName), int64(len(testCase.objects)), bytes.NewReader(testCase.objects), testCase.accessKey, testCase.secretKey, nil) } else { - req, err = newTestRequest("POST", getDeleteMultipleObjectsURL("", bucketName), + req, err = newTestRequest(http.MethodPost, getDeleteMultipleObjectsURL("", bucketName), int64(len(testCase.objects)), bytes.NewReader(testCase.objects)) } @@ -850,7 +850,7 @@ func testAPIDeleteMultipleObjectsHandler(obj ObjectLayer, instanceType, bucketNa nilBucket := "dummy-bucket" nilObject := "" - nilReq, err := newTestSignedRequestV4("POST", getDeleteMultipleObjectsURL("", nilBucket), 0, nil, "", "", nil) + nilReq, err := newTestSignedRequestV4(http.MethodPost, getDeleteMultipleObjectsURL("", nilBucket), 0, nil, "", "", nil) if err != nil { t.Errorf("MinIO %s: Failed to create HTTP request for testing the response when object Layer is set to `nil`.", instanceType) } diff --git a/cmd/bucket-lifecycle-handlers_test.go b/cmd/bucket-lifecycle-handlers_test.go index 3af5daf05..cd8857f26 100644 --- a/cmd/bucket-lifecycle-handlers_test.go +++ b/cmd/bucket-lifecycle-handlers_test.go @@ -50,7 +50,7 @@ func testBucketLifecycleHandlersWrongCredentials(obj ObjectLayer, instanceType, }{ // GET empty credentials { - method: "GET", bucketName: bucketName, + method: http.MethodGet, bucketName: bucketName, accessKey: "", secretKey: "", expectedRespStatus: http.StatusForbidden, @@ -64,7 +64,7 @@ func testBucketLifecycleHandlersWrongCredentials(obj ObjectLayer, instanceType, }, // GET wrong credentials { - method: "GET", bucketName: bucketName, + method: http.MethodGet, bucketName: bucketName, accessKey: "abcd", secretKey: "abcd", expectedRespStatus: http.StatusForbidden, @@ -78,7 +78,7 @@ func testBucketLifecycleHandlersWrongCredentials(obj ObjectLayer, instanceType, }, // PUT empty credentials { - method: "PUT", + method: http.MethodPut, bucketName: bucketName, accessKey: "", secretKey: "", @@ -93,7 +93,7 @@ func testBucketLifecycleHandlersWrongCredentials(obj ObjectLayer, instanceType, }, // PUT wrong credentials { - method: "PUT", + method: http.MethodPut, bucketName: bucketName, accessKey: "abcd", secretKey: "abcd", @@ -108,7 +108,7 @@ func testBucketLifecycleHandlersWrongCredentials(obj ObjectLayer, instanceType, }, // DELETE empty credentials { - method: "DELETE", + method: http.MethodDelete, bucketName: bucketName, accessKey: "", secretKey: "", @@ -123,7 +123,7 @@ func testBucketLifecycleHandlersWrongCredentials(obj ObjectLayer, instanceType, }, // DELETE wrong credentials { - method: "DELETE", + method: http.MethodDelete, bucketName: bucketName, accessKey: "abcd", secretKey: "abcd", @@ -168,7 +168,7 @@ func testBucketLifecycleHandlers(obj ObjectLayer, instanceType, bucketName strin // Test case - 1. // Filter contains more than (Prefix,Tag,And) rule { - method: "PUT", + method: http.MethodPut, bucketName: bucketName, accessKey: creds.AccessKey, secretKey: creds.SecretKey, @@ -185,7 +185,7 @@ func testBucketLifecycleHandlers(obj ObjectLayer, instanceType, bucketName strin }, // Date contains wrong format { - method: "PUT", + method: http.MethodPut, bucketName: bucketName, accessKey: creds.AccessKey, secretKey: creds.SecretKey, @@ -201,7 +201,7 @@ func testBucketLifecycleHandlers(obj ObjectLayer, instanceType, bucketName strin shouldPass: false, }, { - method: "PUT", + method: http.MethodPut, bucketName: bucketName, accessKey: creds.AccessKey, secretKey: creds.SecretKey, @@ -212,7 +212,7 @@ func testBucketLifecycleHandlers(obj ObjectLayer, instanceType, bucketName strin shouldPass: true, }, { - method: "GET", + method: http.MethodGet, accessKey: creds.AccessKey, secretKey: creds.SecretKey, bucketName: bucketName, @@ -223,7 +223,7 @@ func testBucketLifecycleHandlers(obj ObjectLayer, instanceType, bucketName strin shouldPass: true, }, { - method: "DELETE", + method: http.MethodDelete, accessKey: creds.AccessKey, secretKey: creds.SecretKey, bucketName: bucketName, @@ -234,7 +234,7 @@ func testBucketLifecycleHandlers(obj ObjectLayer, instanceType, bucketName strin shouldPass: true, }, { - method: "GET", + method: http.MethodGet, accessKey: creds.AccessKey, secretKey: creds.SecretKey, bucketName: bucketName, diff --git a/cmd/bucket-notification-handlers.go b/cmd/bucket-notification-handlers.go index 36367d32b..40d9325b1 100644 --- a/cmd/bucket-notification-handlers.go +++ b/cmd/bucket-notification-handlers.go @@ -17,15 +17,12 @@ package cmd import ( - "encoding/json" "encoding/xml" "io" "net/http" "reflect" - "time" "github.com/gorilla/mux" - xhttp "github.com/minio/minio/cmd/http" "github.com/minio/minio/cmd/logger" "github.com/minio/minio/pkg/bucket/policy" "github.com/minio/minio/pkg/event" @@ -173,137 +170,3 @@ func (api objectAPIHandlers) PutBucketNotificationHandler(w http.ResponseWriter, writeSuccessResponseHeadersOnly(w) } - -func (api objectAPIHandlers) ListenBucketNotificationHandler(w http.ResponseWriter, r *http.Request) { - ctx := newContext(r, w, "ListenBucketNotification") - - defer logger.AuditLog(w, r, "ListenBucketNotification", mustGetClaimsFromToken(r)) - - // Validate if bucket exists. - objAPI := api.ObjectAPI() - if objAPI == nil { - writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r)) - return - } - - if !objAPI.IsNotificationSupported() { - writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL, guessIsBrowserReq(r)) - return - } - - if !objAPI.IsListenBucketSupported() { - writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL, guessIsBrowserReq(r)) - return - } - - vars := mux.Vars(r) - bucketName := vars["bucket"] - - values := r.URL.Query() - values.Set(peerRESTListenBucket, bucketName) - - var prefix string - if len(values[peerRESTListenPrefix]) > 1 { - writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrFilterNamePrefix), r.URL, guessIsBrowserReq(r)) - return - } - - if len(values[peerRESTListenPrefix]) == 1 { - if err := event.ValidateFilterRuleValue(values[peerRESTListenPrefix][0]); err != nil { - writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r)) - return - } - - prefix = values[peerRESTListenPrefix][0] - } - - var suffix string - if len(values[peerRESTListenSuffix]) > 1 { - writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrFilterNameSuffix), r.URL, guessIsBrowserReq(r)) - return - } - - if len(values[peerRESTListenSuffix]) == 1 { - if err := event.ValidateFilterRuleValue(values[peerRESTListenSuffix][0]); err != nil { - writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r)) - return - } - - suffix = values[peerRESTListenSuffix][0] - } - - pattern := event.NewPattern(prefix, suffix) - - var eventNames []event.Name - for _, s := range values[peerRESTListenEvents] { - eventName, err := event.ParseName(s) - if err != nil { - writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r)) - return - } - - eventNames = append(eventNames, eventName) - } - - if _, err := objAPI.GetBucketInfo(ctx, bucketName); err != nil { - writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r)) - return - } - - rulesMap := event.NewRulesMap(eventNames, pattern, event.TargetID{ID: mustGetUUID()}) - - w.Header().Set(xhttp.ContentType, "text/event-stream") - - // Listen Publisher and peer-listen-client uses nonblocking send and hence does not wait for slow receivers. - // Use buffered channel to take care of burst sends or slow w.Write() - listenCh := make(chan interface{}, 4000) - - peers := newPeerRestClients(globalEndpoints) - - globalHTTPListen.Subscribe(listenCh, ctx.Done(), func(evI interface{}) bool { - ev, ok := evI.(event.Event) - if !ok { - return false - } - if ev.S3.Bucket.Name != values.Get(peerRESTListenBucket) { - return false - } - return rulesMap.MatchSimple(ev.EventName, ev.S3.Object.Key) - }) - - for _, peer := range peers { - if peer == nil { - continue - } - peer.Listen(listenCh, ctx.Done(), values) - } - - keepAliveTicker := time.NewTicker(500 * time.Millisecond) - defer keepAliveTicker.Stop() - - enc := json.NewEncoder(w) - for { - select { - case evI := <-listenCh: - ev := evI.(event.Event) - if len(string(ev.EventName)) > 0 { - if err := enc.Encode(struct{ Records []event.Event }{[]event.Event{ev}}); err != nil { - return - } - } else { - if _, err := w.Write([]byte(" ")); err != nil { - return - } - } - w.(http.Flusher).Flush() - case <-keepAliveTicker.C: - if _, err := w.Write([]byte(" ")); err != nil { - return - } - w.(http.Flusher).Flush() - case <-ctx.Done(): - return - } - } - -} diff --git a/cmd/bucket-policy-handlers_test.go b/cmd/bucket-policy-handlers_test.go index c5a3579cc..428ae4576 100644 --- a/cmd/bucket-policy-handlers_test.go +++ b/cmd/bucket-policy-handlers_test.go @@ -252,7 +252,7 @@ func testPutBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName string // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. recV4 := httptest.NewRecorder() // construct HTTP request for PUT bucket policy endpoint. - reqV4, err := newTestSignedRequestV4("PUT", getPutPolicyURL("", testCase.bucketName), + reqV4, err := newTestSignedRequestV4(http.MethodPut, getPutPolicyURL("", testCase.bucketName), int64(testCase.policyLen), testCase.bucketPolicyReader, testCase.accessKey, testCase.secretKey, nil) if err != nil { t.Fatalf("Test %d: %s: Failed to create HTTP request for PutBucketPolicyHandler: %v", i+1, instanceType, err) @@ -266,7 +266,7 @@ func testPutBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName string // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. recV2 := httptest.NewRecorder() // construct HTTP request for PUT bucket policy endpoint. - reqV2, err := newTestSignedRequestV2("PUT", getPutPolicyURL("", testCase.bucketName), + reqV2, err := newTestSignedRequestV2(http.MethodPut, getPutPolicyURL("", testCase.bucketName), int64(testCase.policyLen), testCase.bucketPolicyReader, testCase.accessKey, testCase.secretKey, nil) if err != nil { t.Fatalf("Test %d: %s: Failed to create HTTP request for PutBucketPolicyHandler: %v", i+1, instanceType, err) @@ -283,7 +283,7 @@ func testPutBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName string // Bucket policy related functions doesn't support anonymous requests, setting policies shouldn't make a difference. bucketPolicyStr := fmt.Sprintf(bucketPolicyTemplate, bucketName, bucketName) // create unsigned HTTP request for PutBucketPolicyHandler. - anonReq, err := newTestRequest("PUT", getPutPolicyURL("", bucketName), + anonReq, err := newTestRequest(http.MethodPut, getPutPolicyURL("", bucketName), int64(len(bucketPolicyStr)), bytes.NewReader([]byte(bucketPolicyStr))) if err != nil { @@ -302,7 +302,7 @@ func testPutBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName string // The only aim is to generate an HTTP request in a way that the relevant/registered end point is evoked/called. nilBucket := "dummy-bucket" - nilReq, err := newTestSignedRequestV4("PUT", getPutPolicyURL("", nilBucket), + nilReq, err := newTestSignedRequestV4(http.MethodPut, getPutPolicyURL("", nilBucket), 0, nil, "", "", nil) if err != nil { @@ -344,7 +344,7 @@ func testGetBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName string // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. recV4 := httptest.NewRecorder() // construct HTTP request for PUT bucket policy endpoint. - reqV4, err := newTestSignedRequestV4("PUT", getPutPolicyURL("", testPolicy.bucketName), + reqV4, err := newTestSignedRequestV4(http.MethodPut, getPutPolicyURL("", testPolicy.bucketName), int64(len(bucketPolicyStr)), bytes.NewReader([]byte(bucketPolicyStr)), testPolicy.accessKey, testPolicy.secretKey, nil) if err != nil { t.Fatalf("Test %d: Failed to create HTTP request for PutBucketPolicyHandler: %v", i+1, err) @@ -358,7 +358,7 @@ func testGetBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName string // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. recV2 := httptest.NewRecorder() // construct HTTP request for PUT bucket policy endpoint. - reqV2, err := newTestSignedRequestV2("PUT", getPutPolicyURL("", testPolicy.bucketName), + reqV2, err := newTestSignedRequestV2(http.MethodPut, getPutPolicyURL("", testPolicy.bucketName), int64(len(bucketPolicyStr)), bytes.NewReader([]byte(bucketPolicyStr)), testPolicy.accessKey, testPolicy.secretKey, nil) if err != nil { t.Fatalf("Test %d: Failed to create HTTP request for PutBucketPolicyHandler: %v", i+1, err) @@ -415,7 +415,7 @@ func testGetBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName string // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. recV4 := httptest.NewRecorder() // construct HTTP request for PUT bucket policy endpoint. - reqV4, err := newTestSignedRequestV4("GET", getGetPolicyURL("", testCase.bucketName), + reqV4, err := newTestSignedRequestV4(http.MethodGet, getGetPolicyURL("", testCase.bucketName), 0, nil, testCase.accessKey, testCase.secretKey, nil) if err != nil { @@ -454,7 +454,7 @@ func testGetBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName string // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. recV2 := httptest.NewRecorder() // construct HTTP request for PUT bucket policy endpoint. - reqV2, err := newTestSignedRequestV2("GET", getGetPolicyURL("", testCase.bucketName), + reqV2, err := newTestSignedRequestV2(http.MethodGet, getGetPolicyURL("", testCase.bucketName), 0, nil, testCase.accessKey, testCase.secretKey, nil) if err != nil { t.Fatalf("Test %d: Failed to create HTTP request for GetBucketPolicyHandler: %v", i+1, err) @@ -491,7 +491,7 @@ func testGetBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName string // Test for Anonymous/unsigned http request. // Bucket policy related functions doesn't support anonymous requests, setting policies shouldn't make a difference. // create unsigned HTTP request for PutBucketPolicyHandler. - anonReq, err := newTestRequest("GET", getPutPolicyURL("", bucketName), 0, nil) + anonReq, err := newTestRequest(http.MethodGet, getPutPolicyURL("", bucketName), 0, nil) if err != nil { t.Fatalf("MinIO %s: Failed to create an anonymous request for bucket \"%s\": %v", @@ -509,7 +509,7 @@ func testGetBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName string // The only aim is to generate an HTTP request in a way that the relevant/registered end point is evoked/called. nilBucket := "dummy-bucket" - nilReq, err := newTestSignedRequestV4("GET", getGetPolicyURL("", nilBucket), + nilReq, err := newTestSignedRequestV4(http.MethodGet, getGetPolicyURL("", nilBucket), 0, nil, "", "", nil) if err != nil { @@ -589,7 +589,7 @@ func testDeleteBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName str // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. recV4 := httptest.NewRecorder() // construct HTTP request for PUT bucket policy endpoint. - reqV4, err := newTestSignedRequestV4("PUT", getPutPolicyURL("", testPolicy.bucketName), + reqV4, err := newTestSignedRequestV4(http.MethodPut, getPutPolicyURL("", testPolicy.bucketName), int64(len(bucketPolicyStr)), bytes.NewReader([]byte(bucketPolicyStr)), testPolicy.accessKey, testPolicy.secretKey, nil) if err != nil { t.Fatalf("Test %d: Failed to create HTTP request for PutBucketPolicyHandler: %v", i+1, err) @@ -639,7 +639,7 @@ func testDeleteBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName str // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. recV4 := httptest.NewRecorder() // construct HTTP request for Delete bucket policy endpoint. - reqV4, err := newTestSignedRequestV4("DELETE", getDeletePolicyURL("", testCase.bucketName), + reqV4, err := newTestSignedRequestV4(http.MethodDelete, getDeletePolicyURL("", testCase.bucketName), 0, nil, testCase.accessKey, testCase.secretKey, nil) if err != nil { t.Fatalf("Test %d: Failed to create HTTP request for GetBucketPolicyHandler: %v", i+1, err) @@ -661,7 +661,7 @@ func testDeleteBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName str // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. recV2 := httptest.NewRecorder() // construct HTTP request for PUT bucket policy endpoint. - reqV2, err := newTestSignedRequestV2("PUT", getPutPolicyURL("", testPolicy.bucketName), + reqV2, err := newTestSignedRequestV2(http.MethodPut, getPutPolicyURL("", testPolicy.bucketName), int64(len(bucketPolicyStr)), bytes.NewReader([]byte(bucketPolicyStr)), testPolicy.accessKey, testPolicy.secretKey, nil) if err != nil { t.Fatalf("Test %d: Failed to create HTTP request for PutBucketPolicyHandler: %v", i+1, err) @@ -678,7 +678,7 @@ func testDeleteBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName str // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. recV2 := httptest.NewRecorder() // construct HTTP request for Delete bucket policy endpoint. - reqV2, err := newTestSignedRequestV2("DELETE", getDeletePolicyURL("", testCase.bucketName), + reqV2, err := newTestSignedRequestV2(http.MethodDelete, getDeletePolicyURL("", testCase.bucketName), 0, nil, testCase.accessKey, testCase.secretKey, nil) if err != nil { t.Fatalf("Test %d: Failed to create HTTP request for GetBucketPolicyHandler: %v", i+1, err) @@ -694,7 +694,7 @@ func testDeleteBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName str // Test for Anonymous/unsigned http request. // Bucket policy related functions doesn't support anonymous requests, setting policies shouldn't make a difference. // create unsigned HTTP request for PutBucketPolicyHandler. - anonReq, err := newTestRequest("DELETE", getPutPolicyURL("", bucketName), 0, nil) + anonReq, err := newTestRequest(http.MethodDelete, getPutPolicyURL("", bucketName), 0, nil) if err != nil { t.Fatalf("MinIO %s: Failed to create an anonymous request for bucket \"%s\": %v", @@ -712,7 +712,7 @@ func testDeleteBucketPolicyHandler(obj ObjectLayer, instanceType, bucketName str // The only aim is to generate an HTTP request in a way that the relevant/registered end point is evoked/called. nilBucket := "dummy-bucket" - nilReq, err := newTestSignedRequestV4("DELETE", getDeletePolicyURL("", nilBucket), + nilReq, err := newTestSignedRequestV4(http.MethodDelete, getDeletePolicyURL("", nilBucket), 0, nil, "", "", nil) if err != nil { diff --git a/cmd/erasure-bucket.go b/cmd/erasure-bucket.go index 3a015d608..14b680e83 100644 --- a/cmd/erasure-bucket.go +++ b/cmd/erasure-bucket.go @@ -254,8 +254,8 @@ func (er erasureObjects) IsNotificationSupported() bool { return true } -// IsListenBucketSupported returns whether listen bucket notification is applicable for this layer. -func (er erasureObjects) IsListenBucketSupported() bool { +// IsListenSupported returns whether listen bucket notification is applicable for this layer. +func (er erasureObjects) IsListenSupported() bool { return true } diff --git a/cmd/erasure-sets.go b/cmd/erasure-sets.go index 774f4c463..913a20f4f 100644 --- a/cmd/erasure-sets.go +++ b/cmd/erasure-sets.go @@ -576,8 +576,8 @@ func (s *erasureSets) IsNotificationSupported() bool { return s.getHashedSet("").IsNotificationSupported() } -// IsListenBucketSupported returns whether listen bucket notification is applicable for this layer. -func (s *erasureSets) IsListenBucketSupported() bool { +// IsListenSupported returns whether listen bucket notification is applicable for this layer. +func (s *erasureSets) IsListenSupported() bool { return true } diff --git a/cmd/erasure-zones.go b/cmd/erasure-zones.go index 1fbf31dd4..09499643c 100644 --- a/cmd/erasure-zones.go +++ b/cmd/erasure-zones.go @@ -1614,8 +1614,8 @@ func (z *erasureZones) IsNotificationSupported() bool { return true } -// IsListenBucketSupported returns whether listen bucket notification is applicable for this layer. -func (z *erasureZones) IsListenBucketSupported() bool { +// IsListenSupported returns whether listen bucket notification is applicable for this layer. +func (z *erasureZones) IsListenSupported() bool { return true } diff --git a/cmd/fs-v1.go b/cmd/fs-v1.go index aa1569b70..fe3b1773e 100644 --- a/cmd/fs-v1.go +++ b/cmd/fs-v1.go @@ -1537,8 +1537,8 @@ func (fs *FSObjects) IsNotificationSupported() bool { return true } -// IsListenBucketSupported returns whether listen bucket notification is applicable for this layer. -func (fs *FSObjects) IsListenBucketSupported() bool { +// IsListenSupported returns whether listen bucket notification is applicable for this layer. +func (fs *FSObjects) IsListenSupported() bool { return true } diff --git a/cmd/gateway-unsupported.go b/cmd/gateway-unsupported.go index a51f5fdf1..f626675f5 100644 --- a/cmd/gateway-unsupported.go +++ b/cmd/gateway-unsupported.go @@ -230,8 +230,8 @@ func (a GatewayUnsupported) IsNotificationSupported() bool { return false } -// IsListenBucketSupported returns whether listen bucket notification is applicable for this layer. -func (a GatewayUnsupported) IsListenBucketSupported() bool { +// IsListenSupported returns whether listen bucket notification is applicable for this layer. +func (a GatewayUnsupported) IsListenSupported() bool { return false } diff --git a/cmd/gateway/nas/gateway-nas.go b/cmd/gateway/nas/gateway-nas.go index e368b9755..ed332b07a 100644 --- a/cmd/gateway/nas/gateway-nas.go +++ b/cmd/gateway/nas/gateway-nas.go @@ -104,8 +104,8 @@ func (g *NAS) Production() bool { return true } -// IsListenBucketSupported returns whether listen bucket notification is applicable for this gateway. -func (n *nasObjects) IsListenBucketSupported() bool { +// IsListenSupported returns whether listen bucket notification is applicable for this gateway. +func (n *nasObjects) IsListenSupported() bool { return false } diff --git a/cmd/listen-notification-handlers.go b/cmd/listen-notification-handlers.go new file mode 100644 index 000000000..6ec5a99e7 --- /dev/null +++ b/cmd/listen-notification-handlers.go @@ -0,0 +1,177 @@ +/* + * MinIO Cloud Storage, (C) 2020 MinIO, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cmd + +import ( + "encoding/json" + "net/http" + "time" + + "github.com/gorilla/mux" + xhttp "github.com/minio/minio/cmd/http" + "github.com/minio/minio/cmd/logger" + policy "github.com/minio/minio/pkg/bucket/policy" + "github.com/minio/minio/pkg/event" +) + +func (api objectAPIHandlers) ListenNotificationHandler(w http.ResponseWriter, r *http.Request) { + ctx := newContext(r, w, "ListenNotification") + + defer logger.AuditLog(w, r, "ListenNotification", mustGetClaimsFromToken(r)) + + // Validate if bucket exists. + objAPI := api.ObjectAPI() + if objAPI == nil { + writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrServerNotInitialized), r.URL, guessIsBrowserReq(r)) + return + } + + if !objAPI.IsNotificationSupported() { + writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL, guessIsBrowserReq(r)) + return + } + + if !objAPI.IsListenSupported() { + writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL, guessIsBrowserReq(r)) + return + } + + vars := mux.Vars(r) + bucketName := vars["bucket"] + + if bucketName == "" { + if s3Error := checkRequestAuthType(ctx, r, policy.ListenNotificationAction, bucketName, ""); s3Error != ErrNone { + writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r)) + return + } + } else { + if s3Error := checkRequestAuthType(ctx, r, policy.ListenBucketNotificationAction, bucketName, ""); s3Error != ErrNone { + writeErrorResponse(ctx, w, errorCodes.ToAPIErr(s3Error), r.URL, guessIsBrowserReq(r)) + return + } + } + + values := r.URL.Query() + + var prefix string + if len(values[peerRESTListenPrefix]) > 1 { + writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrFilterNamePrefix), r.URL, guessIsBrowserReq(r)) + return + } + + if len(values[peerRESTListenPrefix]) == 1 { + if err := event.ValidateFilterRuleValue(values[peerRESTListenPrefix][0]); err != nil { + writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r)) + return + } + + prefix = values[peerRESTListenPrefix][0] + } + + var suffix string + if len(values[peerRESTListenSuffix]) > 1 { + writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrFilterNameSuffix), r.URL, guessIsBrowserReq(r)) + return + } + + if len(values[peerRESTListenSuffix]) == 1 { + if err := event.ValidateFilterRuleValue(values[peerRESTListenSuffix][0]); err != nil { + writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r)) + return + } + + suffix = values[peerRESTListenSuffix][0] + } + + pattern := event.NewPattern(prefix, suffix) + + var eventNames []event.Name + for _, s := range values[peerRESTListenEvents] { + eventName, err := event.ParseName(s) + if err != nil { + writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r)) + return + } + + eventNames = append(eventNames, eventName) + } + + if bucketName != "" { + if _, err := objAPI.GetBucketInfo(ctx, bucketName); err != nil { + writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r)) + return + } + } + + rulesMap := event.NewRulesMap(eventNames, pattern, event.TargetID{ID: mustGetUUID()}) + + w.Header().Set(xhttp.ContentType, "text/event-stream") + + // Listen Publisher and peer-listen-client uses nonblocking send and hence does not wait for slow receivers. + // Use buffered channel to take care of burst sends or slow w.Write() + listenCh := make(chan interface{}, 4000) + + peers := newPeerRestClients(globalEndpoints) + + globalHTTPListen.Subscribe(listenCh, ctx.Done(), func(evI interface{}) bool { + ev, ok := evI.(event.Event) + if !ok { + return false + } + if ev.S3.Bucket.Name != "" && bucketName != "" { + if ev.S3.Bucket.Name != bucketName { + return false + } + } + return rulesMap.MatchSimple(ev.EventName, ev.S3.Object.Key) + }) + + for _, peer := range peers { + if peer == nil { + continue + } + peer.Listen(listenCh, ctx.Done(), values) + } + + keepAliveTicker := time.NewTicker(500 * time.Millisecond) + defer keepAliveTicker.Stop() + + enc := json.NewEncoder(w) + for { + select { + case evI := <-listenCh: + ev := evI.(event.Event) + if len(string(ev.EventName)) > 0 { + if err := enc.Encode(struct{ Records []event.Event }{[]event.Event{ev}}); err != nil { + return + } + } else { + if _, err := w.Write([]byte(" ")); err != nil { + return + } + } + w.(http.Flusher).Flush() + case <-keepAliveTicker.C: + if _, err := w.Write([]byte(" ")); err != nil { + return + } + w.(http.Flusher).Flush() + case <-ctx.Done(): + return + } + } +} diff --git a/cmd/notification.go b/cmd/notification.go index 320a34eb4..8f04ea8b1 100644 --- a/cmd/notification.go +++ b/cmd/notification.go @@ -58,7 +58,7 @@ func (sys *NotificationSys) GetARNList(onlyActive bool) []string { } region := globalServerRegion for targetID, target := range sys.targetList.TargetMap() { - // httpclient target is part of ListenBucketNotification + // httpclient target is part of ListenNotification // which doesn't need to be listed as part of the ARN list // This list is only meant for external targets, filter // this out pro-actively. diff --git a/cmd/object-api-interface.go b/cmd/object-api-interface.go index 3fac029ee..e19ea5cab 100644 --- a/cmd/object-api-interface.go +++ b/cmd/object-api-interface.go @@ -125,7 +125,7 @@ type ObjectLayer interface { // Supported operations check IsNotificationSupported() bool - IsListenBucketSupported() bool + IsListenSupported() bool IsEncryptionSupported() bool IsTaggingSupported() bool IsCompressionSupported() bool diff --git a/cmd/object-handlers_test.go b/cmd/object-handlers_test.go index f953657f9..0f6b598dd 100644 --- a/cmd/object-handlers_test.go +++ b/cmd/object-handlers_test.go @@ -137,7 +137,7 @@ func testAPIHeadObjectHandler(obj ObjectLayer, instanceType, bucketName string, // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. rec := httptest.NewRecorder() // construct HTTP request for Get Object end point. - req, err := newTestSignedRequestV4("HEAD", getHeadObjectURL("", testCase.bucketName, testCase.objectName), + req, err := newTestSignedRequestV4(http.MethodHead, getHeadObjectURL("", testCase.bucketName, testCase.objectName), 0, nil, testCase.accessKey, testCase.secretKey, nil) if err != nil { t.Fatalf("Test %d: %s: Failed to create HTTP request for Head Object: %v", i+1, instanceType, err) @@ -155,7 +155,7 @@ func testAPIHeadObjectHandler(obj ObjectLayer, instanceType, bucketName string, // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. recV2 := httptest.NewRecorder() // construct HTTP request for Head Object endpoint. - reqV2, err := newTestSignedRequestV2("HEAD", getHeadObjectURL("", testCase.bucketName, testCase.objectName), + reqV2, err := newTestSignedRequestV2(http.MethodHead, getHeadObjectURL("", testCase.bucketName, testCase.objectName), 0, nil, testCase.accessKey, testCase.secretKey, nil) if err != nil { @@ -171,7 +171,7 @@ func testAPIHeadObjectHandler(obj ObjectLayer, instanceType, bucketName string, } // Test for Anonymous/unsigned http request. - anonReq, err := newTestRequest("HEAD", getHeadObjectURL("", bucketName, objectName), 0, nil) + anonReq, err := newTestRequest(http.MethodHead, getHeadObjectURL("", bucketName, objectName), 0, nil) if err != nil { t.Fatalf("MinIO %s: Failed to create an anonymous request for %s/%s: %v", @@ -190,7 +190,7 @@ func testAPIHeadObjectHandler(obj ObjectLayer, instanceType, bucketName string, nilBucket := "dummy-bucket" nilObject := "dummy-object" - nilReq, err := newTestSignedRequestV4("HEAD", getGetObjectURL("", nilBucket, nilObject), + nilReq, err := newTestSignedRequestV4(http.MethodHead, getGetObjectURL("", nilBucket, nilObject), 0, nil, "", "", nil) if err != nil { @@ -276,7 +276,7 @@ func testAPIHeadObjectHandlerWithEncryption(obj ObjectLayer, instanceType, bucke // mutations to response writer inside the handler. rec := httptest.NewRecorder() // construct HTTP request for HEAD object. - req, err := newTestSignedRequestV4("HEAD", getHeadObjectURL("", bucketName, input.objectName), + req, err := newTestSignedRequestV4(http.MethodHead, getHeadObjectURL("", bucketName, input.objectName), 0, nil, credentials.AccessKey, credentials.SecretKey, nil) if err != nil { t.Fatalf("Test %d: %s: Failed to create HTTP request for Head Object: %v", i+1, instanceType, err) @@ -301,7 +301,7 @@ func testAPIHeadObjectHandlerWithEncryption(obj ObjectLayer, instanceType, bucke // mutations to response writer inside the handler. rec := httptest.NewRecorder() // construct HTTP request for HEAD object. - req, err := newTestSignedRequestV4("HEAD", getHeadObjectURL("", bucketName, input.objectName), + req, err := newTestSignedRequestV4(http.MethodHead, getHeadObjectURL("", bucketName, input.objectName), 0, nil, credentials.AccessKey, credentials.SecretKey, input.metaData) if err != nil { t.Fatalf("Test %d: %s: Failed to create HTTP request for Head Object: %v", i+1, instanceType, err) @@ -522,7 +522,7 @@ func testAPIGetObjectHandler(obj ObjectLayer, instanceType, bucketName string, a // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. rec := httptest.NewRecorder() // construct HTTP request for Get Object end point. - req, err := newTestSignedRequestV4("GET", getGetObjectURL("", testCase.bucketName, testCase.objectName), + req, err := newTestSignedRequestV4(http.MethodGet, getGetObjectURL("", testCase.bucketName, testCase.objectName), 0, nil, testCase.accessKey, testCase.secretKey, nil) if err != nil { @@ -569,7 +569,7 @@ func testAPIGetObjectHandler(obj ObjectLayer, instanceType, bucketName string, a // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. recV2 := httptest.NewRecorder() // construct HTTP request for GET Object endpoint. - reqV2, err := newTestSignedRequestV2("GET", getGetObjectURL("", testCase.bucketName, testCase.objectName), + reqV2, err := newTestSignedRequestV2(http.MethodGet, getGetObjectURL("", testCase.bucketName, testCase.objectName), 0, nil, testCase.accessKey, testCase.secretKey, nil) if err != nil { @@ -616,7 +616,7 @@ func testAPIGetObjectHandler(obj ObjectLayer, instanceType, bucketName string, a } // Test for Anonymous/unsigned http request. - anonReq, err := newTestRequest("GET", getGetObjectURL("", bucketName, objectName), 0, nil) + anonReq, err := newTestRequest(http.MethodGet, getGetObjectURL("", bucketName, objectName), 0, nil) if err != nil { t.Fatalf("MinIO %s: Failed to create an anonymous request for %s/%s: %v", @@ -635,7 +635,7 @@ func testAPIGetObjectHandler(obj ObjectLayer, instanceType, bucketName string, a nilBucket := "dummy-bucket" nilObject := "dummy-object" - nilReq, err := newTestSignedRequestV4("GET", getGetObjectURL("", nilBucket, nilObject), + nilReq, err := newTestSignedRequestV4(http.MethodGet, getGetObjectURL("", nilBucket, nilObject), 0, nil, "", "", nil) if err != nil { @@ -733,7 +733,7 @@ func testAPIGetObjectWithMPHandler(obj ObjectLayer, instanceType, bucketName str mkGetReq := func(oi ObjectInput, byteRange string, i int, mkSignedReq testSignedReqFn) { object := oi.objectName rec := httptest.NewRecorder() - req, err := mkSignedReq("GET", getGetObjectURL("", bucketName, object), + req, err := mkSignedReq(http.MethodGet, getGetObjectURL("", bucketName, object), 0, nil, credentials.AccessKey, credentials.SecretKey, oi.metaData) if err != nil { t.Fatalf("Object: %s Case %d ByteRange: %s: Failed to create HTTP request for Get Object: %v", @@ -832,7 +832,7 @@ func testAPIGetObjectWithMPHandler(obj ObjectLayer, instanceType, bucketName str nilBucket := "dummy-bucket" nilObject := "dummy-object" - nilReq, err := newTestSignedRequestV4("GET", getGetObjectURL("", nilBucket, nilObject), + nilReq, err := newTestSignedRequestV4(http.MethodGet, getGetObjectURL("", nilBucket, nilObject), 0, nil, "", "", nil) if err != nil { @@ -1080,18 +1080,18 @@ func testAPIPutObjectStreamSigV4Handler(obj ObjectLayer, instanceType, bucketNam // construct HTTP request for Put Object end point. var req *http.Request if testCase.fault == chunkDateMismatch { - req, err = newTestStreamingSignedBadChunkDateRequest("PUT", + req, err = newTestStreamingSignedBadChunkDateRequest(http.MethodPut, getPutObjectURL("", testCase.bucketName, testCase.objectName), int64(testCase.dataLen), testCase.chunkSize, bytes.NewReader(testCase.data), testCase.accessKey, testCase.secretKey) } else if testCase.contentEncoding == "" { - req, err = newTestStreamingSignedRequest("PUT", + req, err = newTestStreamingSignedRequest(http.MethodPut, getPutObjectURL("", testCase.bucketName, testCase.objectName), int64(testCase.dataLen), testCase.chunkSize, bytes.NewReader(testCase.data), testCase.accessKey, testCase.secretKey) } else if testCase.contentEncoding != "" { - req, err = newTestStreamingSignedCustomEncodingRequest("PUT", + req, err = newTestStreamingSignedCustomEncodingRequest(http.MethodPut, getPutObjectURL("", testCase.bucketName, testCase.objectName), int64(testCase.dataLen), testCase.chunkSize, bytes.NewReader(testCase.data), testCase.accessKey, testCase.secretKey, testCase.contentEncoding) @@ -1296,7 +1296,7 @@ func testAPIPutObjectHandler(obj ObjectLayer, instanceType, bucketName string, a // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. rec := httptest.NewRecorder() // construct HTTP request for Get Object end point. - req, err = newTestSignedRequestV4("PUT", getPutObjectURL("", testCase.bucketName, testCase.objectName), + req, err = newTestSignedRequestV4(http.MethodPut, getPutObjectURL("", testCase.bucketName, testCase.objectName), int64(testCase.dataLen), bytes.NewReader(testCase.data), testCase.accessKey, testCase.secretKey, nil) if err != nil { t.Fatalf("Test %d: Failed to create HTTP request for Put Object: %v", i+1, err) @@ -1337,7 +1337,7 @@ func testAPIPutObjectHandler(obj ObjectLayer, instanceType, bucketName string, a // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. recV2 := httptest.NewRecorder() // construct HTTP request for PUT Object endpoint. - reqV2, err = newTestSignedRequestV2("PUT", getPutObjectURL("", testCase.bucketName, testCase.objectName), + reqV2, err = newTestSignedRequestV2(http.MethodPut, getPutObjectURL("", testCase.bucketName, testCase.objectName), int64(testCase.dataLen), bytes.NewReader(testCase.data), testCase.accessKey, testCase.secretKey, nil) if err != nil { @@ -1378,7 +1378,7 @@ func testAPIPutObjectHandler(obj ObjectLayer, instanceType, bucketName string, a } // Test for Anonymous/unsigned http request. - anonReq, err := newTestRequest("PUT", getPutObjectURL("", bucketName, objectName), + anonReq, err := newTestRequest(http.MethodPut, getPutObjectURL("", bucketName, objectName), int64(len("hello")), bytes.NewReader([]byte("hello"))) if err != nil { t.Fatalf("MinIO %s: Failed to create an anonymous request for %s/%s: %v", @@ -1397,7 +1397,7 @@ func testAPIPutObjectHandler(obj ObjectLayer, instanceType, bucketName string, a nilBucket := "dummy-bucket" nilObject := "dummy-object" - nilReq, err := newTestSignedRequestV4("PUT", getPutObjectURL("", nilBucket, nilObject), + nilReq, err := newTestSignedRequestV4(http.MethodPut, getPutObjectURL("", nilBucket, nilObject), 0, nil, "", "", nil) if err != nil { @@ -1476,7 +1476,7 @@ func testAPICopyObjectPartHandlerSanity(obj ObjectLayer, instanceType, bucketNam // construct HTTP request for copy object. var req *http.Request - req, err = newTestSignedRequestV4("PUT", cpPartURL, 0, nil, credentials.AccessKey, credentials.SecretKey, nil) + req, err = newTestSignedRequestV4(http.MethodPut, cpPartURL, 0, nil, credentials.AccessKey, credentials.SecretKey, nil) if err != nil { t.Fatalf("Test failed to create HTTP request for copy object part: %v", err) } @@ -1775,11 +1775,11 @@ func testAPICopyObjectPartHandler(obj ObjectLayer, instanceType, bucketName stri rec := httptest.NewRecorder() if !testCase.invalidPartNumber || !testCase.maximumPartNumber { // construct HTTP request for copy object. - req, err = newTestSignedRequestV4("PUT", getCopyObjectPartURL("", testCase.bucketName, testObject, testCase.uploadID, "1"), 0, nil, testCase.accessKey, testCase.secretKey, nil) + req, err = newTestSignedRequestV4(http.MethodPut, getCopyObjectPartURL("", testCase.bucketName, testObject, testCase.uploadID, "1"), 0, nil, testCase.accessKey, testCase.secretKey, nil) } else if testCase.invalidPartNumber { - req, err = newTestSignedRequestV4("PUT", getCopyObjectPartURL("", testCase.bucketName, testObject, testCase.uploadID, "abc"), 0, nil, testCase.accessKey, testCase.secretKey, nil) + req, err = newTestSignedRequestV4(http.MethodPut, getCopyObjectPartURL("", testCase.bucketName, testObject, testCase.uploadID, "abc"), 0, nil, testCase.accessKey, testCase.secretKey, nil) } else if testCase.maximumPartNumber { - req, err = newTestSignedRequestV4("PUT", getCopyObjectPartURL("", testCase.bucketName, testObject, testCase.uploadID, "99999"), 0, nil, testCase.accessKey, testCase.secretKey, nil) + req, err = newTestSignedRequestV4(http.MethodPut, getCopyObjectPartURL("", testCase.bucketName, testObject, testCase.uploadID, "99999"), 0, nil, testCase.accessKey, testCase.secretKey, nil) } if err != nil { t.Fatalf("Test %d: Failed to create HTTP request for copy Object: %v", i+1, err) @@ -1821,14 +1821,14 @@ func testAPICopyObjectPartHandler(obj ObjectLayer, instanceType, bucketName stri nilBucket := "dummy-bucket" nilObject := "dummy-object" - nilReq, err := newTestSignedRequestV4("PUT", getCopyObjectPartURL("", nilBucket, nilObject, "0", "0"), + nilReq, err := newTestSignedRequestV4(http.MethodPut, getCopyObjectPartURL("", nilBucket, nilObject, "0", "0"), 0, bytes.NewReader([]byte("testNilObjLayer")), "", "", nil) if err != nil { t.Errorf("MinIO %s: Failed to create http request for testing the response when object Layer is set to `nil`.", instanceType) } // Below is how CopyObjectPartHandler is registered. - // bucket.Methods("PUT").Path("/{object:.+}").HeadersRegexp("X-Amz-Copy-Source", ".*?(\\/|%2F).*?").HandlerFunc(api.CopyObjectPartHandler).Queries("partNumber", "{partNumber:[0-9]+}", "uploadId", "{uploadId:.*}") + // bucket.Methods(http.MethodPut).Path("/{object:.+}").HeadersRegexp("X-Amz-Copy-Source", ".*?(\\/|%2F).*?").HandlerFunc(api.CopyObjectPartHandler).Queries("partNumber", "{partNumber:[0-9]+}", "uploadId", "{uploadId:.*}") // Its necessary to set the "X-Amz-Copy-Source" header for the request to be accepted by the handler. nilReq.Header.Set("X-Amz-Copy-Source", url.QueryEscape(SlashSeparator+nilBucket+SlashSeparator+nilObject)) @@ -2145,7 +2145,7 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. rec := httptest.NewRecorder() // construct HTTP request for copy object. - req, err = newTestSignedRequestV4("PUT", getCopyObjectURL("", testCase.bucketName, testCase.newObjectName), + req, err = newTestSignedRequestV4(http.MethodPut, getCopyObjectURL("", testCase.bucketName, testCase.newObjectName), 0, nil, testCase.accessKey, testCase.secretKey, nil) if err != nil { @@ -2203,7 +2203,7 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. recV2 := httptest.NewRecorder() - reqV2, err = newTestRequest("PUT", getCopyObjectURL("", testCase.bucketName, testCase.newObjectName), 0, nil) + reqV2, err = newTestRequest(http.MethodPut, getCopyObjectURL("", testCase.bucketName, testCase.newObjectName), 0, nil) if err != nil { t.Fatalf("Test %d: Failed to create HTTP request for copy Object: %v", i+1, err) } @@ -2252,11 +2252,11 @@ func testAPICopyObjectHandler(obj ObjectLayer, instanceType, bucketName string, nilBucket := "dummy-bucket" nilObject := "dummy-object" - nilReq, err := newTestSignedRequestV4("PUT", getCopyObjectURL("", nilBucket, nilObject), + nilReq, err := newTestSignedRequestV4(http.MethodPut, getCopyObjectURL("", nilBucket, nilObject), 0, nil, "", "", nil) // Below is how CopyObjectHandler is registered. - // bucket.Methods("PUT").Path("/{object:.+}").HeadersRegexp("X-Amz-Copy-Source", ".*?(\\/|%2F).*?") + // bucket.Methods(http.MethodPut).Path("/{object:.+}").HeadersRegexp("X-Amz-Copy-Source", ".*?(\\/|%2F).*?") // Its necessary to set the "X-Amz-Copy-Source" header for the request to be accepted by the handler. nilReq.Header.Set("X-Amz-Copy-Source", url.QueryEscape(SlashSeparator+nilBucket+SlashSeparator+nilObject)) if err != nil { @@ -2283,7 +2283,7 @@ func testAPINewMultipartHandler(obj ObjectLayer, instanceType, bucketName string objectName := "test-object-new-multipart" rec := httptest.NewRecorder() // construct HTTP request for NewMultipart upload. - req, err := newTestSignedRequestV4("POST", getNewMultipartURL("", bucketName, objectName), + req, err := newTestSignedRequestV4(http.MethodPost, getNewMultipartURL("", bucketName, objectName), 0, nil, credentials.AccessKey, credentials.SecretKey, nil) if err != nil { @@ -2316,7 +2316,7 @@ func testAPINewMultipartHandler(obj ObjectLayer, instanceType, bucketName string rec = httptest.NewRecorder() // construct HTTP request for NewMultipart upload. // Setting an invalid accessID. - req, err = newTestSignedRequestV4("POST", getNewMultipartURL("", bucketName, objectName), + req, err = newTestSignedRequestV4(http.MethodPost, getNewMultipartURL("", bucketName, objectName), 0, nil, "Invalid-AccessID", credentials.SecretKey, nil) if err != nil { @@ -2335,7 +2335,7 @@ func testAPINewMultipartHandler(obj ObjectLayer, instanceType, bucketName string // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. recV2 := httptest.NewRecorder() // construct HTTP request for NewMultipartUpload endpoint. - reqV2, err := newTestSignedRequestV2("POST", getNewMultipartURL("", bucketName, objectName), + reqV2, err := newTestSignedRequestV2(http.MethodPost, getNewMultipartURL("", bucketName, objectName), 0, nil, credentials.AccessKey, credentials.SecretKey, nil) if err != nil { @@ -2368,7 +2368,7 @@ func testAPINewMultipartHandler(obj ObjectLayer, instanceType, bucketName string recV2 = httptest.NewRecorder() // construct HTTP request for NewMultipartUpload endpoint. // Setting invalid AccessID. - reqV2, err = newTestSignedRequestV2("POST", getNewMultipartURL("", bucketName, objectName), + reqV2, err = newTestSignedRequestV2(http.MethodPost, getNewMultipartURL("", bucketName, objectName), 0, nil, "Invalid-AccessID", credentials.SecretKey, nil) if err != nil { @@ -2384,7 +2384,7 @@ func testAPINewMultipartHandler(obj ObjectLayer, instanceType, bucketName string } // Test for Anonymous/unsigned http request. - anonReq, err := newTestRequest("POST", getNewMultipartURL("", bucketName, objectName), 0, nil) + anonReq, err := newTestRequest(http.MethodPost, getNewMultipartURL("", bucketName, objectName), 0, nil) if err != nil { t.Fatalf("MinIO %s: Failed to create an anonymous request for %s/%s: %v", @@ -2403,7 +2403,7 @@ func testAPINewMultipartHandler(obj ObjectLayer, instanceType, bucketName string nilBucket := "dummy-bucket" nilObject := "dummy-object" - nilReq, err := newTestSignedRequestV4("POST", getNewMultipartURL("", nilBucket, nilObject), + nilReq, err := newTestSignedRequestV4(http.MethodPost, getNewMultipartURL("", nilBucket, nilObject), 0, nil, "", "", nil) if err != nil { @@ -2440,7 +2440,7 @@ func testAPINewMultipartHandlerParallel(obj ObjectLayer, instanceType, bucketNam defer wg.Done() rec := httptest.NewRecorder() // construct HTTP request NewMultipartUpload. - req, err := newTestSignedRequestV4("POST", getNewMultipartURL("", bucketName, objectName), 0, nil, credentials.AccessKey, credentials.SecretKey, nil) + req, err := newTestSignedRequestV4(http.MethodPost, getNewMultipartURL("", bucketName, objectName), 0, nil, credentials.AccessKey, credentials.SecretKey, nil) if err != nil { t.Errorf("Failed to create HTTP request for NewMultipart request: %v", err) @@ -2763,7 +2763,7 @@ func testAPICompleteMultipartHandler(obj ObjectLayer, instanceType, bucketName s t.Fatalf("Error XML encoding of parts: %s.", err) } // Indicating that all parts are uploaded and initiating CompleteMultipartUpload. - req, err = newTestSignedRequestV4("POST", getCompleteMultipartUploadURL("", bucketName, objectName, testCase.uploadID), + req, err = newTestSignedRequestV4(http.MethodPost, getCompleteMultipartUploadURL("", bucketName, objectName, testCase.uploadID), int64(len(completeBytes)), bytes.NewReader(completeBytes), testCase.accessKey, testCase.secretKey, nil) if err != nil { t.Fatalf("Failed to create HTTP request for CompleteMultipartUpload: %v", err) @@ -2819,7 +2819,7 @@ func testAPICompleteMultipartHandler(obj ObjectLayer, instanceType, bucketName s } // create unsigned HTTP request for CompleteMultipart upload. - anonReq, err := newTestRequest("POST", getCompleteMultipartUploadURL("", bucketName, objectName, uploadIDs[1]), + anonReq, err := newTestRequest(http.MethodPost, getCompleteMultipartUploadURL("", bucketName, objectName, uploadIDs[1]), int64(len(completeBytes)), bytes.NewReader(completeBytes)) if err != nil { t.Fatalf("MinIO %s: Failed to create an anonymous request for %s/%s: %v", @@ -2840,7 +2840,7 @@ func testAPICompleteMultipartHandler(obj ObjectLayer, instanceType, bucketName s nilBucket := "dummy-bucket" nilObject := "dummy-object" - nilReq, err := newTestSignedRequestV4("POST", getCompleteMultipartUploadURL("", nilBucket, nilObject, "dummy-uploadID"), + nilReq, err := newTestSignedRequestV4(http.MethodPost, getCompleteMultipartUploadURL("", nilBucket, nilObject, "dummy-uploadID"), 0, nil, "", "", nil) if err != nil { @@ -2964,7 +2964,7 @@ func testAPIAbortMultipartHandler(obj ObjectLayer, instanceType, bucketName stri for i, testCase := range testCases { var req *http.Request // Indicating that all parts are uploaded and initiating abortMultipartUpload. - req, err = newTestSignedRequestV4("DELETE", getAbortMultipartUploadURL("", testCase.bucket, testCase.object, testCase.uploadID), + req, err = newTestSignedRequestV4(http.MethodDelete, getAbortMultipartUploadURL("", testCase.bucket, testCase.object, testCase.uploadID), 0, nil, testCase.accessKey, testCase.secretKey, nil) if err != nil { t.Fatalf("Failed to create HTTP request for AbortMultipartUpload: %v", err) @@ -2982,7 +2982,7 @@ func testAPIAbortMultipartHandler(obj ObjectLayer, instanceType, bucketName stri } // create unsigned HTTP request for Abort multipart upload. - anonReq, err := newTestRequest("DELETE", getAbortMultipartUploadURL("", bucketName, objectName, uploadIDs[1]), + anonReq, err := newTestRequest(http.MethodDelete, getAbortMultipartUploadURL("", bucketName, objectName, uploadIDs[1]), 0, nil) if err != nil { t.Fatalf("MinIO %s: Failed to create an anonymous request for %s/%s: %v", @@ -3003,7 +3003,7 @@ func testAPIAbortMultipartHandler(obj ObjectLayer, instanceType, bucketName stri nilBucket := "dummy-bucket" nilObject := "dummy-object" - nilReq, err := newTestSignedRequestV4("DELETE", getAbortMultipartUploadURL("", nilBucket, nilObject, "dummy-uploadID"), + nilReq, err := newTestSignedRequestV4(http.MethodDelete, getAbortMultipartUploadURL("", nilBucket, nilObject, "dummy-uploadID"), 0, nil, "", "", nil) if err != nil { @@ -3108,7 +3108,7 @@ func testAPIDeleteObjectHandler(obj ObjectLayer, instanceType, bucketName string // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. rec := httptest.NewRecorder() // construct HTTP request for Delete Object end point. - req, err = newTestSignedRequestV4("DELETE", getDeleteObjectURL("", testCase.bucketName, testCase.objectName), + req, err = newTestSignedRequestV4(http.MethodDelete, getDeleteObjectURL("", testCase.bucketName, testCase.objectName), 0, nil, testCase.accessKey, testCase.secretKey, nil) if err != nil { @@ -3126,7 +3126,7 @@ func testAPIDeleteObjectHandler(obj ObjectLayer, instanceType, bucketName string // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. recV2 := httptest.NewRecorder() // construct HTTP request for Delete Object endpoint. - reqV2, err = newTestSignedRequestV2("DELETE", getDeleteObjectURL("", testCase.bucketName, testCase.objectName), + reqV2, err = newTestSignedRequestV2(http.MethodDelete, getDeleteObjectURL("", testCase.bucketName, testCase.objectName), 0, nil, testCase.accessKey, testCase.secretKey, nil) if err != nil { @@ -3145,7 +3145,7 @@ func testAPIDeleteObjectHandler(obj ObjectLayer, instanceType, bucketName string } // Test for Anonymous/unsigned http request. - anonReq, err := newTestRequest("DELETE", getDeleteObjectURL("", bucketName, anonObjectName), 0, nil) + anonReq, err := newTestRequest(http.MethodDelete, getDeleteObjectURL("", bucketName, anonObjectName), 0, nil) if err != nil { t.Fatalf("MinIO %s: Failed to create an anonymous request for %s/%s: %v", instanceType, bucketName, anonObjectName, err) @@ -3163,7 +3163,7 @@ func testAPIDeleteObjectHandler(obj ObjectLayer, instanceType, bucketName string nilBucket := "dummy-bucket" nilObject := "dummy-object" - nilReq, err := newTestSignedRequestV4("DELETE", getDeleteObjectURL("", nilBucket, nilObject), + nilReq, err := newTestSignedRequestV4(http.MethodDelete, getDeleteObjectURL("", nilBucket, nilObject), 0, nil, "", "", nil) if err != nil { @@ -3185,7 +3185,7 @@ func testAPIPutObjectPartHandlerStreaming(obj ObjectLayer, instanceType, bucketN credentials auth.Credentials, t *testing.T) { testObject := "testobject" rec := httptest.NewRecorder() - req, err := newTestSignedRequestV4("POST", getNewMultipartURL("", bucketName, "testobject"), + req, err := newTestSignedRequestV4(http.MethodPost, getNewMultipartURL("", bucketName, "testobject"), 0, nil, credentials.AccessKey, credentials.SecretKey, nil) if err != nil { t.Fatalf("[%s] - Failed to create a signed request to initiate multipart upload for %s/%s: %v", @@ -3219,7 +3219,7 @@ func testAPIPutObjectPartHandlerStreaming(obj ObjectLayer, instanceType, bucketN for i, test := range testCases { rec = httptest.NewRecorder() - req, err = newTestStreamingSignedRequest("PUT", + req, err = newTestStreamingSignedRequest(http.MethodPut, getPutObjectPartURL("", bucketName, testObject, mpartResp.UploadID, "1"), 5, 1, bytes.NewReader([]byte("hello")), credentials.AccessKey, credentials.SecretKey) @@ -3455,7 +3455,7 @@ func testAPIPutObjectPartHandler(obj ObjectLayer, instanceType, bucketName strin uploadID = "upload1" } // constructing a v4 signed HTTP request. - reqV4, err = newTestSignedRequestV4("PUT", + reqV4, err = newTestSignedRequestV4(http.MethodPut, getPutObjectPartURL("", bucketName, test.objectName, uploadID, test.partNumber), 0, test.reader, test.accessKey, test.secretKey, nil) if err != nil { @@ -3464,7 +3464,7 @@ func testAPIPutObjectPartHandler(obj ObjectLayer, instanceType, bucketName strin } // Verify response of the V2 signed HTTP request. // construct HTTP request for PutObject Part Object endpoint. - reqV2, err = newTestSignedRequestV2("PUT", + reqV2, err = newTestSignedRequestV2(http.MethodPut, getPutObjectPartURL("", bucketName, test.objectName, uploadID, test.partNumber), 0, test.reader, test.accessKey, test.secretKey, nil) @@ -3548,7 +3548,7 @@ func testAPIPutObjectPartHandler(obj ObjectLayer, instanceType, bucketName strin } // Test for Anonymous/unsigned http request. - anonReq, err := newTestRequest("PUT", getPutObjectPartURL("", bucketName, testObject, uploadIDCopy, "1"), + anonReq, err := newTestRequest(http.MethodPut, getPutObjectPartURL("", bucketName, testObject, uploadIDCopy, "1"), int64(len("hello")), bytes.NewReader([]byte("hello"))) if err != nil { t.Fatalf("MinIO %s: Failed to create an anonymous request for %s/%s: %v", @@ -3567,7 +3567,7 @@ func testAPIPutObjectPartHandler(obj ObjectLayer, instanceType, bucketName strin nilBucket := "dummy-bucket" nilObject := "dummy-object" - nilReq, err := newTestSignedRequestV4("PUT", getPutObjectPartURL("", nilBucket, nilObject, "0", "0"), + nilReq, err := newTestSignedRequestV4(http.MethodPut, getPutObjectPartURL("", nilBucket, nilObject, "0", "0"), 0, bytes.NewReader([]byte("testNilObjLayer")), "", "", nil) if err != nil { @@ -3590,7 +3590,7 @@ func testAPIListObjectPartsHandlerPreSign(obj ObjectLayer, instanceType, bucketN credentials auth.Credentials, t *testing.T) { testObject := "testobject" rec := httptest.NewRecorder() - req, err := newTestSignedRequestV4("POST", getNewMultipartURL("", bucketName, testObject), + req, err := newTestSignedRequestV4(http.MethodPost, getNewMultipartURL("", bucketName, testObject), 0, nil, credentials.AccessKey, credentials.SecretKey, nil) if err != nil { t.Fatalf("[%s] - Failed to create a signed request to initiate multipart upload for %s/%s: %v", @@ -3612,7 +3612,7 @@ func testAPIListObjectPartsHandlerPreSign(obj ObjectLayer, instanceType, bucketN // Upload a part for listing purposes. rec = httptest.NewRecorder() - req, err = newTestSignedRequestV4("PUT", + req, err = newTestSignedRequestV4(http.MethodPut, getPutObjectPartURL("", bucketName, testObject, mpartResp.UploadID, "1"), int64(len("hello")), bytes.NewReader([]byte("hello")), credentials.AccessKey, credentials.SecretKey, nil) if err != nil { @@ -3626,7 +3626,7 @@ func testAPIListObjectPartsHandlerPreSign(obj ObjectLayer, instanceType, bucketN instanceType, bucketName, testObject, rec.Code) } rec = httptest.NewRecorder() - req, err = newTestRequest("GET", + req, err = newTestRequest(http.MethodGet, getListMultipartURLWithParams("", bucketName, testObject, mpartResp.UploadID, "", "", ""), 0, nil) if err != nil { @@ -3647,7 +3647,7 @@ func testAPIListObjectPartsHandlerPreSign(obj ObjectLayer, instanceType, bucketN } rec = httptest.NewRecorder() - req, err = newTestRequest("GET", + req, err = newTestRequest(http.MethodGet, getListMultipartURLWithParams("", bucketName, testObject, mpartResp.UploadID, "", "", ""), 0, nil) if err != nil { @@ -3772,7 +3772,7 @@ func testAPIListObjectPartsHandler(obj ObjectLayer, instanceType, bucketName str } // constructing a v4 signed HTTP request for ListMultipartUploads. - reqV4, err = newTestSignedRequestV4("GET", + reqV4, err = newTestSignedRequestV4(http.MethodGet, getListMultipartURLWithParams("", bucketName, testObject, uploadID, test.maxParts, test.partNumberMarker, ""), 0, nil, credentials.AccessKey, credentials.SecretKey, nil) @@ -3782,7 +3782,7 @@ func testAPIListObjectPartsHandler(obj ObjectLayer, instanceType, bucketName str } // Verify response of the V2 signed HTTP request. // construct HTTP request for PutObject Part Object endpoint. - reqV2, err = newTestSignedRequestV2("GET", + reqV2, err = newTestSignedRequestV2(http.MethodGet, getListMultipartURLWithParams("", bucketName, testObject, uploadID, test.maxParts, test.partNumberMarker, ""), 0, nil, credentials.AccessKey, credentials.SecretKey, nil) @@ -3851,7 +3851,7 @@ func testAPIListObjectPartsHandler(obj ObjectLayer, instanceType, bucketName str } // Test for Anonymous/unsigned http request. - anonReq, err := newTestRequest("GET", + anonReq, err := newTestRequest(http.MethodGet, getListMultipartURLWithParams("", bucketName, testObject, uploadIDCopy, "", "", ""), 0, nil) if err != nil { t.Fatalf("MinIO %s: Failed to create an anonymous request for %s/%s: %v", @@ -3870,7 +3870,7 @@ func testAPIListObjectPartsHandler(obj ObjectLayer, instanceType, bucketName str nilBucket := "dummy-bucket" nilObject := "dummy-object" - nilReq, err := newTestSignedRequestV4("GET", + nilReq, err := newTestSignedRequestV4(http.MethodGet, getListMultipartURLWithParams("", nilBucket, nilObject, "dummy-uploadID", "0", "0", ""), 0, nil, "", "", nil) if err != nil { diff --git a/cmd/peer-rest-server.go b/cmd/peer-rest-server.go index 625cfc4b5..563078ac5 100644 --- a/cmd/peer-rest-server.go +++ b/cmd/peer-rest-server.go @@ -897,8 +897,10 @@ func (s *peerRESTServer) ListenHandler(w http.ResponseWriter, r *http.Request) { if !ok { return false } - if ev.S3.Bucket.Name != values.Get(peerRESTListenBucket) { - return false + if ev.S3.Bucket.Name != "" && values.Get(peerRESTListenBucket) != "" { + if ev.S3.Bucket.Name != values.Get(peerRESTListenBucket) { + return false + } } return rulesMap.MatchSimple(ev.EventName, ev.S3.Object.Key) }) diff --git a/cmd/post-policy_test.go b/cmd/post-policy_test.go index 08baaffb4..9a37c86c3 100644 --- a/cmd/post-policy_test.go +++ b/cmd/post-policy_test.go @@ -548,7 +548,7 @@ func newPostRequestV2(endPoint, bucketName, objectName string, accessKey, secret // Set the body equal to the created policy. reader := bytes.NewReader(buf.Bytes()) - req, err := http.NewRequest("POST", makeTestTargetURL(endPoint, bucketName, "", nil), reader) + req, err := http.NewRequest(http.MethodPost, makeTestTargetURL(endPoint, bucketName, "", nil), reader) if err != nil { return nil, err } @@ -626,7 +626,7 @@ func newPostRequestV4Generic(endPoint, bucketName, objectName string, objData [] // Set the body equal to the created policy. reader := bytes.NewReader(buf.Bytes()) - req, err := http.NewRequest("POST", makeTestTargetURL(endPoint, bucketName, "", nil), reader) + req, err := http.NewRequest(http.MethodPost, makeTestTargetURL(endPoint, bucketName, "", nil), reader) if err != nil { return nil, err } diff --git a/cmd/server_test.go b/cmd/server_test.go index 8cf86e7e8..0507a1f08 100644 --- a/cmd/server_test.go +++ b/cmd/server_test.go @@ -165,7 +165,7 @@ func (s *TestSuiteCommon) TestBucketSQSNotificationWebHook(c *check) { // generate a random bucket Name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -176,7 +176,7 @@ func (s *TestSuiteCommon) TestBucketSQSNotificationWebHook(c *check) { // assert the http response status code. c.Assert(response.StatusCode, http.StatusOK) - request, err = newTestSignedRequest("PUT", getPutNotificationURL(s.endPoint, bucketName), + request, err = newTestSignedRequest(http.MethodPut, getPutNotificationURL(s.endPoint, bucketName), int64(len(bucketNotificationBuf)), bytes.NewReader([]byte(bucketNotificationBuf)), s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -190,7 +190,7 @@ func (s *TestSuiteCommon) TestBucketSQSNotificationWebHook(c *check) { func (s *TestSuiteCommon) TestObjectDir(c *check) { bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -201,7 +201,7 @@ func (s *TestSuiteCommon) TestObjectDir(c *check) { // assert the http response status code. c.Assert(response.StatusCode, http.StatusOK) - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, "my-object-directory/"), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, "my-object-directory/"), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -212,7 +212,7 @@ func (s *TestSuiteCommon) TestObjectDir(c *check) { // assert the http response status code. c.Assert(response.StatusCode, http.StatusOK) - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, "my-object-directory/"), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, "my-object-directory/"), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -226,7 +226,7 @@ func (s *TestSuiteCommon) TestObjectDir(c *check) { c.Assert(err, nil) verifyError(c, response, "XMinioInvalidObjectName", "Object name contains unsupported characters.", http.StatusBadRequest) - request, err = newTestSignedRequest("HEAD", getHeadObjectURL(s.endPoint, bucketName, "my-object-directory/"), + request, err = newTestSignedRequest(http.MethodHead, getHeadObjectURL(s.endPoint, bucketName, "my-object-directory/"), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -236,7 +236,7 @@ func (s *TestSuiteCommon) TestObjectDir(c *check) { c.Assert(err, nil) c.Assert(response.StatusCode, http.StatusOK) - request, err = newTestSignedRequest("GET", getGetObjectURL(s.endPoint, bucketName, "my-object-directory/"), + request, err = newTestSignedRequest(http.MethodGet, getGetObjectURL(s.endPoint, bucketName, "my-object-directory/"), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -246,7 +246,7 @@ func (s *TestSuiteCommon) TestObjectDir(c *check) { c.Assert(err, nil) c.Assert(response.StatusCode, http.StatusOK) - request, err = newTestSignedRequest("DELETE", getDeleteObjectURL(s.endPoint, bucketName, "my-object-directory/"), + request, err = newTestSignedRequest(http.MethodDelete, getDeleteObjectURL(s.endPoint, bucketName, "my-object-directory/"), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -263,7 +263,7 @@ func (s *TestSuiteCommon) TestBucketSQSNotificationAMQP(c *check) { // generate a random bucket Name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -274,7 +274,7 @@ func (s *TestSuiteCommon) TestBucketSQSNotificationAMQP(c *check) { // assert the http response status code. c.Assert(response.StatusCode, http.StatusOK) - request, err = newTestSignedRequest("PUT", getPutNotificationURL(s.endPoint, bucketName), + request, err = newTestSignedRequest(http.MethodPut, getPutNotificationURL(s.endPoint, bucketName), int64(len(bucketNotificationBuf)), bytes.NewReader([]byte(bucketNotificationBuf)), s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -296,7 +296,7 @@ func (s *TestSuiteCommon) TestBucketPolicy(c *check) { // create the policy statement string with the randomly generated bucket name. bucketPolicyStr := fmt.Sprintf(bucketPolicyBuf, bucketName, bucketName) // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -307,7 +307,7 @@ func (s *TestSuiteCommon) TestBucketPolicy(c *check) { c.Assert(response.StatusCode, http.StatusOK) /// Put a new bucket policy. - request, err = newTestSignedRequest("PUT", getPutPolicyURL(s.endPoint, bucketName), + request, err = newTestSignedRequest(http.MethodPut, getPutPolicyURL(s.endPoint, bucketName), int64(len(bucketPolicyStr)), bytes.NewReader([]byte(bucketPolicyStr)), s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -317,7 +317,7 @@ func (s *TestSuiteCommon) TestBucketPolicy(c *check) { c.Assert(response.StatusCode, http.StatusNoContent) // Fetch the uploaded policy. - request, err = newTestSignedRequest("GET", getGetPolicyURL(s.endPoint, bucketName), 0, nil, + request, err = newTestSignedRequest(http.MethodGet, getGetPolicyURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -335,7 +335,7 @@ func (s *TestSuiteCommon) TestBucketPolicy(c *check) { c.Assert(reflect.DeepEqual(expectedPolicy, gotPolicy), true) // Delete policy. - request, err = newTestSignedRequest("DELETE", getDeletePolicyURL(s.endPoint, bucketName), 0, nil, + request, err = newTestSignedRequest(http.MethodDelete, getDeletePolicyURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -344,7 +344,7 @@ func (s *TestSuiteCommon) TestBucketPolicy(c *check) { c.Assert(response.StatusCode, http.StatusNoContent) // Verify if the policy was indeed deleted. - request, err = newTestSignedRequest("GET", getGetPolicyURL(s.endPoint, bucketName), + request, err = newTestSignedRequest(http.MethodGet, getGetPolicyURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -358,7 +358,7 @@ func (s *TestSuiteCommon) TestDeleteBucket(c *check) { bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -368,7 +368,7 @@ func (s *TestSuiteCommon) TestDeleteBucket(c *check) { c.Assert(response.StatusCode, http.StatusOK) // construct request to delete the bucket. - request, err = newTestSignedRequest("DELETE", getDeleteBucketURL(s.endPoint, bucketName), + request, err = newTestSignedRequest(http.MethodDelete, getDeleteBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -384,7 +384,7 @@ func (s *TestSuiteCommon) TestDeleteBucketNotEmpty(c *check) { bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -397,7 +397,7 @@ func (s *TestSuiteCommon) TestDeleteBucketNotEmpty(c *check) { // generate http request for an object upload. // "test-object" is the object name. objectName := "test-object" - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -410,7 +410,7 @@ func (s *TestSuiteCommon) TestDeleteBucketNotEmpty(c *check) { // constructing http request to delete the bucket. // making an attempt to delete an non-empty bucket. // expected to fail. - request, err = newTestSignedRequest("DELETE", getDeleteBucketURL(s.endPoint, bucketName), + request, err = newTestSignedRequest(http.MethodDelete, getDeleteBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -420,11 +420,11 @@ func (s *TestSuiteCommon) TestDeleteBucketNotEmpty(c *check) { } -func (s *TestSuiteCommon) TestListenBucketNotificationHandler(c *check) { +func (s *TestSuiteCommon) TestListenNotificationHandler(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - req, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + req, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -440,8 +440,8 @@ func (s *TestSuiteCommon) TestListenBucketNotificationHandler(c *check) { validEvents := []string{"s3:ObjectCreated:*", "s3:ObjectRemoved:*"} invalidEvents := []string{"invalidEvent"} - req, err = newTestSignedRequest("GET", - getListenBucketNotificationURL(s.endPoint, invalidBucket, []string{}, []string{}, []string{}), + req, err = newTestSignedRequest(http.MethodGet, + getListenNotificationURL(s.endPoint, invalidBucket, []string{}, []string{}, []string{}), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -450,8 +450,8 @@ func (s *TestSuiteCommon) TestListenBucketNotificationHandler(c *check) { c.Assert(err, nil) verifyError(c, response, "InvalidBucketName", "The specified bucket is not valid.", http.StatusBadRequest) - req, err = newTestSignedRequest("GET", - getListenBucketNotificationURL(s.endPoint, bucketName, []string{}, []string{}, invalidEvents), + req, err = newTestSignedRequest(http.MethodGet, + getListenNotificationURL(s.endPoint, bucketName, []string{}, []string{}, invalidEvents), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -460,8 +460,8 @@ func (s *TestSuiteCommon) TestListenBucketNotificationHandler(c *check) { c.Assert(err, nil) verifyError(c, response, "InvalidArgument", "A specified event is not supported for notifications.", http.StatusBadRequest) - req, err = newTestSignedRequest("GET", - getListenBucketNotificationURL(s.endPoint, bucketName, []string{tooBigPrefix}, []string{}, validEvents), + req, err = newTestSignedRequest(http.MethodGet, + getListenNotificationURL(s.endPoint, bucketName, []string{tooBigPrefix}, []string{}, validEvents), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -470,8 +470,8 @@ func (s *TestSuiteCommon) TestListenBucketNotificationHandler(c *check) { c.Assert(err, nil) verifyError(c, response, "InvalidArgument", "Size of filter rule value cannot exceed 1024 bytes in UTF-8 representation", http.StatusBadRequest) - req, err = newTestSignedBadSHARequest("GET", - getListenBucketNotificationURL(s.endPoint, bucketName, []string{}, []string{}, validEvents), + req, err = newTestSignedBadSHARequest(http.MethodGet, + getListenNotificationURL(s.endPoint, bucketName, []string{}, []string{}, validEvents), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -488,7 +488,7 @@ func (s *TestSuiteCommon) TestDeleteMultipleObjects(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -506,7 +506,7 @@ func (s *TestSuiteCommon) TestDeleteMultipleObjects(c *check) { // Obtain http request to upload object. // object Name contains a prefix. objName := fmt.Sprintf("%d/%s", i, objectName) - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -525,7 +525,7 @@ func (s *TestSuiteCommon) TestDeleteMultipleObjects(c *check) { c.Assert(err, nil) // Delete list of objects. - request, err = newTestSignedRequest("POST", getMultiDeleteObjectURL(s.endPoint, bucketName), + request, err = newTestSignedRequest(http.MethodPost, getMultiDeleteObjectURL(s.endPoint, bucketName), int64(len(deleteReqBytes)), bytes.NewReader(deleteReqBytes), s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) response, err = s.client.Do(request) @@ -548,7 +548,7 @@ func (s *TestSuiteCommon) TestDeleteMultipleObjects(c *check) { // Attempt second time results should be same, NoSuchKey for objects not found // shouldn't be set. - request, err = newTestSignedRequest("POST", getMultiDeleteObjectURL(s.endPoint, bucketName), + request, err = newTestSignedRequest(http.MethodPost, getMultiDeleteObjectURL(s.endPoint, bucketName), int64(len(deleteReqBytes)), bytes.NewReader(deleteReqBytes), s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) response, err = s.client.Do(request) @@ -575,7 +575,7 @@ func (s *TestSuiteCommon) TestDeleteObject(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -588,7 +588,7 @@ func (s *TestSuiteCommon) TestDeleteObject(c *check) { objectName := "prefix/myobject" // obtain http request to upload object. // object Name contains a prefix. - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -600,7 +600,7 @@ func (s *TestSuiteCommon) TestDeleteObject(c *check) { // object name was "prefix/myobject", an attempt to delete "prefix" // Should not delete "prefix/myobject" - request, err = newTestSignedRequest("DELETE", getDeleteObjectURL(s.endPoint, bucketName, "prefix"), + request, err = newTestSignedRequest(http.MethodDelete, getDeleteObjectURL(s.endPoint, bucketName, "prefix"), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) response, err = s.client.Do(request) @@ -609,7 +609,7 @@ func (s *TestSuiteCommon) TestDeleteObject(c *check) { // create http request to HEAD on the object. // this helps to validate the existence of the bucket. - request, err = newTestSignedRequest("HEAD", getHeadObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodHead, getHeadObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -619,7 +619,7 @@ func (s *TestSuiteCommon) TestDeleteObject(c *check) { c.Assert(response.StatusCode, http.StatusOK) // create HTTP request to delete the object. - request, err = newTestSignedRequest("DELETE", getDeleteObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodDelete, getDeleteObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // execute the http request. @@ -629,7 +629,7 @@ func (s *TestSuiteCommon) TestDeleteObject(c *check) { c.Assert(response.StatusCode, http.StatusNoContent) // Delete of non-existent data should return success. - request, err = newTestSignedRequest("DELETE", getDeleteObjectURL(s.endPoint, bucketName, "prefix/myobject1"), + request, err = newTestSignedRequest(http.MethodDelete, getDeleteObjectURL(s.endPoint, bucketName, "prefix/myobject1"), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // execute the http request. @@ -645,7 +645,7 @@ func (s *TestSuiteCommon) TestNonExistentBucket(c *check) { bucketName := getRandomBucketName() // create request to HEAD on the bucket. // HEAD on an bucket helps validate the existence of the bucket. - request, err := newTestSignedRequest("HEAD", getHEADBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodHead, getHEADBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -661,7 +661,7 @@ func (s *TestSuiteCommon) TestEmptyObject(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -673,7 +673,7 @@ func (s *TestSuiteCommon) TestEmptyObject(c *check) { objectName := "test-object" // construct http request for uploading the object. - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -684,7 +684,7 @@ func (s *TestSuiteCommon) TestEmptyObject(c *check) { c.Assert(response.StatusCode, http.StatusOK) // make HTTP request to fetch the object. - request, err = newTestSignedRequest("GET", getGetObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodGet, getGetObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -706,7 +706,7 @@ func (s *TestSuiteCommon) TestBucket(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -714,7 +714,7 @@ func (s *TestSuiteCommon) TestBucket(c *check) { c.Assert(err, nil) c.Assert(response.StatusCode, http.StatusOK) - request, err = newTestSignedRequest("HEAD", getMakeBucketURL(s.endPoint, bucketName), + request, err = newTestSignedRequest(http.MethodHead, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -729,7 +729,7 @@ func (s *TestSuiteCommon) TestObjectGetAnonymous(c *check) { bucketName := getRandomBucketName() buffer := bytes.NewReader([]byte("hello world")) // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -741,7 +741,7 @@ func (s *TestSuiteCommon) TestObjectGetAnonymous(c *check) { objectName := "testObject" // create HTTP request to upload the object. - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objectName), int64(buffer.Len()), buffer, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -769,7 +769,7 @@ func (s *TestSuiteCommon) TestMultipleObjects(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -781,7 +781,7 @@ func (s *TestSuiteCommon) TestMultipleObjects(c *check) { // constructing HTTP request to fetch a non-existent object. // expected to fail, error response asserted for expected error values later. objectName := "testObject" - request, err = newTestSignedRequest("GET", getGetObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodGet, getGetObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -795,7 +795,7 @@ func (s *TestSuiteCommon) TestMultipleObjects(c *check) { // content for the object to be uploaded. buffer1 := bytes.NewReader([]byte("hello one")) // create HTTP request for the object upload. - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objectName), int64(buffer1.Len()), buffer1, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -806,7 +806,7 @@ func (s *TestSuiteCommon) TestMultipleObjects(c *check) { c.Assert(response.StatusCode, http.StatusOK) // create HTTP request to fetch the object which was uploaded above. - request, err = newTestSignedRequest("GET", getGetObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodGet, getGetObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -825,7 +825,7 @@ func (s *TestSuiteCommon) TestMultipleObjects(c *check) { // data for new object to be uploaded. buffer2 := bytes.NewReader([]byte("hello two")) objectName = "testObject2" - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objectName), int64(buffer2.Len()), buffer2, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -835,7 +835,7 @@ func (s *TestSuiteCommon) TestMultipleObjects(c *check) { // assert the response status code for expected value 200 OK. c.Assert(response.StatusCode, http.StatusOK) // fetch the object which was uploaded above. - request, err = newTestSignedRequest("GET", getGetObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodGet, getGetObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -853,7 +853,7 @@ func (s *TestSuiteCommon) TestMultipleObjects(c *check) { // data for new object to be uploaded. buffer3 := bytes.NewReader([]byte("hello three")) objectName = "testObject3" - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objectName), int64(buffer3.Len()), buffer3, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -864,7 +864,7 @@ func (s *TestSuiteCommon) TestMultipleObjects(c *check) { c.Assert(response.StatusCode, http.StatusOK) // fetch the object which was uploaded above. - request, err = newTestSignedRequest("GET", getPutObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodGet, getPutObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -883,7 +883,7 @@ func (s *TestSuiteCommon) TestHeader(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // obtain HTTP request to fetch an object from non-existent bucket/object. - request, err := newTestSignedRequest("GET", getGetObjectURL(s.endPoint, bucketName, "testObject"), + request, err := newTestSignedRequest(http.MethodGet, getGetObjectURL(s.endPoint, bucketName, "testObject"), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -906,7 +906,7 @@ func (s *TestSuiteCommon) TestPutBucket(c *check) { go func() { defer wg.Done() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -923,7 +923,7 @@ func (s *TestSuiteCommon) TestPutBucket(c *check) { bucketName = getRandomBucketName() //Block 2: testing for correctness of the functionality // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -943,7 +943,7 @@ func (s *TestSuiteCommon) TestCopyObject(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -956,7 +956,7 @@ func (s *TestSuiteCommon) TestCopyObject(c *check) { buffer1 := bytes.NewReader([]byte("hello world")) objectName := "testObject" // create HTTP request for object upload. - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objectName), int64(buffer1.Len()), buffer1, s.accessKey, s.secretKey, s.signer) request.Header.Set("Content-Type", "application/json") if s.signer == signerV2 { @@ -972,7 +972,7 @@ func (s *TestSuiteCommon) TestCopyObject(c *check) { objectName2 := "testObject2" // Unlike the actual PUT object request, the request to Copy Object doesn't contain request body, // empty body with the "X-Amz-Copy-Source" header pointing to the object to copies it in the backend. - request, err = newTestRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName2), 0, nil) + request, err = newTestRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objectName2), 0, nil) c.Assert(err, nil) // setting the "X-Amz-Copy-Source" to allow copying the content of previously uploaded object. request.Header.Set("X-Amz-Copy-Source", url.QueryEscape(SlashSeparator+bucketName+SlashSeparator+objectName)) @@ -989,7 +989,7 @@ func (s *TestSuiteCommon) TestCopyObject(c *check) { c.Assert(response.StatusCode, http.StatusOK) // creating HTTP request to fetch the previously uploaded object. - request, err = newTestSignedRequest("GET", getGetObjectURL(s.endPoint, bucketName, objectName2), + request, err = newTestSignedRequest(http.MethodGet, getGetObjectURL(s.endPoint, bucketName, objectName2), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // executing the HTTP request. @@ -1009,7 +1009,7 @@ func (s *TestSuiteCommon) TestPutObject(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1022,7 +1022,7 @@ func (s *TestSuiteCommon) TestPutObject(c *check) { buffer1 := bytes.NewReader([]byte("hello world")) objectName := "testObject" // creating HTTP request for object upload. - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objectName), int64(buffer1.Len()), buffer1, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // execute the HTTP request for object upload. @@ -1031,7 +1031,7 @@ func (s *TestSuiteCommon) TestPutObject(c *check) { c.Assert(response.StatusCode, http.StatusOK) // fetch the object back and verify its contents. - request, err = newTestSignedRequest("GET", getGetObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodGet, getGetObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // execute the HTTP request to fetch the object. @@ -1054,7 +1054,7 @@ func (s *TestSuiteCommon) TestPutObject(c *check) { // The response Etag headers should contain Md5Sum of empty string. objectName = "objectwith/" // create HTTP request for object upload. - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) if s.signer == signerV2 { c.Assert(err, nil) @@ -1076,7 +1076,7 @@ func (s *TestSuiteCommon) TestListBuckets(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // execute the HTTP request to list buckets. @@ -1085,7 +1085,7 @@ func (s *TestSuiteCommon) TestListBuckets(c *check) { c.Assert(response.StatusCode, http.StatusOK) // create HTTP request for listing buckets. - request, err = newTestSignedRequest("GET", getListBucketURL(s.endPoint), + request, err = newTestSignedRequest(http.MethodGet, getListBucketURL(s.endPoint), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1125,7 +1125,7 @@ func (s *TestSuiteCommon) TestValidateSignature(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1140,7 +1140,7 @@ func (s *TestSuiteCommon) TestValidateSignature(c *check) { // Create new HTTP request with incorrect secretKey to generate an incorrect signature. secretKey := s.secretKey + "a" - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objName), 0, nil, s.accessKey, secretKey, s.signer) + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objName), 0, nil, s.accessKey, secretKey, s.signer) c.Assert(err, nil) response, err = s.client.Do(request) c.Assert(err, nil) @@ -1152,7 +1152,7 @@ func (s *TestSuiteCommon) TestSHA256Mismatch(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1166,7 +1166,7 @@ func (s *TestSuiteCommon) TestSHA256Mismatch(c *check) { // Body is on purpose set to nil so that we get payload generated for empty bytes. // Create new HTTP request with incorrect secretKey to generate an incorrect signature. - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objName), 0, nil, s.accessKey, s.secretKey, s.signer) + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objName), 0, nil, s.accessKey, s.secretKey, s.signer) if s.signer == signerV4 { c.Assert(request.Header.Get("x-amz-content-sha256"), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855") } @@ -1190,7 +1190,7 @@ func (s *TestSuiteCommon) TestPutObjectLongName(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1206,7 +1206,7 @@ func (s *TestSuiteCommon) TestPutObjectLongName(c *check) { longObjName = fmt.Sprintf("%0242d/%0242d/%0242d", 1, 1, 1) } // create new HTTP request to insert the object. - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, longObjName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, longObjName), int64(buffer.Len()), buffer, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // execute the HTTP request. @@ -1221,7 +1221,7 @@ func (s *TestSuiteCommon) TestPutObjectLongName(c *check) { } // create new HTTP request to insert the object. buffer = bytes.NewReader([]byte("hello world")) - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, longObjName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, longObjName), int64(buffer.Len()), buffer, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // execute the HTTP request. @@ -1234,7 +1234,7 @@ func (s *TestSuiteCommon) TestPutObjectLongName(c *check) { longObjName = fmt.Sprintf("/%0255d/%0255d", 1, 1) buffer = bytes.NewReader([]byte("hello world")) // create new HTTP request to insert the object. - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, longObjName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, longObjName), int64(buffer.Len()), buffer, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // execute the HTTP request. @@ -1246,7 +1246,7 @@ func (s *TestSuiteCommon) TestPutObjectLongName(c *check) { //make object name as unsupported longObjName = fmt.Sprintf("%0256d", 1) buffer = bytes.NewReader([]byte("hello world")) - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, longObjName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, longObjName), int64(buffer.Len()), buffer, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1265,7 +1265,7 @@ func (s *TestSuiteCommon) TestNotBeAbleToCreateObjectInNonexistentBucket(c *chec // preparing for upload by generating the upload URL. objectName := "test-object" - request, err := newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName), + request, err := newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objectName), int64(buffer1.Len()), buffer1, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1286,7 +1286,7 @@ func (s *TestSuiteCommon) TestHeadOnObjectLastModified(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1300,7 +1300,7 @@ func (s *TestSuiteCommon) TestHeadOnObjectLastModified(c *check) { // content for the object to be uploaded. buffer1 := bytes.NewReader([]byte("hello world")) // obtaining URL for uploading the object. - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objectName), int64(buffer1.Len()), buffer1, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1309,7 +1309,7 @@ func (s *TestSuiteCommon) TestHeadOnObjectLastModified(c *check) { c.Assert(err, nil) c.Assert(response.StatusCode, http.StatusOK) // make HTTP request to obtain object info. - request, err = newTestSignedRequest("HEAD", getHeadObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodHead, getHeadObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // execute the HTTP request. @@ -1327,7 +1327,7 @@ func (s *TestSuiteCommon) TestHeadOnObjectLastModified(c *check) { // make HTTP request to obtain object info. // But this time set the "If-Modified-Since" header to be 10 minute more than the actual // last modified time of the object. - request, err = newTestSignedRequest("HEAD", getHeadObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodHead, getHeadObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) request.Header.Set("If-Modified-Since", t.Add(10*time.Minute).UTC().Format(http.TimeFormat)) @@ -1340,7 +1340,7 @@ func (s *TestSuiteCommon) TestHeadOnObjectLastModified(c *check) { // Again, obtain the object info. // This time setting "If-Unmodified-Since" to a time after the object is modified. // As documented above, expecting http.StatusPreconditionFailed. - request, err = newTestSignedRequest("HEAD", getHeadObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodHead, getHeadObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) request.Header.Set("If-Unmodified-Since", t.Add(-10*time.Minute).UTC().Format(http.TimeFormat)) @@ -1350,7 +1350,7 @@ func (s *TestSuiteCommon) TestHeadOnObjectLastModified(c *check) { // make HTTP request to obtain object info. // But this time set a date with unrecognized format to the "If-Modified-Since" header - request, err = newTestSignedRequest("HEAD", getHeadObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodHead, getHeadObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) request.Header.Set("If-Unmodified-Since", "Mon, 02 Jan 2006 15:04:05 +00:00") @@ -1368,7 +1368,7 @@ func (s *TestSuiteCommon) TestHeadOnBucket(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getHEADBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getHEADBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1377,7 +1377,7 @@ func (s *TestSuiteCommon) TestHeadOnBucket(c *check) { c.Assert(err, nil) c.Assert(response.StatusCode, http.StatusOK) // make HEAD request on the bucket. - request, err = newTestSignedRequest("HEAD", getHEADBucketURL(s.endPoint, bucketName), + request, err = newTestSignedRequest(http.MethodHead, getHEADBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // execute the HTTP request. @@ -1393,7 +1393,7 @@ func (s *TestSuiteCommon) TestContentTypePersists(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1407,7 +1407,7 @@ func (s *TestSuiteCommon) TestContentTypePersists(c *check) { buffer1 := bytes.NewReader([]byte("hello world")) objectName := "test-object.png" // constructing HTTP request for object upload. - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objectName), int64(buffer1.Len()), buffer1, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) request.Header.Set("Content-Type", "image/png") @@ -1422,7 +1422,7 @@ func (s *TestSuiteCommon) TestContentTypePersists(c *check) { c.Assert(response.StatusCode, http.StatusOK) // Fetching the object info using HEAD request for the object which was uploaded above. - request, err = newTestSignedRequest("HEAD", getHeadObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodHead, getHeadObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1433,7 +1433,7 @@ func (s *TestSuiteCommon) TestContentTypePersists(c *check) { c.Assert(response.Header.Get("Content-Type"), "image/png") // Fetching the object itself and then verify the Content-Type header. - request, err = newTestSignedRequest("GET", getGetObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodGet, getGetObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1447,7 +1447,7 @@ func (s *TestSuiteCommon) TestContentTypePersists(c *check) { // Uploading a new object with Content-Type "application/json". objectName = "test-object.json" buffer2 := bytes.NewReader([]byte("hello world")) - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objectName), int64(buffer2.Len()), buffer2, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // setting the request header to be application/json. @@ -1463,7 +1463,7 @@ func (s *TestSuiteCommon) TestContentTypePersists(c *check) { c.Assert(response.StatusCode, http.StatusOK) // Obtain the info of the object which was uploaded above using HEAD request. - request, err = newTestSignedRequest("HEAD", getHeadObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodHead, getHeadObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // Execute the HTTP request. @@ -1473,7 +1473,7 @@ func (s *TestSuiteCommon) TestContentTypePersists(c *check) { c.Assert(response.Header.Get("Content-Type"), "application/json") // Fetch the object and assert whether the Content-Type header persists. - request, err = newTestSignedRequest("GET", getGetObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodGet, getGetObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1490,7 +1490,7 @@ func (s *TestSuiteCommon) TestContentTypePersists(c *check) { func (s *TestSuiteCommon) TestPartialContent(c *check) { bucketName := getRandomBucketName() - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1499,7 +1499,7 @@ func (s *TestSuiteCommon) TestPartialContent(c *check) { c.Assert(response.StatusCode, http.StatusOK) buffer1 := bytes.NewReader([]byte("Hello World")) - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, "bar"), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, "bar"), int64(buffer1.Len()), buffer1, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1508,7 +1508,7 @@ func (s *TestSuiteCommon) TestPartialContent(c *check) { c.Assert(response.StatusCode, http.StatusOK) // Prepare request - request, err = newTestSignedRequest("GET", getGetObjectURL(s.endPoint, bucketName, "bar"), + request, err = newTestSignedRequest(http.MethodGet, getGetObjectURL(s.endPoint, bucketName, "bar"), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) request.Header.Add("Range", "bytes=6-7") @@ -1528,7 +1528,7 @@ func (s *TestSuiteCommon) TestListObjectsHandler(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1539,7 +1539,7 @@ func (s *TestSuiteCommon) TestListObjectsHandler(c *check) { for _, objectName := range []string{"foo bar 1", "foo bar 2"} { buffer := bytes.NewReader([]byte("Hello World")) - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objectName), int64(buffer.Len()), buffer, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1573,7 +1573,7 @@ func (s *TestSuiteCommon) TestListObjectsHandler(c *check) { for _, testCase := range testCases { // create listObjectsV1 request with valid parameters - request, err = newTestSignedRequest("GET", testCase.getURL, 0, nil, s.accessKey, s.secretKey, s.signer) + request, err = newTestSignedRequest(http.MethodGet, testCase.getURL, 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // execute the HTTP request. response, err = s.client.Do(request) @@ -1595,7 +1595,7 @@ func (s *TestSuiteCommon) TestListObjectsHandlerErrors(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1605,7 +1605,7 @@ func (s *TestSuiteCommon) TestListObjectsHandlerErrors(c *check) { c.Assert(response.StatusCode, http.StatusOK) // create listObjectsV1 request with invalid value of max-keys parameter. max-keys is set to -2. - request, err = newTestSignedRequest("GET", getListObjectsV1URL(s.endPoint, bucketName, "", "-2", ""), + request, err = newTestSignedRequest(http.MethodGet, getListObjectsV1URL(s.endPoint, bucketName, "", "-2", ""), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // execute the HTTP request. @@ -1615,7 +1615,7 @@ func (s *TestSuiteCommon) TestListObjectsHandlerErrors(c *check) { verifyError(c, response, "InvalidArgument", "Argument maxKeys must be an integer between 0 and 2147483647", http.StatusBadRequest) // create listObjectsV2 request with invalid value of max-keys parameter. max-keys is set to -2. - request, err = newTestSignedRequest("GET", getListObjectsV2URL(s.endPoint, bucketName, "", "-2", "", ""), + request, err = newTestSignedRequest(http.MethodGet, getListObjectsV2URL(s.endPoint, bucketName, "", "-2", "", ""), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // execute the HTTP request. @@ -1633,7 +1633,7 @@ func (s *TestSuiteCommon) TestPutBucketErrors(c *check) { bucketName := getRandomBucketName() // generating a HTTP request to create bucket. // using invalid bucket name. - request, err := newTestSignedRequest("PUT", s.endPoint+"/putbucket-.", + request, err := newTestSignedRequest(http.MethodPut, s.endPoint+"/putbucket-.", 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1642,7 +1642,7 @@ func (s *TestSuiteCommon) TestPutBucketErrors(c *check) { // expected to fail with error message "InvalidBucketName". verifyError(c, response, "InvalidBucketName", "The specified bucket is not valid.", http.StatusBadRequest) // HTTP request to create the bucket. - request, err = newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err = newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1652,7 +1652,7 @@ func (s *TestSuiteCommon) TestPutBucketErrors(c *check) { c.Assert(response.StatusCode, http.StatusOK) // make HTTP request to create the same bucket again. // expected to fail with error message "BucketAlreadyOwnedByYou". - request, err = newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err = newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1666,7 +1666,7 @@ func (s *TestSuiteCommon) TestGetObjectLarge10MiB(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // form HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1695,7 +1695,7 @@ func (s *TestSuiteCommon) TestGetObjectLarge10MiB(c *check) { objectName := "test-big-object" // create HTTP request for object upload. - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objectName), int64(buf.Len()), buf, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1706,7 +1706,7 @@ func (s *TestSuiteCommon) TestGetObjectLarge10MiB(c *check) { c.Assert(response.StatusCode, http.StatusOK) // prepare HTTP requests to download the object. - request, err = newTestSignedRequest("GET", getPutObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodGet, getPutObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1727,7 +1727,7 @@ func (s *TestSuiteCommon) TestGetObjectLarge11MiB(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1757,7 +1757,7 @@ func (s *TestSuiteCommon) TestGetObjectLarge11MiB(c *check) { // Put object buf := bytes.NewReader(buffer.Bytes()) // create HTTP request foe object upload. - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objectName), int64(buf.Len()), buf, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1767,7 +1767,7 @@ func (s *TestSuiteCommon) TestGetObjectLarge11MiB(c *check) { c.Assert(response.StatusCode, http.StatusOK) // create HTTP request to download the object. - request, err = newTestSignedRequest("GET", getGetObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodGet, getGetObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1793,7 +1793,7 @@ func (s *TestSuiteCommon) TestGetPartialObjectMisAligned(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1822,7 +1822,7 @@ func (s *TestSuiteCommon) TestGetPartialObjectMisAligned(c *check) { putContent := string(putBytes) objectName := "test-big-file" // HTTP request to upload the object. - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objectName), int64(buf.Len()), buf, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1852,7 +1852,7 @@ func (s *TestSuiteCommon) TestGetPartialObjectMisAligned(c *check) { for _, t := range testCases { // HTTP request to download the object. - request, err = newTestSignedRequest("GET", getGetObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodGet, getGetObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // Get partial content based on the byte range set. @@ -1877,7 +1877,7 @@ func (s *TestSuiteCommon) TestGetPartialObjectLarge11MiB(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1908,7 +1908,7 @@ func (s *TestSuiteCommon) TestGetPartialObjectLarge11MiB(c *check) { buf := bytes.NewReader([]byte(putContent)) // HTTP request to upload the object. - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objectName), int64(buf.Len()), buf, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1918,7 +1918,7 @@ func (s *TestSuiteCommon) TestGetPartialObjectLarge11MiB(c *check) { c.Assert(response.StatusCode, http.StatusOK) // HTTP request to download the object. - request, err = newTestSignedRequest("GET", getGetObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodGet, getGetObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // This range spans into first two blocks. @@ -1942,7 +1942,7 @@ func (s *TestSuiteCommon) TestGetPartialObjectLarge10MiB(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1974,7 +1974,7 @@ func (s *TestSuiteCommon) TestGetPartialObjectLarge10MiB(c *check) { objectName := "test-big-10Mb-file" // HTTP request to upload the object. - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objectName), int64(buf.Len()), buf, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -1985,7 +1985,7 @@ func (s *TestSuiteCommon) TestGetPartialObjectLarge10MiB(c *check) { c.Assert(response.StatusCode, http.StatusOK) // HTTP request to download the object. - request, err = newTestSignedRequest("GET", getGetObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodGet, getGetObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // Get partial content based on the byte range set. @@ -2010,7 +2010,7 @@ func (s *TestSuiteCommon) TestGetObjectErrors(c *check) { bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -2023,7 +2023,7 @@ func (s *TestSuiteCommon) TestGetObjectErrors(c *check) { // HTTP request to download the object. // Since the specified object doesn't exist in the given bucket, // expected to fail with error message "NoSuchKey" - request, err = newTestSignedRequest("GET", getGetObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodGet, getGetObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -2032,7 +2032,7 @@ func (s *TestSuiteCommon) TestGetObjectErrors(c *check) { verifyError(c, response, "NoSuchKey", "The specified key does not exist.", http.StatusNotFound) // request to download an object, but an invalid bucket name is set. - request, err = newTestSignedRequest("GET", getGetObjectURL(s.endPoint, "getobjecterrors-.", objectName), + request, err = newTestSignedRequest(http.MethodGet, getGetObjectURL(s.endPoint, "getobjecterrors-.", objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -2048,7 +2048,7 @@ func (s *TestSuiteCommon) TestGetObjectRangeErrors(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -2062,7 +2062,7 @@ func (s *TestSuiteCommon) TestGetObjectRangeErrors(c *check) { objectName := "test-object" // HTTP request to upload the object. - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objectName), int64(buffer1.Len()), buffer1, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -2073,7 +2073,7 @@ func (s *TestSuiteCommon) TestGetObjectRangeErrors(c *check) { c.Assert(response.StatusCode, http.StatusOK) // HTTP request to download the object. - request, err = newTestSignedRequest("GET", getGetObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodGet, getGetObjectURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) // Invalid byte range set. request.Header.Add("Range", "bytes=-0") @@ -2091,7 +2091,7 @@ func (s *TestSuiteCommon) TestObjectMultipartAbort(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -2110,7 +2110,7 @@ func (s *TestSuiteCommon) TestObjectMultipartAbort(c *check) { // and the case where there is only one upload ID. // construct HTTP request to initiate a NewMultipart upload. - request, err = newTestSignedRequest("POST", getNewMultipartURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPost, getNewMultipartURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -2128,7 +2128,7 @@ func (s *TestSuiteCommon) TestObjectMultipartAbort(c *check) { c.Assert(len(newResponse.UploadID) > 0, true) // construct HTTP request to initiate a NewMultipart upload. - request, err = newTestSignedRequest("POST", getNewMultipartURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPost, getNewMultipartURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -2150,7 +2150,7 @@ func (s *TestSuiteCommon) TestObjectMultipartAbort(c *check) { // content for the part to be uploaded. buffer1 := bytes.NewReader([]byte("hello world")) // HTTP request for the part to be uploaded. - request, err = newTestSignedRequest("PUT", getPartUploadURL(s.endPoint, bucketName, objectName, uploadID, "1"), + request, err = newTestSignedRequest(http.MethodPut, getPartUploadURL(s.endPoint, bucketName, objectName, uploadID, "1"), int64(buffer1.Len()), buffer1, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // execute the HTTP request to upload the first part. @@ -2161,7 +2161,7 @@ func (s *TestSuiteCommon) TestObjectMultipartAbort(c *check) { // content for the second part to be uploaded. buffer2 := bytes.NewReader([]byte("hello world")) // HTTP request for the second part to be uploaded. - request, err = newTestSignedRequest("PUT", getPartUploadURL(s.endPoint, bucketName, objectName, uploadID, "2"), + request, err = newTestSignedRequest(http.MethodPut, getPartUploadURL(s.endPoint, bucketName, objectName, uploadID, "2"), int64(buffer2.Len()), buffer2, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // execute the HTTP request to upload the second part. @@ -2169,7 +2169,7 @@ func (s *TestSuiteCommon) TestObjectMultipartAbort(c *check) { c.Assert(err, nil) c.Assert(response2.StatusCode, http.StatusOK) // HTTP request for aborting the multipart upload. - request, err = newTestSignedRequest("DELETE", getAbortMultipartUploadURL(s.endPoint, bucketName, objectName, uploadID), + request, err = newTestSignedRequest(http.MethodDelete, getAbortMultipartUploadURL(s.endPoint, bucketName, objectName, uploadID), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // execute the HTTP request to abort the multipart upload. @@ -2185,7 +2185,7 @@ func (s *TestSuiteCommon) TestBucketMultipartList(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), 0, + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -2196,7 +2196,7 @@ func (s *TestSuiteCommon) TestBucketMultipartList(c *check) { objectName := "test-multipart-object" // construct HTTP request to initiate a NewMultipart upload. - request, err = newTestSignedRequest("POST", getNewMultipartURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPost, getNewMultipartURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // execute the HTTP request initiating the new multipart upload. @@ -2218,7 +2218,7 @@ func (s *TestSuiteCommon) TestBucketMultipartList(c *check) { // content for the part to be uploaded. buffer1 := bytes.NewReader([]byte("hello world")) // HTTP request for the part to be uploaded. - request, err = newTestSignedRequest("PUT", getPartUploadURL(s.endPoint, bucketName, objectName, uploadID, "1"), + request, err = newTestSignedRequest(http.MethodPut, getPartUploadURL(s.endPoint, bucketName, objectName, uploadID, "1"), int64(buffer1.Len()), buffer1, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // execute the HTTP request to upload the first part. @@ -2229,7 +2229,7 @@ func (s *TestSuiteCommon) TestBucketMultipartList(c *check) { // content for the second part to be uploaded. buffer2 := bytes.NewReader([]byte("hello world")) // HTTP request for the second part to be uploaded. - request, err = newTestSignedRequest("PUT", getPartUploadURL(s.endPoint, bucketName, objectName, uploadID, "2"), + request, err = newTestSignedRequest(http.MethodPut, getPartUploadURL(s.endPoint, bucketName, objectName, uploadID, "2"), int64(buffer2.Len()), buffer2, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // execute the HTTP request to upload the second part. @@ -2238,7 +2238,7 @@ func (s *TestSuiteCommon) TestBucketMultipartList(c *check) { c.Assert(response2.StatusCode, http.StatusOK) // HTTP request to ListMultipart Uploads. - request, err = newTestSignedRequest("GET", getListMultipartURL(s.endPoint, bucketName), + request, err = newTestSignedRequest(http.MethodGet, getListMultipartURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // execute the HTTP request. @@ -2297,7 +2297,7 @@ func (s *TestSuiteCommon) TestValidateObjectMultipartUploadID(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -2308,7 +2308,7 @@ func (s *TestSuiteCommon) TestValidateObjectMultipartUploadID(c *check) { objectName := "directory1/directory2/object" // construct HTTP request to initiate a NewMultipart upload. - request, err = newTestSignedRequest("POST", getNewMultipartURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPost, getNewMultipartURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // execute the HTTP request initiating the new multipart upload. @@ -2332,7 +2332,7 @@ func (s *TestSuiteCommon) TestObjectMultipartListError(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -2343,7 +2343,7 @@ func (s *TestSuiteCommon) TestObjectMultipartListError(c *check) { objectName := "test-multipart-object" // construct HTTP request to initiate a NewMultipart upload. - request, err = newTestSignedRequest("POST", getNewMultipartURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPost, getNewMultipartURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // execute the HTTP request initiating the new multipart upload. @@ -2363,7 +2363,7 @@ func (s *TestSuiteCommon) TestObjectMultipartListError(c *check) { // content for the part to be uploaded. buffer1 := bytes.NewReader([]byte("hello world")) // HTTP request for the part to be uploaded. - request, err = newTestSignedRequest("PUT", getPartUploadURL(s.endPoint, bucketName, objectName, uploadID, "1"), + request, err = newTestSignedRequest(http.MethodPut, getPartUploadURL(s.endPoint, bucketName, objectName, uploadID, "1"), int64(buffer1.Len()), buffer1, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // execute the HTTP request to upload the first part. @@ -2374,7 +2374,7 @@ func (s *TestSuiteCommon) TestObjectMultipartListError(c *check) { // content for the second part to be uploaded. buffer2 := bytes.NewReader([]byte("hello world")) // HTTP request for the second part to be uploaded. - request, err = newTestSignedRequest("PUT", getPartUploadURL(s.endPoint, bucketName, objectName, uploadID, "2"), + request, err = newTestSignedRequest(http.MethodPut, getPartUploadURL(s.endPoint, bucketName, objectName, uploadID, "2"), int64(buffer2.Len()), buffer2, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -2385,7 +2385,7 @@ func (s *TestSuiteCommon) TestObjectMultipartListError(c *check) { // HTTP request to ListMultipart Uploads. // max-keys is set to valid value of 1 - request, err = newTestSignedRequest("GET", getListMultipartURLWithParams(s.endPoint, bucketName, objectName, uploadID, "1", "", ""), + request, err = newTestSignedRequest(http.MethodGet, getListMultipartURLWithParams(s.endPoint, bucketName, objectName, uploadID, "1", "", ""), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // execute the HTTP request. @@ -2395,7 +2395,7 @@ func (s *TestSuiteCommon) TestObjectMultipartListError(c *check) { // HTTP request to ListMultipart Uploads. // max-keys is set to invalid value of -2. - request, err = newTestSignedRequest("GET", getListMultipartURLWithParams(s.endPoint, bucketName, objectName, uploadID, "-2", "", ""), + request, err = newTestSignedRequest(http.MethodGet, getListMultipartURLWithParams(s.endPoint, bucketName, objectName, uploadID, "-2", "", ""), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // execute the HTTP request. @@ -2412,7 +2412,7 @@ func (s *TestSuiteCommon) TestObjectValidMD5(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -2430,7 +2430,7 @@ func (s *TestSuiteCommon) TestObjectValidMD5(c *check) { buffer1 := bytes.NewReader(data) objectName := "test-1-object" // HTTP request for the object to be uploaded. - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objectName), int64(buffer1.Len()), buffer1, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // set the Content-Md5 to be the hash to content. @@ -2442,7 +2442,7 @@ func (s *TestSuiteCommon) TestObjectValidMD5(c *check) { objectName = "test-2-object" buffer1 = bytes.NewReader(data) // HTTP request for the object to be uploaded. - request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPut, getPutObjectURL(s.endPoint, bucketName, objectName), int64(buffer1.Len()), buffer1, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // set Content-Md5 to invalid value. @@ -2460,7 +2460,7 @@ func (s *TestSuiteCommon) TestObjectMultipart(c *check) { // generate a random bucket name. bucketName := getRandomBucketName() // HTTP request to create the bucket. - request, err := newTestSignedRequest("PUT", getMakeBucketURL(s.endPoint, bucketName), + request, err := newTestSignedRequest(http.MethodPut, getMakeBucketURL(s.endPoint, bucketName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -2471,7 +2471,7 @@ func (s *TestSuiteCommon) TestObjectMultipart(c *check) { objectName := "test-multipart-object" // construct HTTP request to initiate a NewMultipart upload. - request, err = newTestSignedRequest("POST", getNewMultipartURL(s.endPoint, bucketName, objectName), + request, err = newTestSignedRequest(http.MethodPost, getNewMultipartURL(s.endPoint, bucketName, objectName), 0, nil, s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) @@ -2498,7 +2498,7 @@ func (s *TestSuiteCommon) TestObjectMultipart(c *check) { buffer1 := bytes.NewReader(data) // HTTP request for the part to be uploaded. - request, err = newTestSignedRequest("PUT", getPartUploadURL(s.endPoint, bucketName, objectName, uploadID, "1"), + request, err = newTestSignedRequest(http.MethodPut, getPartUploadURL(s.endPoint, bucketName, objectName, uploadID, "1"), int64(buffer1.Len()), buffer1, s.accessKey, s.secretKey, s.signer) // set the Content-Md5 header to the base64 encoding the etag of the content. request.Header.Set("Content-Md5", md5SumBase64) @@ -2518,7 +2518,7 @@ func (s *TestSuiteCommon) TestObjectMultipart(c *check) { buffer2 := bytes.NewReader(data) // HTTP request for the second part to be uploaded. - request, err = newTestSignedRequest("PUT", getPartUploadURL(s.endPoint, bucketName, objectName, uploadID, "2"), + request, err = newTestSignedRequest(http.MethodPut, getPartUploadURL(s.endPoint, bucketName, objectName, uploadID, "2"), int64(buffer2.Len()), buffer2, s.accessKey, s.secretKey, s.signer) // set the Content-Md5 header to the base64 encoding the etag of the content. request.Header.Set("Content-Md5", md5SumBase64) @@ -2546,7 +2546,7 @@ func (s *TestSuiteCommon) TestObjectMultipart(c *check) { completeBytes, err := xml.Marshal(completeUploads) c.Assert(err, nil) // Indicating that all parts are uploaded and initiating CompleteMultipartUpload. - request, err = newTestSignedRequest("POST", getCompleteMultipartUploadURL(s.endPoint, bucketName, objectName, uploadID), + request, err = newTestSignedRequest(http.MethodPost, getCompleteMultipartUploadURL(s.endPoint, bucketName, objectName, uploadID), int64(len(completeBytes)), bytes.NewReader(completeBytes), s.accessKey, s.secretKey, s.signer) c.Assert(err, nil) // Execute the complete multipart request. diff --git a/cmd/signature-v4-utils_test.go b/cmd/signature-v4-utils_test.go index 399cf50c1..493f01d91 100644 --- a/cmd/signature-v4-utils_test.go +++ b/cmd/signature-v4-utils_test.go @@ -72,7 +72,7 @@ func TestSkipContentSha256Cksum(t *testing.T) { for i, testCase := range testCases { // creating an input HTTP request. // Only the headers are relevant for this particular test. - inputReq, err := http.NewRequest("GET", "http://example.com", nil) + inputReq, err := http.NewRequest(http.MethodGet, "http://example.com", nil) if err != nil { t.Fatalf("Error initializing input HTTP request: %v", err) } @@ -135,7 +135,7 @@ func TestExtractSignedHeaders(t *testing.T) { expectedTransferEncoding := "gzip" expectedExpect := "100-continue" - r, err := http.NewRequest("GET", "http://play.min.io:9000", nil) + r, err := http.NewRequest(http.MethodGet, "http://play.min.io:9000", nil) if err != nil { t.Fatal("Unable to create http.Request :", err) } @@ -259,7 +259,7 @@ func TestGetContentSha256Cksum(t *testing.T) { } for i, testCase := range testCases { - r, err := http.NewRequest("GET", "http://localhost/?"+testCase.q, nil) + r, err := http.NewRequest(http.MethodGet, "http://localhost/?"+testCase.q, nil) if err != nil { t.Fatal(err) } diff --git a/cmd/test-utils_test.go b/cmd/test-utils_test.go index 55e95a38c..4d6454f17 100644 --- a/cmd/test-utils_test.go +++ b/cmd/test-utils_test.go @@ -671,7 +671,7 @@ func signStreamingRequest(req *http.Request, accessKey, secretKey string, currTi // Returns new HTTP request object. func newTestStreamingRequest(method, urlStr string, dataLength, chunkSize int64, body io.ReadSeeker) (*http.Request, error) { if method == "" { - method = "POST" + method = http.MethodPost } req, err := http.NewRequest(method, urlStr, nil) @@ -1036,7 +1036,7 @@ func getMD5HashBase64(data []byte) string { // Returns new HTTP request object. func newTestRequest(method, urlStr string, contentLength int64, body io.ReadSeeker) (*http.Request, error) { if method == "" { - method = "POST" + method = http.MethodPost } // Save for subsequent use @@ -1164,7 +1164,7 @@ func newTestSignedRequestV4(method, urlStr string, contentLength int64, body io. // Return new WebRPC request object. func newWebRPCRequest(methodRPC, authorization string, body io.ReadSeeker) (*http.Request, error) { - req, err := http.NewRequest("POST", "/minio/webrpc", nil) + req, err := http.NewRequest(http.MethodPost, "/minio/webrpc", nil) if err != nil { return nil, err } @@ -1515,7 +1515,7 @@ func getCompleteMultipartUploadURL(endPoint, bucketName, objectName, uploadID st } // return URL for listen bucket notification. -func getListenBucketNotificationURL(endPoint, bucketName string, prefixes, suffixes, events []string) string { +func getListenNotificationURL(endPoint, bucketName string, prefixes, suffixes, events []string) string { queryValue := url.Values{} queryValue["prefix"] = prefixes @@ -1693,7 +1693,7 @@ func ExecObjectLayerAPIAnonTest(t *testing.T, obj ObjectLayer, testName, bucketN } // HEAD HTTTP request doesn't contain response body. - if anonReq.Method != "HEAD" { + if anonReq.Method != http.MethodHead { // read the response body. var actualContent []byte actualContent, err = ioutil.ReadAll(rec.Body) @@ -1724,7 +1724,7 @@ func ExecObjectLayerAPIAnonTest(t *testing.T, obj ObjectLayer, testName, bucketN // call the handler using the HTTP Request. apiRouter.ServeHTTP(rec, anonReq) // verify the response body for `ErrAccessDenied` message =. - if anonReq.Method != "HEAD" { + if anonReq.Method != http.MethodHead { // read the response body. actualContent, err := ioutil.ReadAll(rec.Body) if err != nil { @@ -1781,7 +1781,7 @@ func ExecObjectLayerAPINilTest(t TestErrHandler, bucketName, objectName, instanc // HEAD HTTP Request doesn't contain body in its response, // for other type of HTTP requests compare the response body content with the expected one. - if req.Method != "HEAD" { + if req.Method != http.MethodHead { // read the response body. actualContent, err := ioutil.ReadAll(rec.Body) if err != nil { @@ -1975,76 +1975,76 @@ func registerBucketLevelFunc(bucket *mux.Router, api objectAPIHandlers, apiFunct switch apiFunction { case "PostPolicy": // Register PostPolicy handler. - bucket.Methods("POST").HeadersRegexp("Content-Type", "multipart/form-data*").HandlerFunc(api.PostPolicyBucketHandler) + bucket.Methods(http.MethodPost).HeadersRegexp("Content-Type", "multipart/form-data*").HandlerFunc(api.PostPolicyBucketHandler) case "HeadObject": // Register HeadObject handler. bucket.Methods("Head").Path("/{object:.+}").HandlerFunc(api.HeadObjectHandler) case "GetObject": // Register GetObject handler. - bucket.Methods("GET").Path("/{object:.+}").HandlerFunc(api.GetObjectHandler) + bucket.Methods(http.MethodGet).Path("/{object:.+}").HandlerFunc(api.GetObjectHandler) case "PutObject": // Register PutObject handler. - bucket.Methods("PUT").Path("/{object:.+}").HandlerFunc(api.PutObjectHandler) + bucket.Methods(http.MethodPut).Path("/{object:.+}").HandlerFunc(api.PutObjectHandler) case "DeleteObject": // Register Delete Object handler. - bucket.Methods("DELETE").Path("/{object:.+}").HandlerFunc(api.DeleteObjectHandler) + bucket.Methods(http.MethodDelete).Path("/{object:.+}").HandlerFunc(api.DeleteObjectHandler) case "CopyObject": // Register Copy Object handler. - bucket.Methods("PUT").Path("/{object:.+}").HeadersRegexp("X-Amz-Copy-Source", ".*?(\\/|%2F).*?").HandlerFunc(api.CopyObjectHandler) + bucket.Methods(http.MethodPut).Path("/{object:.+}").HeadersRegexp("X-Amz-Copy-Source", ".*?(\\/|%2F).*?").HandlerFunc(api.CopyObjectHandler) case "PutBucketPolicy": // Register PutBucket Policy handler. - bucket.Methods("PUT").HandlerFunc(api.PutBucketPolicyHandler).Queries("policy", "") + bucket.Methods(http.MethodPut).HandlerFunc(api.PutBucketPolicyHandler).Queries("policy", "") case "DeleteBucketPolicy": // Register Delete bucket HTTP policy handler. - bucket.Methods("DELETE").HandlerFunc(api.DeleteBucketPolicyHandler).Queries("policy", "") + bucket.Methods(http.MethodDelete).HandlerFunc(api.DeleteBucketPolicyHandler).Queries("policy", "") case "GetBucketPolicy": // Register Get Bucket policy HTTP Handler. - bucket.Methods("GET").HandlerFunc(api.GetBucketPolicyHandler).Queries("policy", "") + bucket.Methods(http.MethodGet).HandlerFunc(api.GetBucketPolicyHandler).Queries("policy", "") case "GetBucketLifecycle": - bucket.Methods("GET").HandlerFunc(api.GetBucketLifecycleHandler).Queries("lifecycle", "") + bucket.Methods(http.MethodGet).HandlerFunc(api.GetBucketLifecycleHandler).Queries("lifecycle", "") case "PutBucketLifecycle": - bucket.Methods("PUT").HandlerFunc(api.PutBucketLifecycleHandler).Queries("lifecycle", "") + bucket.Methods(http.MethodPut).HandlerFunc(api.PutBucketLifecycleHandler).Queries("lifecycle", "") case "DeleteBucketLifecycle": - bucket.Methods("DELETE").HandlerFunc(api.DeleteBucketLifecycleHandler).Queries("lifecycle", "") + bucket.Methods(http.MethodDelete).HandlerFunc(api.DeleteBucketLifecycleHandler).Queries("lifecycle", "") case "GetBucketLocation": // Register GetBucketLocation handler. - bucket.Methods("GET").HandlerFunc(api.GetBucketLocationHandler).Queries("location", "") + bucket.Methods(http.MethodGet).HandlerFunc(api.GetBucketLocationHandler).Queries("location", "") case "HeadBucket": // Register HeadBucket handler. - bucket.Methods("HEAD").HandlerFunc(api.HeadBucketHandler) + bucket.Methods(http.MethodHead).HandlerFunc(api.HeadBucketHandler) case "DeleteMultipleObjects": // Register DeleteMultipleObjects handler. - bucket.Methods("POST").HandlerFunc(api.DeleteMultipleObjectsHandler).Queries("delete", "") + bucket.Methods(http.MethodPost).HandlerFunc(api.DeleteMultipleObjectsHandler).Queries("delete", "") case "NewMultipart": // Register New Multipart upload handler. - bucket.Methods("POST").Path("/{object:.+}").HandlerFunc(api.NewMultipartUploadHandler).Queries("uploads", "") + bucket.Methods(http.MethodPost).Path("/{object:.+}").HandlerFunc(api.NewMultipartUploadHandler).Queries("uploads", "") case "CopyObjectPart": // Register CopyObjectPart handler. - bucket.Methods("PUT").Path("/{object:.+}").HeadersRegexp("X-Amz-Copy-Source", ".*?(\\/|%2F).*?").HandlerFunc(api.CopyObjectPartHandler).Queries("partNumber", "{partNumber:[0-9]+}", "uploadId", "{uploadId:.*}") + bucket.Methods(http.MethodPut).Path("/{object:.+}").HeadersRegexp("X-Amz-Copy-Source", ".*?(\\/|%2F).*?").HandlerFunc(api.CopyObjectPartHandler).Queries("partNumber", "{partNumber:[0-9]+}", "uploadId", "{uploadId:.*}") case "PutObjectPart": // Register PutObjectPart handler. - bucket.Methods("PUT").Path("/{object:.+}").HandlerFunc(api.PutObjectPartHandler).Queries("partNumber", "{partNumber:[0-9]+}", "uploadId", "{uploadId:.*}") + bucket.Methods(http.MethodPut).Path("/{object:.+}").HandlerFunc(api.PutObjectPartHandler).Queries("partNumber", "{partNumber:[0-9]+}", "uploadId", "{uploadId:.*}") case "ListObjectParts": // Register ListObjectParts handler. - bucket.Methods("GET").Path("/{object:.+}").HandlerFunc(api.ListObjectPartsHandler).Queries("uploadId", "{uploadId:.*}") + bucket.Methods(http.MethodGet).Path("/{object:.+}").HandlerFunc(api.ListObjectPartsHandler).Queries("uploadId", "{uploadId:.*}") case "ListMultipartUploads": // Register ListMultipartUploads handler. - bucket.Methods("GET").HandlerFunc(api.ListMultipartUploadsHandler).Queries("uploads", "") + bucket.Methods(http.MethodGet).HandlerFunc(api.ListMultipartUploadsHandler).Queries("uploads", "") case "CompleteMultipart": // Register Complete Multipart Upload handler. - bucket.Methods("POST").Path("/{object:.+}").HandlerFunc(api.CompleteMultipartUploadHandler).Queries("uploadId", "{uploadId:.*}") + bucket.Methods(http.MethodPost).Path("/{object:.+}").HandlerFunc(api.CompleteMultipartUploadHandler).Queries("uploadId", "{uploadId:.*}") case "AbortMultipart": // Register AbortMultipart Handler. - bucket.Methods("DELETE").Path("/{object:.+}").HandlerFunc(api.AbortMultipartUploadHandler).Queries("uploadId", "{uploadId:.*}") + bucket.Methods(http.MethodDelete).Path("/{object:.+}").HandlerFunc(api.AbortMultipartUploadHandler).Queries("uploadId", "{uploadId:.*}") case "GetBucketNotification": // Register GetBucketNotification Handler. - bucket.Methods("GET").HandlerFunc(api.GetBucketNotificationHandler).Queries("notification", "") + bucket.Methods(http.MethodGet).HandlerFunc(api.GetBucketNotificationHandler).Queries("notification", "") case "PutBucketNotification": // Register PutBucketNotification Handler. - bucket.Methods("PUT").HandlerFunc(api.PutBucketNotificationHandler).Queries("notification", "") - case "ListenBucketNotification": - // Register ListenBucketNotification Handler. - bucket.Methods("GET").HandlerFunc(api.ListenBucketNotificationHandler).Queries("events", "{events:.*}") + bucket.Methods(http.MethodPut).HandlerFunc(api.PutBucketNotificationHandler).Queries("notification", "") + case "ListenNotification": + // Register ListenNotification Handler. + bucket.Methods(http.MethodGet).HandlerFunc(api.ListenNotificationHandler).Queries("events", "{events:.*}") } } } @@ -2087,7 +2087,7 @@ func registerAPIFunctions(muxRouter *mux.Router, objLayer ObjectLayer, apiFuncti } // Register ListBuckets handler. - apiRouter.Methods("GET").HandlerFunc(api.ListBucketsHandler) + apiRouter.Methods(http.MethodGet).HandlerFunc(api.ListBucketsHandler) // Register all bucket level handlers. registerBucketLevelFunc(bucketRouter, api, apiFunctions...) } @@ -2306,7 +2306,7 @@ func uploadTestObject(t *testing.T, apiRouter http.Handler, creds auth.Credentia if !asMultipart { srcData := NewDummyDataGen(partSizes[0], 0) - req, err := newTestSignedRequestV4("PUT", getPutObjectURL("", bucketName, objectName), + req, err := newTestSignedRequestV4(http.MethodPut, getPutObjectURL("", bucketName, objectName), partSizes[0], srcData, creds.AccessKey, creds.SecretKey, metadata) if err != nil { t.Fatalf("Unexpected err: %#v", err) @@ -2320,7 +2320,7 @@ func uploadTestObject(t *testing.T, apiRouter http.Handler, creds auth.Credentia // object when reading). // Initiate mp upload - reqI, err := newTestSignedRequestV4("POST", getNewMultipartURL("", bucketName, objectName), + reqI, err := newTestSignedRequestV4(http.MethodPost, getNewMultipartURL("", bucketName, objectName), 0, nil, creds.AccessKey, creds.SecretKey, metadata) if err != nil { t.Fatalf("Unexpected err: %#v", err) @@ -2343,7 +2343,7 @@ func uploadTestObject(t *testing.T, apiRouter http.Handler, creds auth.Credentia partID := i + 1 partSrc := NewDummyDataGen(partLen, cumulativeSum) cumulativeSum += partLen - req, errP := newTestSignedRequestV4("PUT", + req, errP := newTestSignedRequestV4(http.MethodPut, getPutObjectPartURL("", bucketName, objectName, upID, fmt.Sprintf("%d", partID)), partLen, partSrc, creds.AccessKey, creds.SecretKey, metadata) if errP != nil { @@ -2369,7 +2369,7 @@ func uploadTestObject(t *testing.T, apiRouter http.Handler, creds auth.Credentia if err != nil { t.Fatalf("Unexpected err: %#v", err) } - reqC, errP := newTestSignedRequestV4("POST", + reqC, errP := newTestSignedRequestV4(http.MethodPost, getCompleteMultipartUploadURL("", bucketName, objectName, upID), int64(len(compMpBody)), bytes.NewReader(compMpBody), creds.AccessKey, creds.SecretKey, metadata) diff --git a/cmd/utils_test.go b/cmd/utils_test.go index 087f9842c..90e329b86 100644 --- a/cmd/utils_test.go +++ b/cmd/utils_test.go @@ -225,7 +225,7 @@ func TestCheckURL(t *testing.T) { // Testing dumping request function. func TestDumpRequest(t *testing.T) { - req, err := http.NewRequest("GET", "http://localhost:9000?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=USWUXHGYZQYFYFFIT3RE%2F20170529%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20170529T190139Z&X-Amz-Expires=600&X-Amz-Signature=19b58080999df54b446fc97304eb8dda60d3df1812ae97f3e8783351bfd9781d&X-Amz-SignedHeaders=host&prefix=Hello%2AWorld%2A", nil) + req, err := http.NewRequest(http.MethodGet, "http://localhost:9000?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=USWUXHGYZQYFYFFIT3RE%2F20170529%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20170529T190139Z&X-Amz-Expires=600&X-Amz-Signature=19b58080999df54b446fc97304eb8dda60d3df1812ae97f3e8783351bfd9781d&X-Amz-SignedHeaders=host&prefix=Hello%2AWorld%2A", nil) if err != nil { t.Fatal(err) } @@ -244,7 +244,7 @@ func TestDumpRequest(t *testing.T) { } // Look for expected method. - if res.Method != "GET" { + if res.Method != http.MethodGet { t.Fatalf("Unexpected method %s, expected 'GET'", res.Method) } diff --git a/cmd/web-handlers.go b/cmd/web-handlers.go index bc85e8752..95269feba 100644 --- a/cmd/web-handlers.go +++ b/cmd/web-handlers.go @@ -183,6 +183,7 @@ func (web *webAPIHandlers) MakeBucket(r *http.Request, args *MakeBucketArgs, rep if err = objectAPI.MakeBucketWithLocation(ctx, args.BucketName, opts); err != nil { return toJSONError(ctx, err) } + if err = globalDNSConfig.Put(args.BucketName); err != nil { objectAPI.DeleteBucket(ctx, args.BucketName, false) return toJSONError(ctx, err) @@ -201,6 +202,15 @@ func (web *webAPIHandlers) MakeBucket(r *http.Request, args *MakeBucketArgs, rep } reply.UIVersion = browser.UIVersion + + sendEvent(eventArgs{ + EventName: event.BucketCreated, + BucketName: args.BucketName, + ReqParams: extractReqParams(r), + UserAgent: r.UserAgent(), + Host: handlers.GetSourceIP(r), + }) + return nil } @@ -275,6 +285,14 @@ func (web *webAPIHandlers) DeleteBucket(r *http.Request, args *RemoveBucketArgs, } } + sendEvent(eventArgs{ + EventName: event.BucketRemoved, + BucketName: args.BucketName, + ReqParams: extractReqParams(r), + UserAgent: r.UserAgent(), + Host: handlers.GetSourceIP(r), + }) + return nil } diff --git a/cmd/web-handlers_test.go b/cmd/web-handlers_test.go index 2c1afe6d3..d8eb7f598 100644 --- a/cmd/web-handlers_test.go +++ b/cmd/web-handlers_test.go @@ -752,7 +752,7 @@ func testUploadWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler test := func(token string, sendContentLength bool) int { rec := httptest.NewRecorder() - req, rErr := http.NewRequest("PUT", "/minio/upload/"+bucketName+SlashSeparator+objectName, nil) + req, rErr := http.NewRequest(http.MethodPut, "/minio/upload/"+bucketName+SlashSeparator+objectName, nil) if rErr != nil { t.Fatalf("Cannot create upload request, %v", rErr) } @@ -838,7 +838,7 @@ func testDownloadWebHandler(obj ObjectLayer, instanceType string, t TestErrHandl path = path + token } var req *http.Request - req, err = http.NewRequest("GET", path, nil) + req, err = http.NewRequest(http.MethodGet, path, nil) if err != nil { t.Fatalf("Cannot create upload request, %v", err) @@ -957,7 +957,7 @@ func testWebHandlerDownloadZip(obj ObjectLayer, instanceType string, t TestErrHa return 0, nil } var req *http.Request - req, err = http.NewRequest("POST", path, bytes.NewBuffer(argsData)) + req, err = http.NewRequest(http.MethodPost, path, bytes.NewBuffer(argsData)) if err != nil { t.Fatalf("Cannot create upload request, %v", err) @@ -1055,7 +1055,7 @@ func testWebPresignedGetHandler(obj ObjectLayer, instanceType string, t TestErrH // Initialize a new api recorder. arec := httptest.NewRecorder() - req, err = newTestRequest("GET", presignGetRep.URL, 0, nil) + req, err = newTestRequest(http.MethodGet, presignGetRep.URL, 0, nil) req.Header.Del("x-amz-content-sha256") if err != nil { t.Fatal("Failed to initialized a new request", err) @@ -1153,7 +1153,7 @@ func TestWebCheckAuthorization(t *testing.T) { rec = httptest.NewRecorder() // Test authorization of Web.Download - req, err := http.NewRequest("GET", "/minio/download/bucket/object?token=wrongauth", nil) + req, err := http.NewRequest(http.MethodGet, "/minio/download/bucket/object?token=wrongauth", nil) if err != nil { t.Fatalf("Cannot create upload request, %v", err) } @@ -1170,7 +1170,7 @@ func TestWebCheckAuthorization(t *testing.T) { rec = httptest.NewRecorder() // Test authorization of Web.Upload content := []byte("temporary file's content") - req, err = http.NewRequest("PUT", "/minio/upload/bucket/object", nil) + req, err = http.NewRequest(http.MethodPut, "/minio/upload/bucket/object", nil) req.Header.Set("Authorization", "Bearer foo-authorization") req.Header.Set("User-Agent", "Mozilla") req.Header.Set("Content-Length", strconv.Itoa(len(content))) @@ -1288,7 +1288,7 @@ func TestWebObjectLayerFaultyDisks(t *testing.T) { } // Test authorization of Web.Download - req, err = http.NewRequest("GET", "/minio/download/bucket/object?token="+authorization, nil) + req, err = http.NewRequest(http.MethodGet, "/minio/download/bucket/object?token="+authorization, nil) if err != nil { t.Fatalf("Cannot create upload request, %v", err) } @@ -1299,7 +1299,7 @@ func TestWebObjectLayerFaultyDisks(t *testing.T) { // Test authorization of Web.Upload content := []byte("temporary file's content") - req, err = http.NewRequest("PUT", "/minio/upload/bucket/object", nil) + req, err = http.NewRequest(http.MethodPut, "/minio/upload/bucket/object", nil) req.Header.Set("Authorization", "Bearer "+authorization) req.Header.Set("Content-Length", strconv.Itoa(len(content))) req.Header.Set("x-amz-date", "20160814T114029Z") diff --git a/cmd/web-router.go b/cmd/web-router.go index 6e94246c4..8c32bf567 100644 --- a/cmd/web-router.go +++ b/cmd/web-router.go @@ -83,13 +83,13 @@ func registerWebRouter(router *mux.Router) error { } // RPC handler at URI - /minio/webrpc - webBrowserRouter.Methods("POST").Path("/webrpc").Handler(webRPC) - webBrowserRouter.Methods("PUT").Path("/upload/{bucket}/{object:.+}").HandlerFunc(httpTraceHdrs(web.Upload)) + webBrowserRouter.Methods(http.MethodPost).Path("/webrpc").Handler(webRPC) + webBrowserRouter.Methods(http.MethodPut).Path("/upload/{bucket}/{object:.+}").HandlerFunc(httpTraceHdrs(web.Upload)) // These methods use short-expiry tokens in the URLs. These tokens may unintentionally // be logged, so a new one must be generated for each request. - webBrowserRouter.Methods("GET").Path("/download/{bucket}/{object:.+}").Queries("token", "{token:.*}").HandlerFunc(httpTraceHdrs(web.Download)) - webBrowserRouter.Methods("POST").Path("/zip").Queries("token", "{token:.*}").HandlerFunc(httpTraceHdrs(web.DownloadZip)) + webBrowserRouter.Methods(http.MethodGet).Path("/download/{bucket}/{object:.+}").Queries("token", "{token:.*}").HandlerFunc(httpTraceHdrs(web.Download)) + webBrowserRouter.Methods(http.MethodPost).Path("/zip").Queries("token", "{token:.*}").HandlerFunc(httpTraceHdrs(web.DownloadZip)) // Create compressed assets handler compressAssets := handlers.CompressHandler(http.StripPrefix(minioReservedBucketPath, http.FileServer(assetFS()))) diff --git a/pkg/bucket/policy/action.go b/pkg/bucket/policy/action.go index 43bebf18a..b6d18610e 100644 --- a/pkg/bucket/policy/action.go +++ b/pkg/bucket/policy/action.go @@ -71,6 +71,10 @@ const ( // ListBucketMultipartUploadsAction - ListMultipartUploads Rest API action. ListBucketMultipartUploadsAction = "s3:ListBucketMultipartUploads" + // ListenNotificationAction - ListenNotification Rest API action. + // This is MinIO extension. + ListenNotificationAction = "s3:ListenNotification" + // ListenBucketNotificationAction - ListenBucketNotification Rest API action. // This is MinIO extension. ListenBucketNotificationAction = "s3:ListenBucketNotification" @@ -191,6 +195,7 @@ var supportedActions = map[Action]struct{}{ ListAllMyBucketsAction: {}, ListBucketAction: {}, ListBucketMultipartUploadsAction: {}, + ListenNotificationAction: {}, ListenBucketNotificationAction: {}, ListMultipartUploadPartsAction: {}, PutBucketNotificationAction: {}, @@ -293,6 +298,10 @@ var actionConditionKeyMap = map[Action]condition.KeySet{ ListBucketMultipartUploadsAction: condition.NewKeySet(condition.CommonKeys...), + ListenNotificationAction: condition.NewKeySet(condition.CommonKeys...), + + ListenBucketNotificationAction: condition.NewKeySet(condition.CommonKeys...), + ListMultipartUploadPartsAction: condition.NewKeySet(condition.CommonKeys...), PutObjectAction: condition.NewKeySet( diff --git a/pkg/event/name.go b/pkg/event/name.go index 74ea8802f..d53313bb1 100644 --- a/pkg/event/name.go +++ b/pkg/event/name.go @@ -23,9 +23,10 @@ import ( // Name - event type enum. // Refer http://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html#notification-how-to-event-types-and-destinations +// for most basic values we have since extend this and its not really much applicable other than a reference point. type Name int -// Values of Name +// Values of event Name const ( ObjectAccessedAll Name = 1 + iota ObjectAccessedGet @@ -42,15 +43,23 @@ const ( ObjectRemovedAll ObjectRemovedDelete ObjectRemovedDeleteMarkerCreated + + BucketCreated + BucketRemoved ) // Expand - returns expanded values of abbreviated event type. func (name Name) Expand() []Name { switch name { + case BucketCreated: + return []Name{BucketCreated} + case BucketRemoved: + return []Name{BucketRemoved} case ObjectAccessedAll: return []Name{ObjectAccessedGet, ObjectAccessedHead, ObjectAccessedGetRetention, ObjectAccessedGetLegalHold} case ObjectCreatedAll: - return []Name{ObjectCreatedCompleteMultipartUpload, ObjectCreatedCopy, ObjectCreatedPost, ObjectCreatedPut, ObjectCreatedPutRetention, ObjectCreatedPutLegalHold} + return []Name{ObjectCreatedCompleteMultipartUpload, ObjectCreatedCopy, + ObjectCreatedPost, ObjectCreatedPut, ObjectCreatedPutRetention, ObjectCreatedPutLegalHold} case ObjectRemovedAll: return []Name{ObjectRemovedDelete} default: @@ -61,6 +70,10 @@ func (name Name) Expand() []Name { // String - returns string representation of event type. func (name Name) String() string { switch name { + case BucketCreated: + return "s3:BucketCreated:*" + case BucketRemoved: + return "s3:BucketRemoved:*" case ObjectAccessedAll: return "s3:ObjectAccessed:*" case ObjectAccessedGet: @@ -141,6 +154,10 @@ func (name *Name) UnmarshalJSON(data []byte) error { // ParseName - parses string to Name. func ParseName(s string) (Name, error) { switch s { + case "s3:BucketCreated:*": + return BucketCreated, nil + case "s3:BucketRemoved:*": + return BucketRemoved, nil case "s3:ObjectAccessed:*": return ObjectAccessedAll, nil case "s3:ObjectAccessed:Get": diff --git a/pkg/event/name_test.go b/pkg/event/name_test.go index 2e3fa407a..cf81eba67 100644 --- a/pkg/event/name_test.go +++ b/pkg/event/name_test.go @@ -28,8 +28,11 @@ func TestNameExpand(t *testing.T) { name Name expectedResult []Name }{ + {BucketCreated, []Name{BucketCreated}}, + {BucketRemoved, []Name{BucketRemoved}}, {ObjectAccessedAll, []Name{ObjectAccessedGet, ObjectAccessedHead, ObjectAccessedGetRetention, ObjectAccessedGetLegalHold}}, - {ObjectCreatedAll, []Name{ObjectCreatedCompleteMultipartUpload, ObjectCreatedCopy, ObjectCreatedPost, ObjectCreatedPut, ObjectCreatedPutRetention, ObjectCreatedPutLegalHold}}, + {ObjectCreatedAll, []Name{ObjectCreatedCompleteMultipartUpload, ObjectCreatedCopy, + ObjectCreatedPost, ObjectCreatedPut, ObjectCreatedPutRetention, ObjectCreatedPutLegalHold}}, {ObjectRemovedAll, []Name{ObjectRemovedDelete}}, {ObjectAccessedHead, []Name{ObjectAccessedHead}}, } @@ -50,6 +53,8 @@ func TestNameString(t *testing.T) { name Name expectedResult string }{ + {BucketCreated, "s3:BucketCreated:*"}, + {BucketRemoved, "s3:BucketRemoved:*"}, {ObjectAccessedAll, "s3:ObjectAccessed:*"}, {ObjectAccessedGet, "s3:ObjectAccessed:Get"}, {ObjectAccessedHead, "s3:ObjectAccessed:Head"}, diff --git a/pkg/iam/policy/action.go b/pkg/iam/policy/action.go index 8ac00093d..45122a9bf 100644 --- a/pkg/iam/policy/action.go +++ b/pkg/iam/policy/action.go @@ -70,6 +70,10 @@ const ( // ListBucketMultipartUploadsAction - ListMultipartUploads Rest API action. ListBucketMultipartUploadsAction = "s3:ListBucketMultipartUploads" + // ListenNotificationAction - ListenNotification Rest API action. + // This is MinIO extension. + ListenNotificationAction = "s3:ListenNotification" + // ListenBucketNotificationAction - ListenBucketNotification Rest API action. // This is MinIO extension. ListenBucketNotificationAction = "s3:ListenBucketNotification" @@ -175,6 +179,7 @@ var supportedActions = map[Action]struct{}{ ListAllMyBucketsAction: {}, ListBucketAction: {}, ListBucketMultipartUploadsAction: {}, + ListenNotificationAction: {}, ListenBucketNotificationAction: {}, ListMultipartUploadPartsAction: {}, PutBucketLifecycleAction: {}, @@ -283,6 +288,8 @@ var actionConditionKeyMap = map[Action]condition.KeySet{ ListBucketMultipartUploadsAction: condition.NewKeySet(condition.CommonKeys...), + ListenNotificationAction: condition.NewKeySet(condition.CommonKeys...), + ListenBucketNotificationAction: condition.NewKeySet(condition.CommonKeys...), ListMultipartUploadPartsAction: condition.NewKeySet(condition.CommonKeys...),