| 
									
										
										
										
											2015-02-24 08:46:48 +08:00
										 |  |  | /* | 
					
						
							| 
									
										
										
										
											2015-03-20 05:35:50 +08:00
										 |  |  |  * Minimalist Object Storage, (C) 2015 Minio, Inc. | 
					
						
							| 
									
										
										
										
											2015-02-24 08:46:48 +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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-19 08:49:33 +08:00
										 |  |  | package api | 
					
						
							| 
									
										
										
										
											2015-02-16 09:03:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2015-04-23 07:28:13 +08:00
										 |  |  | 	"net/http" | 
					
						
							| 
									
										
										
										
											2015-02-28 09:50:55 +08:00
										 |  |  | 	"sort" | 
					
						
							| 
									
										
										
										
											2015-04-30 06:28:04 +08:00
										 |  |  | 	"strconv" | 
					
						
							| 
									
										
										
										
											2015-02-28 09:50:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-09 07:28:14 +08:00
										 |  |  | 	"github.com/minio-io/minio/pkg/storage/drivers" | 
					
						
							| 
									
										
										
										
											2015-02-16 09:03:27 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-24 08:46:48 +08:00
										 |  |  | // Reply date format
 | 
					
						
							|  |  |  | const ( | 
					
						
							| 
									
										
										
										
											2015-03-10 16:44:55 +08:00
										 |  |  | 	iso8601Format = "2006-01-02T15:04:05.000Z" | 
					
						
							| 
									
										
										
										
											2015-02-24 08:46:48 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // takes an array of Bucketmetadata information for serialization
 | 
					
						
							|  |  |  | // input:
 | 
					
						
							|  |  |  | // array of bucket metadata
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // output:
 | 
					
						
							|  |  |  | // populated struct that can be serialized to match xml and json api spec output
 | 
					
						
							| 
									
										
										
										
											2015-04-30 06:28:04 +08:00
										 |  |  | func generateListBucketsResponse(buckets []drivers.BucketMetadata) ListBucketsResponse { | 
					
						
							| 
									
										
										
										
											2015-02-16 09:03:27 +08:00
										 |  |  | 	var listbuckets []*Bucket | 
					
						
							| 
									
										
										
										
											2015-04-30 06:28:04 +08:00
										 |  |  | 	var data = ListBucketsResponse{} | 
					
						
							| 
									
										
										
										
											2015-02-16 09:03:27 +08:00
										 |  |  | 	var owner = Owner{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	owner.ID = "minio" | 
					
						
							|  |  |  | 	owner.DisplayName = "minio" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, bucket := range buckets { | 
					
						
							|  |  |  | 		var listbucket = &Bucket{} | 
					
						
							|  |  |  | 		listbucket.Name = bucket.Name | 
					
						
							| 
									
										
										
										
											2015-03-10 16:44:55 +08:00
										 |  |  | 		listbucket.CreationDate = bucket.Created.Format(iso8601Format) | 
					
						
							| 
									
										
										
										
											2015-02-16 09:03:27 +08:00
										 |  |  | 		listbuckets = append(listbuckets, listbucket) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	data.Owner = owner | 
					
						
							|  |  |  | 	data.Buckets.Bucket = listbuckets | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return data | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-02 10:58:46 +08:00
										 |  |  | // itemKey
 | 
					
						
							| 
									
										
										
										
											2015-05-06 05:27:18 +08:00
										 |  |  | type itemKey []*Object | 
					
						
							| 
									
										
										
										
											2015-02-28 09:50:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-02 10:58:46 +08:00
										 |  |  | func (b itemKey) Len() int           { return len(b) } | 
					
						
							|  |  |  | func (b itemKey) Swap(i, j int)      { b[i], b[j] = b[j], b[i] } | 
					
						
							| 
									
										
										
										
											2015-03-06 13:07:19 +08:00
										 |  |  | func (b itemKey) Less(i, j int) bool { return b[i].Key < b[j].Key } | 
					
						
							| 
									
										
										
										
											2015-02-28 09:50:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-16 09:03:27 +08:00
										 |  |  | // takes a set of objects and prepares the objects for serialization
 | 
					
						
							|  |  |  | // input:
 | 
					
						
							|  |  |  | // bucket name
 | 
					
						
							|  |  |  | // array of object metadata
 | 
					
						
							|  |  |  | // results truncated flag
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // output:
 | 
					
						
							|  |  |  | // populated struct that can be serialized to match xml and json api spec output
 | 
					
						
							| 
									
										
										
										
											2015-04-30 06:28:04 +08:00
										 |  |  | func generateListObjectsResponse(bucket string, objects []drivers.ObjectMetadata, bucketResources drivers.BucketResourcesMetadata) ListObjectsResponse { | 
					
						
							| 
									
										
										
										
											2015-05-06 05:27:18 +08:00
										 |  |  | 	var contents []*Object | 
					
						
							|  |  |  | 	var prefixes []*CommonPrefix | 
					
						
							| 
									
										
										
										
											2015-02-16 09:03:27 +08:00
										 |  |  | 	var owner = Owner{} | 
					
						
							| 
									
										
										
										
											2015-04-30 06:28:04 +08:00
										 |  |  | 	var data = ListObjectsResponse{} | 
					
						
							| 
									
										
										
										
											2015-02-16 09:03:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	owner.ID = "minio" | 
					
						
							|  |  |  | 	owner.DisplayName = "minio" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, object := range objects { | 
					
						
							| 
									
										
										
										
											2015-05-06 05:27:18 +08:00
										 |  |  | 		var content = &Object{} | 
					
						
							| 
									
										
										
										
											2015-03-01 06:44:26 +08:00
										 |  |  | 		if object.Key == "" { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-02-16 09:03:27 +08:00
										 |  |  | 		content.Key = object.Key | 
					
						
							| 
									
										
										
										
											2015-03-10 16:44:55 +08:00
										 |  |  | 		content.LastModified = object.Created.Format(iso8601Format) | 
					
						
							| 
									
										
										
										
											2015-03-17 09:38:42 +08:00
										 |  |  | 		content.ETag = object.Md5 | 
					
						
							| 
									
										
										
										
											2015-02-16 09:03:27 +08:00
										 |  |  | 		content.Size = object.Size | 
					
						
							|  |  |  | 		content.StorageClass = "STANDARD" | 
					
						
							|  |  |  | 		content.Owner = owner | 
					
						
							|  |  |  | 		contents = append(contents, content) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-03-06 13:07:19 +08:00
										 |  |  | 	sort.Sort(itemKey(contents)) | 
					
						
							| 
									
										
										
										
											2015-05-06 05:27:18 +08:00
										 |  |  | 	// TODO - support EncodingType in xml decoding
 | 
					
						
							| 
									
										
										
										
											2015-02-16 09:03:27 +08:00
										 |  |  | 	data.Name = bucket | 
					
						
							|  |  |  | 	data.Contents = contents | 
					
						
							| 
									
										
										
										
											2015-03-01 06:44:26 +08:00
										 |  |  | 	data.MaxKeys = bucketResources.Maxkeys | 
					
						
							|  |  |  | 	data.Prefix = bucketResources.Prefix | 
					
						
							|  |  |  | 	data.Delimiter = bucketResources.Delimiter | 
					
						
							|  |  |  | 	data.Marker = bucketResources.Marker | 
					
						
							| 
									
										
										
										
											2015-05-06 05:27:18 +08:00
										 |  |  | 	data.NextMarker = bucketResources.NextMarker | 
					
						
							| 
									
										
										
										
											2015-03-01 06:44:26 +08:00
										 |  |  | 	data.IsTruncated = bucketResources.IsTruncated | 
					
						
							|  |  |  | 	for _, prefix := range bucketResources.CommonPrefixes { | 
					
						
							| 
									
										
										
										
											2015-05-06 05:27:18 +08:00
										 |  |  | 		var prefixItem = &CommonPrefix{} | 
					
						
							| 
									
										
										
										
											2015-03-01 06:44:26 +08:00
										 |  |  | 		prefixItem.Prefix = prefix | 
					
						
							|  |  |  | 		prefixes = append(prefixes, prefixItem) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	data.CommonPrefixes = prefixes | 
					
						
							| 
									
										
										
										
											2015-02-16 09:03:27 +08:00
										 |  |  | 	return data | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-04-23 07:28:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-30 01:51:59 +08:00
										 |  |  | // writeSuccessResponse - write success headers
 | 
					
						
							| 
									
										
										
										
											2015-04-30 06:28:04 +08:00
										 |  |  | func writeSuccessResponse(w http.ResponseWriter, acceptsContentType contentType) { | 
					
						
							|  |  |  | 	setCommonHeaders(w, getContentTypeString(acceptsContentType)) | 
					
						
							| 
									
										
										
										
											2015-04-30 01:51:59 +08:00
										 |  |  | 	w.WriteHeader(http.StatusOK) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // writeErrorRespone - write error headers
 | 
					
						
							| 
									
										
										
										
											2015-04-27 08:02:49 +08:00
										 |  |  | func writeErrorResponse(w http.ResponseWriter, req *http.Request, errorType int, acceptsContentType contentType, resource string) { | 
					
						
							| 
									
										
										
										
											2015-04-23 07:28:13 +08:00
										 |  |  | 	error := getErrorCode(errorType) | 
					
						
							| 
									
										
										
										
											2015-04-30 06:28:04 +08:00
										 |  |  | 	// generate error response
 | 
					
						
							| 
									
										
										
										
											2015-04-23 07:28:13 +08:00
										 |  |  | 	errorResponse := getErrorResponse(error, resource) | 
					
						
							| 
									
										
										
										
											2015-04-30 06:28:04 +08:00
										 |  |  | 	encodedErrorResponse := encodeErrorResponse(errorResponse, acceptsContentType) | 
					
						
							|  |  |  | 	// set common headers
 | 
					
						
							| 
									
										
										
										
											2015-04-23 07:28:13 +08:00
										 |  |  | 	setCommonHeaders(w, getContentTypeString(acceptsContentType)) | 
					
						
							| 
									
										
										
										
											2015-04-30 06:28:04 +08:00
										 |  |  | 	// set content-length to size of error response
 | 
					
						
							|  |  |  | 	w.Header().Set("Content-Length", strconv.Itoa(len(encodedErrorResponse))) | 
					
						
							|  |  |  | 	// set headers
 | 
					
						
							| 
									
										
										
										
											2015-04-23 07:28:13 +08:00
										 |  |  | 	w.WriteHeader(error.HTTPStatusCode) | 
					
						
							|  |  |  | 	// write body
 | 
					
						
							|  |  |  | 	w.Write(encodedErrorResponse) | 
					
						
							|  |  |  | } |