| 
									
										
										
										
											2015-07-01 05:42:29 +08:00
										 |  |  | /* | 
					
						
							| 
									
										
										
										
											2017-01-19 04:24:34 +08:00
										 |  |  |  * Minio Cloud Storage, (C) 2015, 2016, 2017 Minio, Inc. | 
					
						
							| 
									
										
										
										
											2015-07-01 05:42:29 +08:00
										 |  |  |  * | 
					
						
							|  |  |  |  * 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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-19 07:23:42 +08:00
										 |  |  | package cmd | 
					
						
							| 
									
										
										
										
											2015-07-01 05:42:29 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2016-10-25 14:47:03 +08:00
										 |  |  | 	"encoding/base64" | 
					
						
							| 
									
										
										
										
											2016-03-06 08:43:48 +08:00
										 |  |  | 	"encoding/xml" | 
					
						
							| 
									
										
										
										
											2016-12-21 01:32:17 +08:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2016-02-16 09:42:39 +08:00
										 |  |  | 	"io" | 
					
						
							| 
									
										
										
										
											2015-07-01 05:42:29 +08:00
										 |  |  | 	"net/http" | 
					
						
							| 
									
										
										
											
												accessPolicy: Implement Put, Get, Delete access policy.
This patch implements Get,Put,Delete bucket policies
Supporting - http://docs.aws.amazon.com/AmazonS3/latest/dev/access-policy-language-overview.html
Currently supports following actions.
   "*":                             true,
   "s3:*":                          true,
   "s3:GetObject":                  true,
   "s3:ListBucket":                 true,
   "s3:PutObject":                  true,
   "s3:CreateBucket":               true,
   "s3:GetBucketLocation":          true,
   "s3:DeleteBucket":               true,
   "s3:DeleteObject":               true,
   "s3:AbortMultipartUpload":       true,
   "s3:ListBucketMultipartUploads": true,
   "s3:ListMultipartUploadParts":   true,
following conditions for "StringEquals" and "StringNotEquals"
   "s3:prefix", "s3:max-keys"
											
										 
											2016-02-04 08:46:56 +08:00
										 |  |  | 	"net/url" | 
					
						
							| 
									
										
										
										
											2017-01-12 05:26:42 +08:00
										 |  |  | 	"path" | 
					
						
							| 
									
										
										
											
												accessPolicy: Implement Put, Get, Delete access policy.
This patch implements Get,Put,Delete bucket policies
Supporting - http://docs.aws.amazon.com/AmazonS3/latest/dev/access-policy-language-overview.html
Currently supports following actions.
   "*":                             true,
   "s3:*":                          true,
   "s3:GetObject":                  true,
   "s3:ListBucket":                 true,
   "s3:PutObject":                  true,
   "s3:CreateBucket":               true,
   "s3:GetBucketLocation":          true,
   "s3:DeleteBucket":               true,
   "s3:DeleteObject":               true,
   "s3:AbortMultipartUpload":       true,
   "s3:ListBucketMultipartUploads": true,
   "s3:ListMultipartUploadParts":   true,
following conditions for "StringEquals" and "StringNotEquals"
   "s3:prefix", "s3:max-keys"
											
										 
											2016-02-04 08:46:56 +08:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2016-09-02 16:59:08 +08:00
										 |  |  | 	"sync" | 
					
						
							| 
									
										
										
										
											2015-07-01 05:42:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-22 09:57:05 +08:00
										 |  |  | 	mux "github.com/gorilla/mux" | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  | 	"github.com/minio/minio-go/pkg/set" | 
					
						
							| 
									
										
										
										
											2015-07-01 05:42:29 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-07 09:31:40 +08:00
										 |  |  | // http://docs.aws.amazon.com/AmazonS3/latest/dev/using-with-s3-actions.html
 | 
					
						
							| 
									
										
										
										
											2016-08-11 11:10:48 +08:00
										 |  |  | // Enforces bucket policies for a bucket for a given tatusaction.
 | 
					
						
							|  |  |  | func enforceBucketPolicy(bucket string, action string, reqURL *url.URL) (s3Error APIErrorCode) { | 
					
						
							| 
									
										
										
										
											2016-09-27 05:28:35 +08:00
										 |  |  | 	// Verify if bucket actually exists
 | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | 	if err := checkBucketExist(bucket, newObjectLayerFn()); err != nil { | 
					
						
							| 
									
										
										
										
											2016-09-23 14:47:48 +08:00
										 |  |  | 		err = errorCause(err) | 
					
						
							|  |  |  | 		switch err.(type) { | 
					
						
							|  |  |  | 		case BucketNameInvalid: | 
					
						
							|  |  |  | 			// Return error for invalid bucket name.
 | 
					
						
							|  |  |  | 			return ErrInvalidBucketName | 
					
						
							|  |  |  | 		case BucketNotFound: | 
					
						
							|  |  |  | 			// For no bucket found we return NoSuchBucket instead.
 | 
					
						
							|  |  |  | 			return ErrNoSuchBucket | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		errorIf(err, "Unable to read bucket policy.") | 
					
						
							|  |  |  | 		// Return internal error for any other errors so that we can investigate.
 | 
					
						
							|  |  |  | 		return ErrInternalError | 
					
						
							| 
									
										
										
											
												accessPolicy: Implement Put, Get, Delete access policy.
This patch implements Get,Put,Delete bucket policies
Supporting - http://docs.aws.amazon.com/AmazonS3/latest/dev/access-policy-language-overview.html
Currently supports following actions.
   "*":                             true,
   "s3:*":                          true,
   "s3:GetObject":                  true,
   "s3:ListBucket":                 true,
   "s3:PutObject":                  true,
   "s3:CreateBucket":               true,
   "s3:GetBucketLocation":          true,
   "s3:DeleteBucket":               true,
   "s3:DeleteObject":               true,
   "s3:AbortMultipartUpload":       true,
   "s3:ListBucketMultipartUploads": true,
   "s3:ListMultipartUploadParts":   true,
following conditions for "StringEquals" and "StringNotEquals"
   "s3:prefix", "s3:max-keys"
											
										 
											2016-02-04 08:46:56 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-27 05:28:35 +08:00
										 |  |  | 	// Fetch bucket policy, if policy is not set return access denied.
 | 
					
						
							|  |  |  | 	policy := globalBucketPolicies.GetBucketPolicy(bucket) | 
					
						
							|  |  |  | 	if policy == nil { | 
					
						
							|  |  |  | 		return ErrAccessDenied | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-05 07:56:57 +08:00
										 |  |  | 	// Construct resource in 'arn:aws:s3:::examplebucket/object' format.
 | 
					
						
							| 
									
										
										
										
											2017-01-11 08:43:48 +08:00
										 |  |  | 	resource := bucketARNPrefix + strings.TrimSuffix(strings.TrimPrefix(reqURL.Path, "/"), "/") | 
					
						
							| 
									
										
										
											
												accessPolicy: Implement Put, Get, Delete access policy.
This patch implements Get,Put,Delete bucket policies
Supporting - http://docs.aws.amazon.com/AmazonS3/latest/dev/access-policy-language-overview.html
Currently supports following actions.
   "*":                             true,
   "s3:*":                          true,
   "s3:GetObject":                  true,
   "s3:ListBucket":                 true,
   "s3:PutObject":                  true,
   "s3:CreateBucket":               true,
   "s3:GetBucketLocation":          true,
   "s3:DeleteBucket":               true,
   "s3:DeleteObject":               true,
   "s3:AbortMultipartUpload":       true,
   "s3:ListBucketMultipartUploads": true,
   "s3:ListMultipartUploadParts":   true,
following conditions for "StringEquals" and "StringNotEquals"
   "s3:prefix", "s3:max-keys"
											
										 
											2016-02-04 08:46:56 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Get conditions for policy verification.
 | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  | 	conditionKeyMap := make(map[string]set.StringSet) | 
					
						
							| 
									
										
										
											
												accessPolicy: Implement Put, Get, Delete access policy.
This patch implements Get,Put,Delete bucket policies
Supporting - http://docs.aws.amazon.com/AmazonS3/latest/dev/access-policy-language-overview.html
Currently supports following actions.
   "*":                             true,
   "s3:*":                          true,
   "s3:GetObject":                  true,
   "s3:ListBucket":                 true,
   "s3:PutObject":                  true,
   "s3:CreateBucket":               true,
   "s3:GetBucketLocation":          true,
   "s3:DeleteBucket":               true,
   "s3:DeleteObject":               true,
   "s3:AbortMultipartUpload":       true,
   "s3:ListBucketMultipartUploads": true,
   "s3:ListMultipartUploadParts":   true,
following conditions for "StringEquals" and "StringNotEquals"
   "s3:prefix", "s3:max-keys"
											
										 
											2016-02-04 08:46:56 +08:00
										 |  |  | 	for queryParam := range reqURL.Query() { | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  | 		conditionKeyMap[queryParam] = set.CreateStringSet(reqURL.Query().Get(queryParam)) | 
					
						
							| 
									
										
										
											
												accessPolicy: Implement Put, Get, Delete access policy.
This patch implements Get,Put,Delete bucket policies
Supporting - http://docs.aws.amazon.com/AmazonS3/latest/dev/access-policy-language-overview.html
Currently supports following actions.
   "*":                             true,
   "s3:*":                          true,
   "s3:GetObject":                  true,
   "s3:ListBucket":                 true,
   "s3:PutObject":                  true,
   "s3:CreateBucket":               true,
   "s3:GetBucketLocation":          true,
   "s3:DeleteBucket":               true,
   "s3:DeleteObject":               true,
   "s3:AbortMultipartUpload":       true,
   "s3:ListBucketMultipartUploads": true,
   "s3:ListMultipartUploadParts":   true,
following conditions for "StringEquals" and "StringNotEquals"
   "s3:prefix", "s3:max-keys"
											
										 
											2016-02-04 08:46:56 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Validate action, resource and conditions with current policy statements.
 | 
					
						
							| 
									
										
										
										
											2016-08-20 18:16:38 +08:00
										 |  |  | 	if !bucketPolicyEvalStatements(action, resource, conditionKeyMap, policy.Statements) { | 
					
						
							| 
									
										
										
										
											2016-03-10 18:24:52 +08:00
										 |  |  | 		return ErrAccessDenied | 
					
						
							| 
									
										
										
											
												accessPolicy: Implement Put, Get, Delete access policy.
This patch implements Get,Put,Delete bucket policies
Supporting - http://docs.aws.amazon.com/AmazonS3/latest/dev/access-policy-language-overview.html
Currently supports following actions.
   "*":                             true,
   "s3:*":                          true,
   "s3:GetObject":                  true,
   "s3:ListBucket":                 true,
   "s3:PutObject":                  true,
   "s3:CreateBucket":               true,
   "s3:GetBucketLocation":          true,
   "s3:DeleteBucket":               true,
   "s3:DeleteObject":               true,
   "s3:AbortMultipartUpload":       true,
   "s3:ListBucketMultipartUploads": true,
   "s3:ListMultipartUploadParts":   true,
following conditions for "StringEquals" and "StringNotEquals"
   "s3:prefix", "s3:max-keys"
											
										 
											2016-02-04 08:46:56 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-10 18:24:52 +08:00
										 |  |  | 	return ErrNone | 
					
						
							| 
									
										
										
											
												accessPolicy: Implement Put, Get, Delete access policy.
This patch implements Get,Put,Delete bucket policies
Supporting - http://docs.aws.amazon.com/AmazonS3/latest/dev/access-policy-language-overview.html
Currently supports following actions.
   "*":                             true,
   "s3:*":                          true,
   "s3:GetObject":                  true,
   "s3:ListBucket":                 true,
   "s3:PutObject":                  true,
   "s3:CreateBucket":               true,
   "s3:GetBucketLocation":          true,
   "s3:DeleteBucket":               true,
   "s3:DeleteObject":               true,
   "s3:AbortMultipartUpload":       true,
   "s3:ListBucketMultipartUploads": true,
   "s3:ListMultipartUploadParts":   true,
following conditions for "StringEquals" and "StringNotEquals"
   "s3:prefix", "s3:max-keys"
											
										 
											2016-02-04 08:46:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-12 05:26:42 +08:00
										 |  |  | // Check if the action is allowed on the bucket/prefix.
 | 
					
						
							|  |  |  | func isBucketActionAllowed(action, bucket, prefix string) bool { | 
					
						
							|  |  |  | 	policy := globalBucketPolicies.GetBucketPolicy(bucket) | 
					
						
							|  |  |  | 	if policy == nil { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	resource := bucketARNPrefix + path.Join(bucket, prefix) | 
					
						
							|  |  |  | 	var conditionKeyMap map[string]set.StringSet | 
					
						
							|  |  |  | 	// Validate action, resource and conditions with current policy statements.
 | 
					
						
							|  |  |  | 	if !bucketPolicyEvalStatements(action, resource, conditionKeyMap, policy.Statements) { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return true | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 15:38:38 +08:00
										 |  |  | // GetBucketLocationHandler - GET Bucket location.
 | 
					
						
							|  |  |  | // -------------------------
 | 
					
						
							|  |  |  | // This operation returns bucket location.
 | 
					
						
							| 
									
										
										
										
											2016-04-13 03:45:15 +08:00
										 |  |  | func (api objectAPIHandlers) GetBucketLocationHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							| 
									
										
										
										
											2016-02-16 09:42:39 +08:00
										 |  |  | 	vars := mux.Vars(r) | 
					
						
							| 
									
										
										
										
											2015-12-27 15:38:38 +08:00
										 |  |  | 	bucket := vars["bucket"] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-11 09:47:49 +08:00
										 |  |  | 	objectAPI := api.ObjectAPI() | 
					
						
							|  |  |  | 	if objectAPI == nil { | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, ErrServerNotInitialized, r.URL) | 
					
						
							| 
									
										
										
										
											2016-08-11 09:47:49 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-20 03:31:51 +08:00
										 |  |  | 	s3Error := checkRequestAuthType(r, bucket, "s3:GetBucketLocation", globalMinioDefaultRegion) | 
					
						
							|  |  |  | 	if s3Error == ErrInvalidRegion { | 
					
						
							|  |  |  | 		// Clients like boto3 send getBucketLocation() call signed with region that is configured.
 | 
					
						
							|  |  |  | 		s3Error = checkRequestAuthType(r, "", "s3:GetBucketLocation", serverConfig.GetRegion()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if s3Error != ErrNone { | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, s3Error, r.URL) | 
					
						
							| 
									
										
										
										
											2016-11-22 05:51:05 +08:00
										 |  |  | 		return | 
					
						
							| 
									
										
										
										
											2016-02-05 04:52:25 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-01 05:11:14 +08:00
										 |  |  | 	if _, err := objectAPI.GetBucketInfo(bucket); err != nil { | 
					
						
							| 
									
										
										
										
											2016-05-17 05:31:28 +08:00
										 |  |  | 		errorIf(err, "Unable to fetch bucket info.") | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, toAPIErrorCode(err), r.URL) | 
					
						
							| 
									
										
										
										
											2016-01-20 09:49:48 +08:00
										 |  |  | 		return | 
					
						
							| 
									
										
										
										
											2015-12-27 15:38:38 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-16 09:42:39 +08:00
										 |  |  | 	// Generate response.
 | 
					
						
							| 
									
										
										
										
											2016-03-07 04:16:22 +08:00
										 |  |  | 	encodedSuccessResponse := encodeResponse(LocationResponse{}) | 
					
						
							| 
									
										
											  
											
												config/main: Re-write config files - add to new config v3
- New config format.
```
{
	"version": "3",
	"address": ":9000",
    "backend": {
          "type": "fs",
          "disk": "/path"
    },
	"credential": {
		"accessKey": "WLGDGYAQYIGI833EV05A",
		"secretKey": "BYvgJM101sHngl2uzjXS/OBF/aMxAN06JrJ3qJlF"
	},
	"region": "us-east-1",
	"logger": {
		"file": {
			"enable": false,
			"fileName": "",
			"level": "error"
		},
		"syslog": {
			"enable": false,
			"address": "",
			"level": "debug"
		},
		"console": {
			"enable": true,
			"level": "fatal"
		}
	}
}
```
New command lines in lieu of supporting XL.
Minio initialize filesystem backend.
~~~
$ minio init fs <path>
~~~
Minio initialize XL backend.
~~~
$ minio init xl <url1>...<url16>
~~~
For 'fs' backend it starts the server.
~~~
$ minio server
~~~
For 'xl' backend it waits for servers to join.
~~~
$ minio server
... [PROGRESS BAR] of servers connecting
~~~
Now on other servers execute 'join' and they connect.
~~~
....
minio join <url1> -- from <url2> && minio server
minio join <url1> -- from <url3> && minio server
...
...
minio join <url1> -- from <url16> && minio server
~~~
											
										 
											2016-02-13 07:27:10 +08:00
										 |  |  | 	// Get current region.
 | 
					
						
							|  |  |  | 	region := serverConfig.GetRegion() | 
					
						
							| 
									
										
										
										
											2017-01-19 04:24:34 +08:00
										 |  |  | 	if region != globalMinioDefaultRegion { | 
					
						
							| 
									
										
										
										
											2016-03-07 04:16:22 +08:00
										 |  |  | 		encodedSuccessResponse = encodeResponse(LocationResponse{ | 
					
						
							| 
									
										
											  
											
												config/main: Re-write config files - add to new config v3
- New config format.
```
{
	"version": "3",
	"address": ":9000",
    "backend": {
          "type": "fs",
          "disk": "/path"
    },
	"credential": {
		"accessKey": "WLGDGYAQYIGI833EV05A",
		"secretKey": "BYvgJM101sHngl2uzjXS/OBF/aMxAN06JrJ3qJlF"
	},
	"region": "us-east-1",
	"logger": {
		"file": {
			"enable": false,
			"fileName": "",
			"level": "error"
		},
		"syslog": {
			"enable": false,
			"address": "",
			"level": "debug"
		},
		"console": {
			"enable": true,
			"level": "fatal"
		}
	}
}
```
New command lines in lieu of supporting XL.
Minio initialize filesystem backend.
~~~
$ minio init fs <path>
~~~
Minio initialize XL backend.
~~~
$ minio init xl <url1>...<url16>
~~~
For 'fs' backend it starts the server.
~~~
$ minio server
~~~
For 'xl' backend it waits for servers to join.
~~~
$ minio server
... [PROGRESS BAR] of servers connecting
~~~
Now on other servers execute 'join' and they connect.
~~~
....
minio join <url1> -- from <url2> && minio server
minio join <url1> -- from <url3> && minio server
...
...
minio join <url1> -- from <url16> && minio server
~~~
											
										 
											2016-02-13 07:27:10 +08:00
										 |  |  | 			Location: region, | 
					
						
							| 
									
										
										
										
											2016-02-16 09:42:39 +08:00
										 |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Write success response.
 | 
					
						
							|  |  |  | 	writeSuccessResponseXML(w, encodedSuccessResponse) | 
					
						
							| 
									
										
										
										
											2015-12-27 15:38:38 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-01 11:15:48 +08:00
										 |  |  | // ListMultipartUploadsHandler - GET Bucket (List Multipart uploads)
 | 
					
						
							| 
									
										
										
										
											2015-07-01 05:42:29 +08:00
										 |  |  | // -------------------------
 | 
					
						
							|  |  |  | // This operation lists in-progress multipart uploads. An in-progress
 | 
					
						
							|  |  |  | // multipart upload is a multipart upload that has been initiated,
 | 
					
						
							| 
									
										
										
										
											2015-10-17 10:09:35 +08:00
										 |  |  | // using the Initiate Multipart Upload request, but has not yet been
 | 
					
						
							|  |  |  | // completed or aborted. This operation returns at most 1,000 multipart
 | 
					
						
							|  |  |  | // uploads in the response.
 | 
					
						
							| 
									
										
										
										
											2015-07-01 05:42:29 +08:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2016-04-13 03:45:15 +08:00
										 |  |  | func (api objectAPIHandlers) ListMultipartUploadsHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							| 
									
										
										
										
											2016-02-16 09:42:39 +08:00
										 |  |  | 	vars := mux.Vars(r) | 
					
						
							| 
									
										
										
										
											2015-10-17 10:09:35 +08:00
										 |  |  | 	bucket := vars["bucket"] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-11 09:47:49 +08:00
										 |  |  | 	objectAPI := api.ObjectAPI() | 
					
						
							|  |  |  | 	if objectAPI == nil { | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, ErrServerNotInitialized, r.URL) | 
					
						
							| 
									
										
										
										
											2016-08-11 09:47:49 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-22 05:51:05 +08:00
										 |  |  | 	if s3Error := checkRequestAuthType(r, bucket, "s3:ListBucketMultipartUploads", serverConfig.GetRegion()); s3Error != ErrNone { | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, s3Error, r.URL) | 
					
						
							| 
									
										
										
										
											2016-02-16 09:42:39 +08:00
										 |  |  | 		return | 
					
						
							| 
									
										
										
										
											2016-02-05 04:52:25 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												objectAPI: Fix object API interface, remove unnecessary structs.
ObjectAPI changes.
```
ListObjects(bucket, prefix, marker, delimiter string, maxKeys int) (ListObjectsInfo, *probe.Error)
ListMultipartUploads(bucket, objectPrefix, keyMarker, uploadIDMarker, delimiter string, maxUploads int) (ListMultipartsInfo, *probe.Error)
ListObjectParts(bucket, object, uploadID string, partNumberMarker, maxParts int) (ListPartsInfo, *probe.Error)
CompleteMultipartUpload(bucket string, object string, uploadID string, parts []completePart) (ObjectInfo, *probe.Error)
```
											
										 
											2016-04-03 16:34:20 +08:00
										 |  |  | 	prefix, keyMarker, uploadIDMarker, delimiter, maxUploads, _ := getBucketMultipartResources(r.URL.Query()) | 
					
						
							|  |  |  | 	if maxUploads < 0 { | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, ErrInvalidMaxUploads, r.URL) | 
					
						
							| 
									
										
										
										
											2015-07-17 08:22:45 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-04-06 03:26:17 +08:00
										 |  |  | 	if keyMarker != "" { | 
					
						
							| 
									
										
										
										
											2016-04-30 05:24:10 +08:00
										 |  |  | 		// Marker not common with prefix is not implemented.
 | 
					
						
							|  |  |  | 		if !strings.HasPrefix(keyMarker, prefix) { | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 			writeErrorResponse(w, ErrNotImplemented, r.URL) | 
					
						
							| 
									
										
										
										
											2016-04-30 05:24:10 +08:00
										 |  |  | 			return | 
					
						
							| 
									
										
										
										
											2016-04-06 03:26:17 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-07-01 05:42:29 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-01 05:11:14 +08:00
										 |  |  | 	listMultipartsInfo, err := objectAPI.ListMultipartUploads(bucket, prefix, keyMarker, uploadIDMarker, delimiter, maxUploads) | 
					
						
							| 
									
										
										
										
											2015-09-19 18:20:07 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2016-05-17 05:31:28 +08:00
										 |  |  | 		errorIf(err, "Unable to list multipart uploads.") | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, toAPIErrorCode(err), r.URL) | 
					
						
							| 
									
										
										
										
											2015-08-04 07:17:21 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-09-19 18:20:07 +08:00
										 |  |  | 	// generate response
 | 
					
						
							| 
									
										
										
											
												objectAPI: Fix object API interface, remove unnecessary structs.
ObjectAPI changes.
```
ListObjects(bucket, prefix, marker, delimiter string, maxKeys int) (ListObjectsInfo, *probe.Error)
ListMultipartUploads(bucket, objectPrefix, keyMarker, uploadIDMarker, delimiter string, maxUploads int) (ListMultipartsInfo, *probe.Error)
ListObjectParts(bucket, object, uploadID string, partNumberMarker, maxParts int) (ListPartsInfo, *probe.Error)
CompleteMultipartUpload(bucket string, object string, uploadID string, parts []completePart) (ObjectInfo, *probe.Error)
```
											
										 
											2016-04-03 16:34:20 +08:00
										 |  |  | 	response := generateListMultipartUploadsResponse(bucket, listMultipartsInfo) | 
					
						
							| 
									
										
										
										
											2016-03-07 04:16:22 +08:00
										 |  |  | 	encodedSuccessResponse := encodeResponse(response) | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-08 16:40:06 +08:00
										 |  |  | 	// write success response.
 | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 	writeSuccessResponseXML(w, encodedSuccessResponse) | 
					
						
							| 
									
										
										
										
											2015-07-01 05:42:29 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-10 00:21:37 +08:00
										 |  |  | // ListBucketsHandler - GET Service.
 | 
					
						
							| 
									
										
										
										
											2015-07-01 05:42:29 +08:00
										 |  |  | // -----------
 | 
					
						
							|  |  |  | // This implementation of the GET operation returns a list of all buckets
 | 
					
						
							|  |  |  | // owned by the authenticated sender of the request.
 | 
					
						
							| 
									
										
										
										
											2016-04-13 03:45:15 +08:00
										 |  |  | func (api objectAPIHandlers) ListBucketsHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							| 
									
										
										
										
											2016-08-11 09:47:49 +08:00
										 |  |  | 	objectAPI := api.ObjectAPI() | 
					
						
							|  |  |  | 	if objectAPI == nil { | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, ErrServerNotInitialized, r.URL) | 
					
						
							| 
									
										
										
										
											2016-08-11 09:47:49 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-22 05:51:05 +08:00
										 |  |  | 	// ListBuckets does not have any bucket action.
 | 
					
						
							| 
									
										
										
										
											2017-01-19 04:24:34 +08:00
										 |  |  | 	s3Error := checkRequestAuthType(r, "", "", globalMinioDefaultRegion) | 
					
						
							| 
									
										
										
										
											2016-12-01 05:55:56 +08:00
										 |  |  | 	if s3Error == ErrInvalidRegion { | 
					
						
							|  |  |  | 		// Clients like boto3 send listBuckets() call signed with region that is configured.
 | 
					
						
							|  |  |  | 		s3Error = checkRequestAuthType(r, "", "", serverConfig.GetRegion()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if s3Error != ErrNone { | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, s3Error, r.URL) | 
					
						
							| 
									
										
										
										
											2016-02-16 09:42:39 +08:00
										 |  |  | 		return | 
					
						
							| 
									
										
										
										
											2016-02-05 04:52:25 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-08-11 09:47:49 +08:00
										 |  |  | 	// Invoke the list buckets.
 | 
					
						
							| 
									
										
										
										
											2016-08-01 05:11:14 +08:00
										 |  |  | 	bucketsInfo, err := objectAPI.ListBuckets() | 
					
						
							| 
									
										
										
										
											2016-07-18 04:23:15 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		errorIf(err, "Unable to list buckets.") | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, toAPIErrorCode(err), r.URL) | 
					
						
							| 
									
										
										
										
											2015-08-04 07:17:21 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-07-18 04:23:15 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Generate response.
 | 
					
						
							|  |  |  | 	response := generateListBucketsResponse(bucketsInfo) | 
					
						
							|  |  |  | 	encodedSuccessResponse := encodeResponse(response) | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-18 04:23:15 +08:00
										 |  |  | 	// Write response.
 | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 	writeSuccessResponseXML(w, encodedSuccessResponse) | 
					
						
							| 
									
										
										
										
											2015-07-01 05:42:29 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 08:43:48 +08:00
										 |  |  | // DeleteMultipleObjectsHandler - deletes multiple objects.
 | 
					
						
							| 
									
										
										
										
											2016-04-13 03:45:15 +08:00
										 |  |  | func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							| 
									
										
										
										
											2016-03-06 08:43:48 +08:00
										 |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	bucket := vars["bucket"] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-11 09:47:49 +08:00
										 |  |  | 	objectAPI := api.ObjectAPI() | 
					
						
							|  |  |  | 	if objectAPI == nil { | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, ErrServerNotInitialized, r.URL) | 
					
						
							| 
									
										
										
										
											2016-08-11 09:47:49 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-22 05:51:05 +08:00
										 |  |  | 	if s3Error := checkRequestAuthType(r, bucket, "s3:DeleteObject", serverConfig.GetRegion()); s3Error != ErrNone { | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, s3Error, r.URL) | 
					
						
							| 
									
										
										
										
											2016-03-13 08:08:15 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 08:43:48 +08:00
										 |  |  | 	// Content-Length is required and should be non-zero
 | 
					
						
							|  |  |  | 	// http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html
 | 
					
						
							|  |  |  | 	if r.ContentLength <= 0 { | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, ErrMissingContentLength, r.URL) | 
					
						
							| 
									
										
										
										
											2016-03-06 08:43:48 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Content-Md5 is requied should be set
 | 
					
						
							|  |  |  | 	// http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html
 | 
					
						
							|  |  |  | 	if _, ok := r.Header["Content-Md5"]; !ok { | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, ErrMissingContentMD5, r.URL) | 
					
						
							| 
									
										
										
										
											2016-03-06 08:43:48 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Allocate incoming content length bytes.
 | 
					
						
							|  |  |  | 	deleteXMLBytes := make([]byte, r.ContentLength) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Read incoming body XML bytes.
 | 
					
						
							| 
									
										
										
										
											2016-04-30 05:24:10 +08:00
										 |  |  | 	if _, err := io.ReadFull(r.Body, deleteXMLBytes); err != nil { | 
					
						
							| 
									
										
										
										
											2016-05-17 05:31:28 +08:00
										 |  |  | 		errorIf(err, "Unable to read HTTP body.") | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, ErrInternalError, r.URL) | 
					
						
							| 
									
										
										
										
											2016-03-06 08:43:48 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Unmarshal list of keys to be deleted.
 | 
					
						
							|  |  |  | 	deleteObjects := &DeleteObjectsRequest{} | 
					
						
							| 
									
										
										
										
											2016-04-30 05:24:10 +08:00
										 |  |  | 	if err := xml.Unmarshal(deleteXMLBytes, deleteObjects); err != nil { | 
					
						
							| 
									
										
										
										
											2016-05-17 05:31:28 +08:00
										 |  |  | 		errorIf(err, "Unable to unmarshal delete objects request XML.") | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, ErrMalformedXML, r.URL) | 
					
						
							| 
									
										
										
										
											2016-03-06 08:43:48 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-02 16:59:08 +08:00
										 |  |  | 	var wg = &sync.WaitGroup{} // Allocate a new wait group.
 | 
					
						
							|  |  |  | 	var dErrs = make([]error, len(deleteObjects.Objects)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Delete all requested objects in parallel.
 | 
					
						
							|  |  |  | 	for index, object := range deleteObjects.Objects { | 
					
						
							|  |  |  | 		wg.Add(1) | 
					
						
							|  |  |  | 		go func(i int, obj ObjectIdentifier) { | 
					
						
							|  |  |  | 			defer wg.Done() | 
					
						
							| 
									
										
										
										
											2016-09-07 04:30:05 +08:00
										 |  |  | 			dErr := objectAPI.DeleteObject(bucket, obj.ObjectName) | 
					
						
							| 
									
										
										
										
											2016-09-02 16:59:08 +08:00
										 |  |  | 			if dErr != nil { | 
					
						
							|  |  |  | 				dErrs[i] = dErr | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}(index, object) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	wg.Wait() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Collect deleted objects and errors if any.
 | 
					
						
							| 
									
										
										
										
											2016-03-06 08:43:48 +08:00
										 |  |  | 	var deletedObjects []ObjectIdentifier | 
					
						
							| 
									
										
										
										
											2016-09-02 16:59:08 +08:00
										 |  |  | 	var deleteErrors []DeleteError | 
					
						
							|  |  |  | 	for index, err := range dErrs { | 
					
						
							|  |  |  | 		object := deleteObjects.Objects[index] | 
					
						
							|  |  |  | 		// Success deleted objects are collected separately.
 | 
					
						
							| 
									
										
										
										
											2016-03-06 08:43:48 +08:00
										 |  |  | 		if err == nil { | 
					
						
							| 
									
										
										
										
											2016-09-02 16:59:08 +08:00
										 |  |  | 			deletedObjects = append(deletedObjects, object) | 
					
						
							|  |  |  | 			continue | 
					
						
							| 
									
										
										
										
											2016-03-06 08:43:48 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-09-10 06:32:08 +08:00
										 |  |  | 		if _, ok := errorCause(err).(ObjectNotFound); ok { | 
					
						
							| 
									
										
										
										
											2016-09-08 02:49:12 +08:00
										 |  |  | 			// If the object is not found it should be
 | 
					
						
							|  |  |  | 			// accounted as deleted as per S3 spec.
 | 
					
						
							|  |  |  | 			deletedObjects = append(deletedObjects, object) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-09-02 16:59:08 +08:00
										 |  |  | 		errorIf(err, "Unable to delete object. %s", object.ObjectName) | 
					
						
							|  |  |  | 		// Error during delete should be collected separately.
 | 
					
						
							|  |  |  | 		deleteErrors = append(deleteErrors, DeleteError{ | 
					
						
							|  |  |  | 			Code:    errorCodeResponse[toAPIErrorCode(err)].Code, | 
					
						
							|  |  |  | 			Message: errorCodeResponse[toAPIErrorCode(err)].Description, | 
					
						
							|  |  |  | 			Key:     object.ObjectName, | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2016-03-06 08:43:48 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-09-02 16:59:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 08:43:48 +08:00
										 |  |  | 	// Generate response
 | 
					
						
							|  |  |  | 	response := generateMultiDeleteResponse(deleteObjects.Quiet, deletedObjects, deleteErrors) | 
					
						
							|  |  |  | 	encodedSuccessResponse := encodeResponse(response) | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 08:43:48 +08:00
										 |  |  | 	// Write success response.
 | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 	writeSuccessResponseXML(w, encodedSuccessResponse) | 
					
						
							| 
									
										
										
										
											2016-09-02 16:59:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-29 13:46:19 +08:00
										 |  |  | 	// Notify deleted event for objects.
 | 
					
						
							|  |  |  | 	for _, dobj := range deletedObjects { | 
					
						
							|  |  |  | 		eventNotify(eventData{ | 
					
						
							|  |  |  | 			Type:   ObjectRemovedDelete, | 
					
						
							|  |  |  | 			Bucket: bucket, | 
					
						
							|  |  |  | 			ObjInfo: ObjectInfo{ | 
					
						
							|  |  |  | 				Name: dobj.ObjectName, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			ReqParams: map[string]string{ | 
					
						
							|  |  |  | 				"sourceIPAddress": r.RemoteAddr, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2016-09-02 16:59:08 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-06 08:43:48 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-01 11:15:48 +08:00
										 |  |  | // PutBucketHandler - PUT Bucket
 | 
					
						
							| 
									
										
										
										
											2015-07-01 05:42:29 +08:00
										 |  |  | // ----------
 | 
					
						
							|  |  |  | // This implementation of the PUT operation creates a new bucket for authenticated request
 | 
					
						
							| 
									
										
										
										
											2016-04-13 03:45:15 +08:00
										 |  |  | func (api objectAPIHandlers) PutBucketHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							| 
									
										
										
										
											2016-08-11 09:47:49 +08:00
										 |  |  | 	objectAPI := api.ObjectAPI() | 
					
						
							|  |  |  | 	if objectAPI == nil { | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, ErrServerNotInitialized, r.URL) | 
					
						
							| 
									
										
										
										
											2016-08-11 09:47:49 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-22 05:51:05 +08:00
										 |  |  | 	// PutBucket does not have any bucket action.
 | 
					
						
							| 
									
										
										
										
											2017-01-20 03:31:51 +08:00
										 |  |  | 	s3Error := checkRequestAuthType(r, "", "", globalMinioDefaultRegion) | 
					
						
							|  |  |  | 	if s3Error == ErrInvalidRegion { | 
					
						
							|  |  |  | 		// Clients like boto3 send putBucket() call signed with region that is configured.
 | 
					
						
							|  |  |  | 		s3Error = checkRequestAuthType(r, "", "", serverConfig.GetRegion()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if s3Error != ErrNone { | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, s3Error, r.URL) | 
					
						
							| 
									
										
										
										
											2016-02-05 04:52:25 +08:00
										 |  |  | 		return | 
					
						
							| 
									
										
										
										
											2015-07-15 00:17:30 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-19 14:56:27 +08:00
										 |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	bucket := vars["bucket"] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-19 12:20:17 +08:00
										 |  |  | 	// Validate if incoming location constraint is valid, reject
 | 
					
						
							|  |  |  | 	// requests which do not follow valid region requirements.
 | 
					
						
							| 
									
										
										
										
											2016-07-19 14:56:27 +08:00
										 |  |  | 	if s3Error := isValidLocationConstraint(r); s3Error != ErrNone { | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, s3Error, r.URL) | 
					
						
							| 
									
										
										
										
											2016-08-26 11:00:47 +08:00
										 |  |  | 		return | 
					
						
							| 
									
										
										
										
											2016-04-21 08:35:38 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-11 08:15:12 +08:00
										 |  |  | 	bucketLock := globalNSMutex.NewNSLock(bucket, "") | 
					
						
							|  |  |  | 	bucketLock.Lock() | 
					
						
							|  |  |  | 	defer bucketLock.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | 	// Proceed to creating a bucket.
 | 
					
						
							| 
									
										
										
										
											2016-08-01 05:11:14 +08:00
										 |  |  | 	err := objectAPI.MakeBucket(bucket) | 
					
						
							| 
									
										
										
										
											2015-09-19 18:20:07 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2016-05-17 05:31:28 +08:00
										 |  |  | 		errorIf(err, "Unable to create a bucket.") | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, toAPIErrorCode(err), r.URL) | 
					
						
							| 
									
										
										
										
											2015-08-04 07:17:21 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-19 18:20:07 +08:00
										 |  |  | 	// Make sure to add Location information here only for bucket
 | 
					
						
							| 
									
										
										
										
											2016-03-02 12:01:40 +08:00
										 |  |  | 	w.Header().Set("Location", getLocation(r)) | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	writeSuccessResponseHeadersOnly(w) | 
					
						
							| 
									
										
										
										
											2015-07-01 05:42:29 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-02 14:51:17 +08:00
										 |  |  | // PostPolicyBucketHandler - POST policy
 | 
					
						
							|  |  |  | // ----------
 | 
					
						
							|  |  |  | // This implementation of the POST operation handles object creation with a specified
 | 
					
						
							|  |  |  | // signature policy in multipart/form-data
 | 
					
						
							| 
									
										
										
										
											2016-04-13 03:45:15 +08:00
										 |  |  | func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							| 
									
										
										
										
											2016-08-11 09:47:49 +08:00
										 |  |  | 	objectAPI := api.ObjectAPI() | 
					
						
							|  |  |  | 	if objectAPI == nil { | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, ErrServerNotInitialized, r.URL) | 
					
						
							| 
									
										
										
										
											2016-08-11 09:47:49 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-02 14:51:17 +08:00
										 |  |  | 	// Here the parameter is the size of the form data that should
 | 
					
						
							| 
									
										
										
										
											2016-03-23 08:54:31 +08:00
										 |  |  | 	// be loaded in memory, the remaining being put in temporary files.
 | 
					
						
							| 
									
										
										
										
											2016-04-30 05:24:10 +08:00
										 |  |  | 	reader, err := r.MultipartReader() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2016-05-17 05:31:28 +08:00
										 |  |  | 		errorIf(err, "Unable to initialize multipart reader.") | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, ErrMalformedPOSTRequest, r.URL) | 
					
						
							| 
									
										
										
										
											2015-10-02 14:51:17 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-29 03:02:22 +08:00
										 |  |  | 	fileBody, fileName, formValues, err := extractPostPolicyFormValues(reader) | 
					
						
							| 
									
										
										
										
											2016-02-05 04:52:25 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2016-05-17 05:31:28 +08:00
										 |  |  | 		errorIf(err, "Unable to parse form values.") | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, ErrMalformedPOSTRequest, r.URL) | 
					
						
							| 
									
										
										
										
											2015-10-02 14:51:17 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-02-16 09:42:39 +08:00
										 |  |  | 	bucket := mux.Vars(r)["bucket"] | 
					
						
							| 
									
										
										
										
											2015-10-02 14:51:17 +08:00
										 |  |  | 	formValues["Bucket"] = bucket | 
					
						
							| 
									
										
										
										
											2016-02-16 09:42:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-05 02:30:52 +08:00
										 |  |  | 	if fileName != "" && strings.Contains(formValues["Key"], "${filename}") { | 
					
						
							| 
									
										
										
										
											2016-07-28 08:51:55 +08:00
										 |  |  | 		// S3 feature to replace ${filename} found in Key form field
 | 
					
						
							|  |  |  | 		// by the filename attribute passed in multipart
 | 
					
						
							| 
									
										
										
										
											2016-12-05 02:30:52 +08:00
										 |  |  | 		formValues["Key"] = strings.Replace(formValues["Key"], "${filename}", fileName, -1) | 
					
						
							| 
									
										
										
										
											2016-07-28 08:51:55 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-12-05 02:30:52 +08:00
										 |  |  | 	object := formValues["Key"] | 
					
						
							| 
									
										
										
										
											2016-07-28 08:51:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-16 09:42:39 +08:00
										 |  |  | 	// Verify policy signature.
 | 
					
						
							| 
									
										
										
										
											2016-03-31 11:04:51 +08:00
										 |  |  | 	apiErr := doesPolicySignatureMatch(formValues) | 
					
						
							|  |  |  | 	if apiErr != ErrNone { | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, apiErr, r.URL) | 
					
						
							| 
									
										
										
										
											2015-10-02 14:51:17 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-10-25 14:47:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	policyBytes, err := base64.StdEncoding.DecodeString(formValues["Policy"]) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, ErrMalformedPOSTRequest, r.URL) | 
					
						
							| 
									
										
										
										
											2016-10-25 14:47:03 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-27 01:15:57 +08:00
										 |  |  | 	postPolicyForm, err := parsePostPolicyForm(string(policyBytes)) | 
					
						
							| 
									
										
										
										
											2016-10-25 14:47:03 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, ErrMalformedPOSTRequest, r.URL) | 
					
						
							| 
									
										
										
										
											2016-10-25 14:47:03 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Make sure formValues adhere to policy restrictions.
 | 
					
						
							|  |  |  | 	if apiErr = checkPostPolicy(formValues, postPolicyForm); apiErr != ErrNone { | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, apiErr, r.URL) | 
					
						
							| 
									
										
										
										
											2015-10-07 01:12:06 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-05-20 08:10:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-21 20:15:26 +08:00
										 |  |  | 	// Use rangeReader to ensure that object size is within expected range.
 | 
					
						
							| 
									
										
										
										
											2016-10-25 14:47:03 +08:00
										 |  |  | 	lengthRange := postPolicyForm.Conditions.ContentLengthRange | 
					
						
							|  |  |  | 	if lengthRange.Valid { | 
					
						
							|  |  |  | 		// If policy restricted the size of the object.
 | 
					
						
							| 
									
										
										
										
											2016-11-21 20:15:26 +08:00
										 |  |  | 		fileBody = &rangeReader{ | 
					
						
							|  |  |  | 			Reader: fileBody, | 
					
						
							|  |  |  | 			Min:    lengthRange.Min, | 
					
						
							|  |  |  | 			Max:    lengthRange.Max, | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-10-25 14:47:03 +08:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		// Default values of min/max size of the object.
 | 
					
						
							| 
									
										
										
										
											2016-11-21 20:15:26 +08:00
										 |  |  | 		fileBody = &rangeReader{ | 
					
						
							|  |  |  | 			Reader: fileBody, | 
					
						
							|  |  |  | 			Min:    0, | 
					
						
							|  |  |  | 			Max:    maxObjectSize, | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-10-25 14:47:03 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-20 08:14:04 +08:00
										 |  |  | 	// Extract metadata to be saved from received Form.
 | 
					
						
							|  |  |  | 	metadata := extractMetadataFromForm(formValues) | 
					
						
							| 
									
										
										
										
											2016-05-20 08:10:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-03 06:51:49 +08:00
										 |  |  | 	sha256sum := "" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-11 08:15:12 +08:00
										 |  |  | 	objectLock := globalNSMutex.NewNSLock(bucket, object) | 
					
						
							|  |  |  | 	objectLock.Lock() | 
					
						
							|  |  |  | 	defer objectLock.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-03 06:51:49 +08:00
										 |  |  | 	objInfo, err := objectAPI.PutObject(bucket, object, -1, fileBody, metadata, sha256sum) | 
					
						
							| 
									
										
										
										
											2016-02-05 04:52:25 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2016-05-17 05:31:28 +08:00
										 |  |  | 		errorIf(err, "Unable to create object.") | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, toAPIErrorCode(err), r.URL) | 
					
						
							| 
									
										
										
										
											2015-10-02 14:51:17 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-09-03 03:18:35 +08:00
										 |  |  | 	w.Header().Set("ETag", "\""+objInfo.MD5Sum+"\"") | 
					
						
							| 
									
										
										
										
											2016-09-06 17:18:02 +08:00
										 |  |  | 	w.Header().Set("Location", getObjectLocation(bucket, object)) | 
					
						
							| 
									
										
										
										
											2016-08-05 13:01:58 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-21 01:32:17 +08:00
										 |  |  | 	successRedirect := formValues[http.CanonicalHeaderKey("success_action_redirect")] | 
					
						
							|  |  |  | 	successStatus := formValues[http.CanonicalHeaderKey("success_action_status")] | 
					
						
							| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-21 01:32:17 +08:00
										 |  |  | 	if successStatus == "" && successRedirect == "" { | 
					
						
							| 
									
										
										
										
											2016-12-19 05:39:56 +08:00
										 |  |  | 		writeSuccessNoContent(w) | 
					
						
							| 
									
										
										
										
											2016-12-21 01:32:17 +08:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		if successRedirect != "" { | 
					
						
							|  |  |  | 			redirectURL := successRedirect + "?" + fmt.Sprintf("bucket=%s&key=%s&etag=%s", | 
					
						
							|  |  |  | 				bucket, | 
					
						
							|  |  |  | 				getURLEncodedName(object), | 
					
						
							|  |  |  | 				getURLEncodedName("\""+objInfo.MD5Sum+"\"")) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			writeRedirectSeeOther(w, redirectURL) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			// Decide what http response to send depending on success_action_status parameter
 | 
					
						
							|  |  |  | 			switch successStatus { | 
					
						
							|  |  |  | 			case "201": | 
					
						
							|  |  |  | 				resp := encodeResponse(PostResponse{ | 
					
						
							|  |  |  | 					Bucket:   bucket, | 
					
						
							|  |  |  | 					Key:      object, | 
					
						
							|  |  |  | 					ETag:     "\"" + objInfo.MD5Sum + "\"", | 
					
						
							|  |  |  | 					Location: getObjectLocation(bucket, object), | 
					
						
							|  |  |  | 				}) | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 				writeResponse(w, http.StatusCreated, resp, "application/xml") | 
					
						
							| 
									
										
										
										
											2016-12-21 01:32:17 +08:00
										 |  |  | 			case "200": | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 				writeSuccessResponseHeadersOnly(w) | 
					
						
							| 
									
										
										
										
											2016-12-21 01:32:17 +08:00
										 |  |  | 			default: | 
					
						
							|  |  |  | 				writeSuccessNoContent(w) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-12-19 05:39:56 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-29 13:46:19 +08:00
										 |  |  | 	// Notify object created event.
 | 
					
						
							|  |  |  | 	eventNotify(eventData{ | 
					
						
							|  |  |  | 		Type:    ObjectCreatedPost, | 
					
						
							|  |  |  | 		Bucket:  bucket, | 
					
						
							|  |  |  | 		ObjInfo: objInfo, | 
					
						
							|  |  |  | 		ReqParams: map[string]string{ | 
					
						
							|  |  |  | 			"sourceIPAddress": r.RemoteAddr, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2015-10-02 14:51:17 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-01 11:15:48 +08:00
										 |  |  | // HeadBucketHandler - HEAD Bucket
 | 
					
						
							| 
									
										
										
										
											2015-07-01 05:42:29 +08:00
										 |  |  | // ----------
 | 
					
						
							|  |  |  | // This operation is useful to determine if a bucket exists.
 | 
					
						
							|  |  |  | // The operation returns a 200 OK if the bucket exists and you
 | 
					
						
							|  |  |  | // have permission to access it. Otherwise, the operation might
 | 
					
						
							|  |  |  | // return responses such as 404 Not Found and 403 Forbidden.
 | 
					
						
							| 
									
										
										
										
											2016-04-13 03:45:15 +08:00
										 |  |  | func (api objectAPIHandlers) HeadBucketHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							| 
									
										
										
										
											2016-02-16 09:42:39 +08:00
										 |  |  | 	vars := mux.Vars(r) | 
					
						
							| 
									
										
										
										
											2015-07-01 05:42:29 +08:00
										 |  |  | 	bucket := vars["bucket"] | 
					
						
							| 
									
										
										
										
											2015-07-03 11:31:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-11 09:47:49 +08:00
										 |  |  | 	objectAPI := api.ObjectAPI() | 
					
						
							|  |  |  | 	if objectAPI == nil { | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponseHeadersOnly(w, ErrServerNotInitialized) | 
					
						
							| 
									
										
										
										
											2016-08-11 09:47:49 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-11-22 05:51:05 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if s3Error := checkRequestAuthType(r, bucket, "s3:ListBucket", serverConfig.GetRegion()); s3Error != ErrNone { | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponseHeadersOnly(w, s3Error) | 
					
						
							| 
									
										
										
											
												accessPolicy: Implement Put, Get, Delete access policy.
This patch implements Get,Put,Delete bucket policies
Supporting - http://docs.aws.amazon.com/AmazonS3/latest/dev/access-policy-language-overview.html
Currently supports following actions.
   "*":                             true,
   "s3:*":                          true,
   "s3:GetObject":                  true,
   "s3:ListBucket":                 true,
   "s3:PutObject":                  true,
   "s3:CreateBucket":               true,
   "s3:GetBucketLocation":          true,
   "s3:DeleteBucket":               true,
   "s3:DeleteObject":               true,
   "s3:AbortMultipartUpload":       true,
   "s3:ListBucketMultipartUploads": true,
   "s3:ListMultipartUploadParts":   true,
following conditions for "StringEquals" and "StringNotEquals"
   "s3:prefix", "s3:max-keys"
											
										 
											2016-02-04 08:46:56 +08:00
										 |  |  | 		return | 
					
						
							| 
									
										
										
										
											2016-02-05 04:52:25 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-11 08:15:12 +08:00
										 |  |  | 	bucketLock := globalNSMutex.NewNSLock(bucket, "") | 
					
						
							|  |  |  | 	bucketLock.RLock() | 
					
						
							|  |  |  | 	defer bucketLock.RUnlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-01 05:11:14 +08:00
										 |  |  | 	if _, err := objectAPI.GetBucketInfo(bucket); err != nil { | 
					
						
							| 
									
										
										
										
											2016-05-17 05:31:28 +08:00
										 |  |  | 		errorIf(err, "Unable to fetch bucket info.") | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponseHeadersOnly(w, toAPIErrorCode(err)) | 
					
						
							| 
									
										
										
										
											2015-08-04 07:17:21 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	writeSuccessResponseHeadersOnly(w) | 
					
						
							| 
									
										
										
										
											2015-07-01 05:42:29 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-10-17 02:26:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // DeleteBucketHandler - Delete bucket
 | 
					
						
							| 
									
										
										
										
											2016-04-13 03:45:15 +08:00
										 |  |  | func (api objectAPIHandlers) DeleteBucketHandler(w http.ResponseWriter, r *http.Request) { | 
					
						
							| 
									
										
										
										
											2016-08-11 09:47:49 +08:00
										 |  |  | 	objectAPI := api.ObjectAPI() | 
					
						
							|  |  |  | 	if objectAPI == nil { | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, ErrServerNotInitialized, r.URL) | 
					
						
							| 
									
										
										
										
											2016-08-11 09:47:49 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-22 05:51:05 +08:00
										 |  |  | 	// DeleteBucket does not have any bucket action.
 | 
					
						
							|  |  |  | 	if s3Error := checkRequestAuthType(r, "", "", serverConfig.GetRegion()); s3Error != ErrNone { | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, s3Error, r.URL) | 
					
						
							| 
									
										
										
										
											2016-02-16 09:42:39 +08:00
										 |  |  | 		return | 
					
						
							| 
									
										
										
										
											2016-02-05 04:52:25 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-19 14:56:27 +08:00
										 |  |  | 	vars := mux.Vars(r) | 
					
						
							|  |  |  | 	bucket := vars["bucket"] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-11 08:15:12 +08:00
										 |  |  | 	bucketLock := globalNSMutex.NewNSLock(bucket, "") | 
					
						
							|  |  |  | 	bucketLock.Lock() | 
					
						
							|  |  |  | 	defer bucketLock.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | 	// Attempt to delete bucket.
 | 
					
						
							| 
									
										
										
										
											2016-08-01 05:11:14 +08:00
										 |  |  | 	if err := objectAPI.DeleteBucket(bucket); err != nil { | 
					
						
							| 
									
										
										
										
											2016-05-17 05:31:28 +08:00
										 |  |  | 		errorIf(err, "Unable to delete a bucket.") | 
					
						
							| 
									
										
										
										
											2017-01-06 16:37:00 +08:00
										 |  |  | 		writeErrorResponse(w, toAPIErrorCode(err), r.URL) | 
					
						
							| 
									
										
										
										
											2015-10-17 02:26:01 +08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
											
												accessPolicy: Implement Put, Get, Delete access policy.
This patch implements Get,Put,Delete bucket policies
Supporting - http://docs.aws.amazon.com/AmazonS3/latest/dev/access-policy-language-overview.html
Currently supports following actions.
   "*":                             true,
   "s3:*":                          true,
   "s3:GetObject":                  true,
   "s3:ListBucket":                 true,
   "s3:PutObject":                  true,
   "s3:CreateBucket":               true,
   "s3:GetBucketLocation":          true,
   "s3:DeleteBucket":               true,
   "s3:DeleteObject":               true,
   "s3:AbortMultipartUpload":       true,
   "s3:ListBucketMultipartUploads": true,
   "s3:ListMultipartUploadParts":   true,
following conditions for "StringEquals" and "StringNotEquals"
   "s3:prefix", "s3:max-keys"
											
										 
											2016-02-04 08:46:56 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Delete bucket access policy, if present - ignore any errors.
 | 
					
						
							| 
									
										
										
										
											2016-10-21 07:09:19 +08:00
										 |  |  | 	_ = removeBucketPolicy(bucket, objectAPI) | 
					
						
							| 
									
										
										
										
											2016-08-10 02:33:45 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Delete notification config, if present - ignore any errors.
 | 
					
						
							| 
									
										
										
										
											2016-10-21 07:09:19 +08:00
										 |  |  | 	_ = removeNotificationConfig(bucket, objectAPI) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Delete listener config, if present - ignore any errors.
 | 
					
						
							|  |  |  | 	_ = removeListenerConfig(bucket, objectAPI) | 
					
						
							| 
									
										
										
											
												accessPolicy: Implement Put, Get, Delete access policy.
This patch implements Get,Put,Delete bucket policies
Supporting - http://docs.aws.amazon.com/AmazonS3/latest/dev/access-policy-language-overview.html
Currently supports following actions.
   "*":                             true,
   "s3:*":                          true,
   "s3:GetObject":                  true,
   "s3:ListBucket":                 true,
   "s3:PutObject":                  true,
   "s3:CreateBucket":               true,
   "s3:GetBucketLocation":          true,
   "s3:DeleteBucket":               true,
   "s3:DeleteObject":               true,
   "s3:AbortMultipartUpload":       true,
   "s3:ListBucketMultipartUploads": true,
   "s3:ListMultipartUploadParts":   true,
following conditions for "StringEquals" and "StringNotEquals"
   "s3:prefix", "s3:max-keys"
											
										 
											2016-02-04 08:46:56 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Write success response.
 | 
					
						
							| 
									
										
										
										
											2015-10-17 11:02:37 +08:00
										 |  |  | 	writeSuccessNoContent(w) | 
					
						
							| 
									
										
										
										
											2015-10-17 02:26:01 +08:00
										 |  |  | } |