github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/cmd/api-router.go (about) 1 // Copyright (c) 2015-2021 MinIO, Inc. 2 // 3 // This file is part of MinIO Object Storage stack 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package cmd 19 20 import ( 21 "net" 22 "net/http" 23 24 consoleapi "github.com/minio/console/api" 25 xhttp "github.com/minio/minio/internal/http" 26 "github.com/minio/mux" 27 "github.com/minio/pkg/v2/wildcard" 28 "github.com/rs/cors" 29 ) 30 31 func newHTTPServerFn() *xhttp.Server { 32 globalObjLayerMutex.RLock() 33 defer globalObjLayerMutex.RUnlock() 34 return globalHTTPServer 35 } 36 37 func setHTTPServer(h *xhttp.Server) { 38 globalObjLayerMutex.Lock() 39 globalHTTPServer = h 40 globalObjLayerMutex.Unlock() 41 } 42 43 func newConsoleServerFn() *consoleapi.Server { 44 globalObjLayerMutex.RLock() 45 defer globalObjLayerMutex.RUnlock() 46 return globalConsoleSrv 47 } 48 49 func setConsoleSrv(srv *consoleapi.Server) { 50 globalObjLayerMutex.Lock() 51 globalConsoleSrv = srv 52 globalObjLayerMutex.Unlock() 53 } 54 55 func newObjectLayerFn() ObjectLayer { 56 globalObjLayerMutex.RLock() 57 defer globalObjLayerMutex.RUnlock() 58 return globalObjectAPI 59 } 60 61 func setObjectLayer(o ObjectLayer) { 62 globalObjLayerMutex.Lock() 63 globalObjectAPI = o 64 globalObjLayerMutex.Unlock() 65 } 66 67 // objectAPIHandler implements and provides http handlers for S3 API. 68 type objectAPIHandlers struct { 69 ObjectAPI func() ObjectLayer 70 } 71 72 // getHost tries its best to return the request host. 73 // According to section 14.23 of RFC 2616 the Host header 74 // can include the port number if the default value of 80 is not used. 75 func getHost(r *http.Request) string { 76 if r.URL.IsAbs() { 77 return r.URL.Host 78 } 79 return r.Host 80 } 81 82 func notImplementedHandler(w http.ResponseWriter, r *http.Request) { 83 writeErrorResponse(r.Context(), w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL) 84 } 85 86 type rejectedAPI struct { 87 api string 88 methods []string 89 queries []string 90 path string 91 } 92 93 var rejectedObjAPIs = []rejectedAPI{ 94 { 95 api: "torrent", 96 methods: []string{http.MethodPut, http.MethodDelete, http.MethodGet}, 97 queries: []string{"torrent", ""}, 98 path: "/{object:.+}", 99 }, 100 { 101 api: "acl", 102 methods: []string{http.MethodDelete}, 103 queries: []string{"acl", ""}, 104 path: "/{object:.+}", 105 }, 106 } 107 108 var rejectedBucketAPIs = []rejectedAPI{ 109 { 110 api: "inventory", 111 methods: []string{http.MethodGet, http.MethodPut, http.MethodDelete}, 112 queries: []string{"inventory", ""}, 113 }, 114 { 115 api: "cors", 116 methods: []string{http.MethodPut, http.MethodDelete}, 117 queries: []string{"cors", ""}, 118 }, 119 { 120 api: "metrics", 121 methods: []string{http.MethodGet, http.MethodPut, http.MethodDelete}, 122 queries: []string{"metrics", ""}, 123 }, 124 { 125 api: "website", 126 methods: []string{http.MethodPut}, 127 queries: []string{"website", ""}, 128 }, 129 { 130 api: "logging", 131 methods: []string{http.MethodPut, http.MethodDelete}, 132 queries: []string{"logging", ""}, 133 }, 134 { 135 api: "accelerate", 136 methods: []string{http.MethodPut, http.MethodDelete}, 137 queries: []string{"accelerate", ""}, 138 }, 139 { 140 api: "requestPayment", 141 methods: []string{http.MethodPut, http.MethodDelete}, 142 queries: []string{"requestPayment", ""}, 143 }, 144 { 145 api: "acl", 146 methods: []string{http.MethodDelete, http.MethodPut, http.MethodHead}, 147 queries: []string{"acl", ""}, 148 }, 149 { 150 api: "publicAccessBlock", 151 methods: []string{http.MethodDelete, http.MethodPut, http.MethodGet}, 152 queries: []string{"publicAccessBlock", ""}, 153 }, 154 { 155 api: "ownershipControls", 156 methods: []string{http.MethodDelete, http.MethodPut, http.MethodGet}, 157 queries: []string{"ownershipControls", ""}, 158 }, 159 { 160 api: "intelligent-tiering", 161 methods: []string{http.MethodDelete, http.MethodPut, http.MethodGet}, 162 queries: []string{"intelligent-tiering", ""}, 163 }, 164 { 165 api: "analytics", 166 methods: []string{http.MethodDelete, http.MethodPut, http.MethodGet}, 167 queries: []string{"analytics", ""}, 168 }, 169 } 170 171 // Set of s3 handler options as bit flags. 172 type s3HFlag uint8 173 174 const ( 175 // when provided, disables Gzip compression. 176 noGZS3HFlag = 1 << iota 177 178 // when provided, enables only tracing of headers. Otherwise, both headers 179 // and body are traced. 180 traceHdrsS3HFlag 181 182 // when provided, disables throttling via the `maxClients` middleware. 183 noThrottleS3HFlag 184 ) 185 186 func (h s3HFlag) has(flag s3HFlag) bool { 187 // Use bitwise-AND and check if the result is non-zero. 188 return h&flag != 0 189 } 190 191 // s3APIMiddleware - performs some common handler functionality for S3 API 192 // handlers. 193 // 194 // It is set per-"handler function registration" in the router to allow for 195 // behavior modification via flags. 196 // 197 // This middleware always calls `collectAPIStats` to collect API stats. 198 // 199 // The passed in handler function must be a method of `objectAPIHandlers` for 200 // the name displayed in logs and trace to be accurate. The name is extracted 201 // via reflection. 202 // 203 // When **no** flags are passed, the behavior is to trace both headers and body, 204 // gzip the response and throttle the handler via `maxClients`. Each of these 205 // can be disabled via the corresponding `s3HFlag`. 206 // 207 // CAUTION: for requests involving large req/resp bodies ensure to pass the 208 // `traceHdrsS3HFlag`, otherwise both headers and body will be traced, causing 209 // high memory usage! 210 func s3APIMiddleware(f http.HandlerFunc, flags ...s3HFlag) http.HandlerFunc { 211 // Collect all flags with bitwise-OR and assign operator 212 var handlerFlags s3HFlag 213 for _, flag := range flags { 214 handlerFlags |= flag 215 } 216 217 // Get name of the handler using reflection. 218 handlerName := getHandlerName(f, "objectAPIHandlers") 219 220 var handler http.HandlerFunc = func(w http.ResponseWriter, r *http.Request) { 221 // Wrap the actual handler with the appropriate tracing middleware. 222 var tracedHandler http.HandlerFunc 223 if handlerFlags.has(traceHdrsS3HFlag) { 224 tracedHandler = httpTraceHdrs(f) 225 } else { 226 tracedHandler = httpTraceAll(f) 227 } 228 229 // Skip wrapping with the gzip middleware if specified. 230 var gzippedHandler http.HandlerFunc = tracedHandler 231 if !handlerFlags.has(noGZS3HFlag) { 232 gzippedHandler = gzipHandler(gzippedHandler) 233 } 234 235 // Skip wrapping with throttling middleware if specified. 236 var throttledHandler http.HandlerFunc = gzippedHandler 237 if !handlerFlags.has(noThrottleS3HFlag) { 238 throttledHandler = maxClients(throttledHandler) 239 } 240 241 // Collect API stats using the API name got from reflection in 242 // `getHandlerName`. 243 statsCollectedHandler := collectAPIStats(handlerName, throttledHandler) 244 245 // Call the final handler. 246 statsCollectedHandler(w, r) 247 } 248 249 return handler 250 } 251 252 // registerAPIRouter - registers S3 compatible APIs. 253 func registerAPIRouter(router *mux.Router) { 254 // Initialize API. 255 api := objectAPIHandlers{ 256 ObjectAPI: newObjectLayerFn, 257 } 258 259 // API Router 260 apiRouter := router.PathPrefix(SlashSeparator).Subrouter() 261 262 var routers []*mux.Router 263 for _, domainName := range globalDomainNames { 264 if IsKubernetes() { 265 routers = append(routers, apiRouter.MatcherFunc(func(r *http.Request, match *mux.RouteMatch) bool { 266 host, _, err := net.SplitHostPort(getHost(r)) 267 if err != nil { 268 host = r.Host 269 } 270 // Make sure to skip matching minio.<domain>` this is 271 // specifically meant for operator/k8s deployment 272 // The reason we need to skip this is for a special 273 // usecase where we need to make sure that 274 // minio.<namespace>.svc.<cluster_domain> is ignored 275 // by the bucketDNS style to ensure that path style 276 // is available and honored at this domain. 277 // 278 // All other `<bucket>.<namespace>.svc.<cluster_domain>` 279 // makes sure that buckets are routed through this matcher 280 // to match for `<bucket>` 281 return host != minioReservedBucket+"."+domainName 282 }).Host("{bucket:.+}."+domainName).Subrouter()) 283 } else { 284 routers = append(routers, apiRouter.Host("{bucket:.+}."+domainName).Subrouter()) 285 } 286 } 287 routers = append(routers, apiRouter.PathPrefix("/{bucket}").Subrouter()) 288 289 for _, router := range routers { 290 // Register all rejected object APIs 291 for _, r := range rejectedObjAPIs { 292 t := router.Methods(r.methods...). 293 HandlerFunc(collectAPIStats(r.api, httpTraceAll(notImplementedHandler))). 294 Queries(r.queries...) 295 t.Path(r.path) 296 } 297 298 // Object operations 299 // HeadObject 300 router.Methods(http.MethodHead).Path("/{object:.+}"). 301 HandlerFunc(s3APIMiddleware(api.HeadObjectHandler)) 302 303 // GetObjectAttributes 304 router.Methods(http.MethodGet).Path("/{object:.+}"). 305 HandlerFunc(s3APIMiddleware(api.GetObjectAttributesHandler, traceHdrsS3HFlag)). 306 Queries("attributes", "") 307 308 // CopyObjectPart 309 router.Methods(http.MethodPut).Path("/{object:.+}"). 310 HeadersRegexp(xhttp.AmzCopySource, ".*?(\\/|%2F).*?"). 311 HandlerFunc(s3APIMiddleware(api.CopyObjectPartHandler)). 312 Queries("partNumber", "{partNumber:.*}", "uploadId", "{uploadId:.*}") 313 // PutObjectPart 314 router.Methods(http.MethodPut).Path("/{object:.+}"). 315 HandlerFunc(s3APIMiddleware(api.PutObjectPartHandler, traceHdrsS3HFlag)). 316 Queries("partNumber", "{partNumber:.*}", "uploadId", "{uploadId:.*}") 317 // ListObjectParts 318 router.Methods(http.MethodGet).Path("/{object:.+}"). 319 HandlerFunc(s3APIMiddleware(api.ListObjectPartsHandler)). 320 Queries("uploadId", "{uploadId:.*}") 321 // CompleteMultipartUpload 322 router.Methods(http.MethodPost).Path("/{object:.+}"). 323 HandlerFunc(s3APIMiddleware(api.CompleteMultipartUploadHandler)). 324 Queries("uploadId", "{uploadId:.*}") 325 // NewMultipartUpload 326 router.Methods(http.MethodPost).Path("/{object:.+}"). 327 HandlerFunc(s3APIMiddleware(api.NewMultipartUploadHandler)). 328 Queries("uploads", "") 329 // AbortMultipartUpload 330 router.Methods(http.MethodDelete).Path("/{object:.+}"). 331 HandlerFunc(s3APIMiddleware(api.AbortMultipartUploadHandler)). 332 Queries("uploadId", "{uploadId:.*}") 333 // GetObjectACL - this is a dummy call. 334 router.Methods(http.MethodGet).Path("/{object:.+}"). 335 HandlerFunc(s3APIMiddleware(api.GetObjectACLHandler, traceHdrsS3HFlag)). 336 Queries("acl", "") 337 // PutObjectACL - this is a dummy call. 338 router.Methods(http.MethodPut).Path("/{object:.+}"). 339 HandlerFunc(s3APIMiddleware(api.PutObjectACLHandler, traceHdrsS3HFlag)). 340 Queries("acl", "") 341 // GetObjectTagging 342 router.Methods(http.MethodGet).Path("/{object:.+}"). 343 HandlerFunc(s3APIMiddleware(api.GetObjectTaggingHandler, traceHdrsS3HFlag)). 344 Queries("tagging", "") 345 // PutObjectTagging 346 router.Methods(http.MethodPut).Path("/{object:.+}"). 347 HandlerFunc(s3APIMiddleware(api.PutObjectTaggingHandler, traceHdrsS3HFlag)). 348 Queries("tagging", "") 349 // DeleteObjectTagging 350 router.Methods(http.MethodDelete).Path("/{object:.+}"). 351 HandlerFunc(s3APIMiddleware(api.DeleteObjectTaggingHandler, traceHdrsS3HFlag)). 352 Queries("tagging", "") 353 // SelectObjectContent 354 router.Methods(http.MethodPost).Path("/{object:.+}"). 355 HandlerFunc(s3APIMiddleware(api.SelectObjectContentHandler, traceHdrsS3HFlag)). 356 Queries("select", "").Queries("select-type", "2") 357 // GetObjectRetention 358 router.Methods(http.MethodGet).Path("/{object:.+}"). 359 HandlerFunc(s3APIMiddleware(api.GetObjectRetentionHandler)). 360 Queries("retention", "") 361 // GetObjectLegalHold 362 router.Methods(http.MethodGet).Path("/{object:.+}"). 363 HandlerFunc(s3APIMiddleware(api.GetObjectLegalHoldHandler)). 364 Queries("legal-hold", "") 365 // GetObject with lambda ARNs 366 router.Methods(http.MethodGet).Path("/{object:.+}"). 367 HandlerFunc(s3APIMiddleware(api.GetObjectLambdaHandler, traceHdrsS3HFlag)). 368 Queries("lambdaArn", "{lambdaArn:.*}") 369 // GetObject 370 router.Methods(http.MethodGet).Path("/{object:.+}"). 371 HandlerFunc(s3APIMiddleware(api.GetObjectHandler, traceHdrsS3HFlag)) 372 // CopyObject 373 router.Methods(http.MethodPut).Path("/{object:.+}"). 374 HeadersRegexp(xhttp.AmzCopySource, ".*?(\\/|%2F).*?"). 375 HandlerFunc(s3APIMiddleware(api.CopyObjectHandler)) 376 // PutObjectRetention 377 router.Methods(http.MethodPut).Path("/{object:.+}"). 378 HandlerFunc(s3APIMiddleware(api.PutObjectRetentionHandler)). 379 Queries("retention", "") 380 // PutObjectLegalHold 381 router.Methods(http.MethodPut).Path("/{object:.+}"). 382 HandlerFunc(s3APIMiddleware(api.PutObjectLegalHoldHandler)). 383 Queries("legal-hold", "") 384 385 // PutObject with auto-extract support for zip 386 router.Methods(http.MethodPut).Path("/{object:.+}"). 387 HeadersRegexp(xhttp.AmzSnowballExtract, "true"). 388 HandlerFunc(s3APIMiddleware(api.PutObjectExtractHandler, traceHdrsS3HFlag)) 389 390 // PutObject 391 router.Methods(http.MethodPut).Path("/{object:.+}"). 392 HandlerFunc(s3APIMiddleware(api.PutObjectHandler, traceHdrsS3HFlag)) 393 394 // DeleteObject 395 router.Methods(http.MethodDelete).Path("/{object:.+}"). 396 HandlerFunc(s3APIMiddleware(api.DeleteObjectHandler)) 397 398 // PostRestoreObject 399 router.Methods(http.MethodPost).Path("/{object:.+}"). 400 HandlerFunc(s3APIMiddleware(api.PostRestoreObjectHandler)). 401 Queries("restore", "") 402 403 // Bucket operations 404 405 // GetBucketLocation 406 router.Methods(http.MethodGet). 407 HandlerFunc(s3APIMiddleware(api.GetBucketLocationHandler)). 408 Queries("location", "") 409 // GetBucketPolicy 410 router.Methods(http.MethodGet). 411 HandlerFunc(s3APIMiddleware(api.GetBucketPolicyHandler)). 412 Queries("policy", "") 413 // GetBucketLifecycle 414 router.Methods(http.MethodGet). 415 HandlerFunc(s3APIMiddleware(api.GetBucketLifecycleHandler)). 416 Queries("lifecycle", "") 417 // GetBucketEncryption 418 router.Methods(http.MethodGet). 419 HandlerFunc(s3APIMiddleware(api.GetBucketEncryptionHandler)). 420 Queries("encryption", "") 421 // GetBucketObjectLockConfig 422 router.Methods(http.MethodGet). 423 HandlerFunc(s3APIMiddleware(api.GetBucketObjectLockConfigHandler)). 424 Queries("object-lock", "") 425 // GetBucketReplicationConfig 426 router.Methods(http.MethodGet). 427 HandlerFunc(s3APIMiddleware(api.GetBucketReplicationConfigHandler)). 428 Queries("replication", "") 429 // GetBucketVersioning 430 router.Methods(http.MethodGet). 431 HandlerFunc(s3APIMiddleware(api.GetBucketVersioningHandler)). 432 Queries("versioning", "") 433 // GetBucketNotification 434 router.Methods(http.MethodGet). 435 HandlerFunc(s3APIMiddleware(api.GetBucketNotificationHandler)). 436 Queries("notification", "") 437 // ListenNotification 438 router.Methods(http.MethodGet). 439 HandlerFunc(s3APIMiddleware(api.ListenNotificationHandler, noThrottleS3HFlag)). 440 Queries("events", "{events:.*}") 441 // ResetBucketReplicationStatus - MinIO extension API 442 router.Methods(http.MethodGet). 443 HandlerFunc(s3APIMiddleware(api.ResetBucketReplicationStatusHandler)). 444 Queries("replication-reset-status", "") 445 446 // Dummy Bucket Calls 447 // GetBucketACL -- this is a dummy call. 448 router.Methods(http.MethodGet). 449 HandlerFunc(s3APIMiddleware(api.GetBucketACLHandler)). 450 Queries("acl", "") 451 // PutBucketACL -- this is a dummy call. 452 router.Methods(http.MethodPut). 453 HandlerFunc(s3APIMiddleware(api.PutBucketACLHandler)). 454 Queries("acl", "") 455 // GetBucketCors - this is a dummy call. 456 router.Methods(http.MethodGet). 457 HandlerFunc(s3APIMiddleware(api.GetBucketCorsHandler)). 458 Queries("cors", "") 459 // GetBucketWebsiteHandler - this is a dummy call. 460 router.Methods(http.MethodGet). 461 HandlerFunc(s3APIMiddleware(api.GetBucketWebsiteHandler)). 462 Queries("website", "") 463 // GetBucketAccelerateHandler - this is a dummy call. 464 router.Methods(http.MethodGet). 465 HandlerFunc(s3APIMiddleware(api.GetBucketAccelerateHandler)). 466 Queries("accelerate", "") 467 // GetBucketRequestPaymentHandler - this is a dummy call. 468 router.Methods(http.MethodGet). 469 HandlerFunc(s3APIMiddleware(api.GetBucketRequestPaymentHandler)). 470 Queries("requestPayment", "") 471 // GetBucketLoggingHandler - this is a dummy call. 472 router.Methods(http.MethodGet). 473 HandlerFunc(s3APIMiddleware(api.GetBucketLoggingHandler)). 474 Queries("logging", "") 475 // GetBucketTaggingHandler 476 router.Methods(http.MethodGet). 477 HandlerFunc(s3APIMiddleware(api.GetBucketTaggingHandler)). 478 Queries("tagging", "") 479 // DeleteBucketWebsiteHandler 480 router.Methods(http.MethodDelete). 481 HandlerFunc(s3APIMiddleware(api.DeleteBucketWebsiteHandler)). 482 Queries("website", "") 483 // DeleteBucketTaggingHandler 484 router.Methods(http.MethodDelete). 485 HandlerFunc(s3APIMiddleware(api.DeleteBucketTaggingHandler)). 486 Queries("tagging", "") 487 488 // ListMultipartUploads 489 router.Methods(http.MethodGet). 490 HandlerFunc(s3APIMiddleware(api.ListMultipartUploadsHandler)). 491 Queries("uploads", "") 492 // ListObjectsV2M 493 router.Methods(http.MethodGet). 494 HandlerFunc(s3APIMiddleware(api.ListObjectsV2MHandler)). 495 Queries("list-type", "2", "metadata", "true") 496 // ListObjectsV2 497 router.Methods(http.MethodGet). 498 HandlerFunc(s3APIMiddleware(api.ListObjectsV2Handler)). 499 Queries("list-type", "2") 500 // ListObjectVersions 501 router.Methods(http.MethodGet). 502 HandlerFunc(s3APIMiddleware(api.ListObjectVersionsMHandler)). 503 Queries("versions", "", "metadata", "true") 504 // ListObjectVersions 505 router.Methods(http.MethodGet). 506 HandlerFunc(s3APIMiddleware(api.ListObjectVersionsHandler)). 507 Queries("versions", "") 508 // GetBucketPolicyStatus 509 router.Methods(http.MethodGet). 510 HandlerFunc(s3APIMiddleware(api.GetBucketPolicyStatusHandler)). 511 Queries("policyStatus", "") 512 // PutBucketLifecycle 513 router.Methods(http.MethodPut). 514 HandlerFunc(s3APIMiddleware(api.PutBucketLifecycleHandler)). 515 Queries("lifecycle", "") 516 // PutBucketReplicationConfig 517 router.Methods(http.MethodPut). 518 HandlerFunc(s3APIMiddleware(api.PutBucketReplicationConfigHandler)). 519 Queries("replication", "") 520 // PutBucketEncryption 521 router.Methods(http.MethodPut). 522 HandlerFunc(s3APIMiddleware(api.PutBucketEncryptionHandler)). 523 Queries("encryption", "") 524 525 // PutBucketPolicy 526 router.Methods(http.MethodPut). 527 HandlerFunc(s3APIMiddleware(api.PutBucketPolicyHandler)). 528 Queries("policy", "") 529 530 // PutBucketObjectLockConfig 531 router.Methods(http.MethodPut). 532 HandlerFunc(s3APIMiddleware(api.PutBucketObjectLockConfigHandler)). 533 Queries("object-lock", "") 534 // PutBucketTaggingHandler 535 router.Methods(http.MethodPut). 536 HandlerFunc(s3APIMiddleware(api.PutBucketTaggingHandler)). 537 Queries("tagging", "") 538 // PutBucketVersioning 539 router.Methods(http.MethodPut). 540 HandlerFunc(s3APIMiddleware(api.PutBucketVersioningHandler)). 541 Queries("versioning", "") 542 // PutBucketNotification 543 router.Methods(http.MethodPut). 544 HandlerFunc(s3APIMiddleware(api.PutBucketNotificationHandler)). 545 Queries("notification", "") 546 // ResetBucketReplicationStart - MinIO extension API 547 router.Methods(http.MethodPut). 548 HandlerFunc(s3APIMiddleware(api.ResetBucketReplicationStartHandler)). 549 Queries("replication-reset", "") 550 551 // PutBucket 552 router.Methods(http.MethodPut). 553 HandlerFunc(s3APIMiddleware(api.PutBucketHandler)) 554 // HeadBucket 555 router.Methods(http.MethodHead). 556 HandlerFunc(s3APIMiddleware(api.HeadBucketHandler)) 557 // PostPolicy 558 router.Methods(http.MethodPost). 559 MatcherFunc(func(r *http.Request, _ *mux.RouteMatch) bool { 560 return isRequestPostPolicySignatureV4(r) 561 }). 562 HandlerFunc(s3APIMiddleware(api.PostPolicyBucketHandler, traceHdrsS3HFlag)) 563 // DeleteMultipleObjects 564 router.Methods(http.MethodPost). 565 HandlerFunc(s3APIMiddleware(api.DeleteMultipleObjectsHandler)). 566 Queries("delete", "") 567 // DeleteBucketPolicy 568 router.Methods(http.MethodDelete). 569 HandlerFunc(s3APIMiddleware(api.DeleteBucketPolicyHandler)). 570 Queries("policy", "") 571 // DeleteBucketReplication 572 router.Methods(http.MethodDelete). 573 HandlerFunc(s3APIMiddleware(api.DeleteBucketReplicationConfigHandler)). 574 Queries("replication", "") 575 // DeleteBucketLifecycle 576 router.Methods(http.MethodDelete). 577 HandlerFunc(s3APIMiddleware(api.DeleteBucketLifecycleHandler)). 578 Queries("lifecycle", "") 579 // DeleteBucketEncryption 580 router.Methods(http.MethodDelete). 581 HandlerFunc(s3APIMiddleware(api.DeleteBucketEncryptionHandler)). 582 Queries("encryption", "") 583 // DeleteBucket 584 router.Methods(http.MethodDelete). 585 HandlerFunc(s3APIMiddleware(api.DeleteBucketHandler)) 586 587 // MinIO extension API for replication. 588 // 589 router.Methods(http.MethodGet). 590 HandlerFunc(s3APIMiddleware(api.GetBucketReplicationMetricsV2Handler)). 591 Queries("replication-metrics", "2") 592 // deprecated handler 593 router.Methods(http.MethodGet). 594 HandlerFunc(s3APIMiddleware(api.GetBucketReplicationMetricsHandler)). 595 Queries("replication-metrics", "") 596 597 // ValidateBucketReplicationCreds 598 router.Methods(http.MethodGet). 599 HandlerFunc(s3APIMiddleware(api.ValidateBucketReplicationCredsHandler)). 600 Queries("replication-check", "") 601 602 // Register rejected bucket APIs 603 for _, r := range rejectedBucketAPIs { 604 router.Methods(r.methods...). 605 HandlerFunc(collectAPIStats(r.api, httpTraceAll(notImplementedHandler))). 606 Queries(r.queries...) 607 } 608 609 // S3 ListObjectsV1 (Legacy) 610 router.Methods(http.MethodGet). 611 HandlerFunc(s3APIMiddleware(api.ListObjectsV1Handler)) 612 } 613 614 // Root operation 615 616 // ListenNotification 617 apiRouter.Methods(http.MethodGet).Path(SlashSeparator). 618 HandlerFunc(s3APIMiddleware(api.ListenNotificationHandler, noThrottleS3HFlag)). 619 Queries("events", "{events:.*}") 620 621 // ListBuckets 622 apiRouter.Methods(http.MethodGet).Path(SlashSeparator). 623 HandlerFunc(s3APIMiddleware(api.ListBucketsHandler)) 624 625 // S3 browser with signature v4 adds '//' for ListBuckets request, so rather 626 // than failing with UnknownAPIRequest we simply handle it for now. 627 apiRouter.Methods(http.MethodGet).Path(SlashSeparator + SlashSeparator). 628 HandlerFunc(s3APIMiddleware(api.ListBucketsHandler)) 629 630 // If none of the routes match add default error handler routes 631 apiRouter.NotFoundHandler = collectAPIStats("notfound", httpTraceAll(errorResponseHandler)) 632 apiRouter.MethodNotAllowedHandler = collectAPIStats("methodnotallowed", httpTraceAll(methodNotAllowedHandler("S3"))) 633 } 634 635 // corsHandler handler for CORS (Cross Origin Resource Sharing) 636 func corsHandler(handler http.Handler) http.Handler { 637 commonS3Headers := []string{ 638 xhttp.Date, 639 xhttp.ETag, 640 xhttp.ServerInfo, 641 xhttp.Connection, 642 xhttp.AcceptRanges, 643 xhttp.ContentRange, 644 xhttp.ContentEncoding, 645 xhttp.ContentLength, 646 xhttp.ContentType, 647 xhttp.ContentDisposition, 648 xhttp.LastModified, 649 xhttp.ContentLanguage, 650 xhttp.CacheControl, 651 xhttp.RetryAfter, 652 xhttp.AmzBucketRegion, 653 xhttp.Expires, 654 "X-Amz*", 655 "x-amz*", 656 "*", 657 } 658 opts := cors.Options{ 659 AllowOriginFunc: func(origin string) bool { 660 for _, allowedOrigin := range globalAPIConfig.getCorsAllowOrigins() { 661 if wildcard.MatchSimple(allowedOrigin, origin) { 662 return true 663 } 664 } 665 return false 666 }, 667 AllowedMethods: []string{ 668 http.MethodGet, 669 http.MethodPut, 670 http.MethodHead, 671 http.MethodPost, 672 http.MethodDelete, 673 http.MethodOptions, 674 http.MethodPatch, 675 }, 676 AllowedHeaders: commonS3Headers, 677 ExposedHeaders: commonS3Headers, 678 AllowCredentials: true, 679 } 680 return cors.New(opts).Handler(handler) 681 }