From b7868d23ac8aad675b8e3fe417c7f53da0a5ede3 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Mon, 23 Feb 2015 16:46:48 -0800 Subject: [PATCH] Update minioapi documentation --- pkg/api/minioapi/bucket_handlers.go | 29 ++++++++++++++++++++++++++++ pkg/api/minioapi/contenttype.go | 5 +++++ pkg/api/minioapi/definitions.go | 7 +++++++ pkg/api/minioapi/error_response.go | 10 +++++++--- pkg/api/minioapi/generic_handlers.go | 23 +++++++++++++++------- pkg/api/minioapi/headers.go | 12 ++++++++---- pkg/api/minioapi/muxer.go | 9 +++++---- pkg/api/minioapi/object_handlers.go | 26 +++++++++++++++++++++++++ pkg/api/minioapi/policy_handlers.go | 24 +++++++++++++++++++++++ pkg/api/minioapi/resources.go | 18 +++++++++++++++++ pkg/api/minioapi/response.go | 27 ++++++++++++++++++++++++++ 11 files changed, 172 insertions(+), 18 deletions(-) diff --git a/pkg/api/minioapi/bucket_handlers.go b/pkg/api/minioapi/bucket_handlers.go index 00a625eae..8d73536a6 100644 --- a/pkg/api/minioapi/bucket_handlers.go +++ b/pkg/api/minioapi/bucket_handlers.go @@ -1,3 +1,19 @@ +/* + * Mini Object Storage, (C) 2015 Minio, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package minioapi import ( @@ -8,6 +24,12 @@ import ( mstorage "github.com/minio-io/minio/pkg/storage" ) +// GET Bucket (List Objects) +// ------------------------- +// This implementation of the GET operation returns some or all (up to 1000) +// of the objects in a bucket. You can use the request parameters as selection +// criteria to return a subset of the objects in a bucket. +// func (server *minioApi) listObjectsHandler(w http.ResponseWriter, req *http.Request) { vars := mux.Vars(req) bucket := vars["bucket"] @@ -59,6 +81,10 @@ func (server *minioApi) listObjectsHandler(w http.ResponseWriter, req *http.Requ } } +// GET Service +// ----------- +// This implementation of the GET operation returns a list of all buckets +// owned by the authenticated sender of the request. func (server *minioApi) listBucketsHandler(w http.ResponseWriter, req *http.Request) { acceptsContentType := getContentType(req) buckets, err := server.storage.ListBuckets() @@ -87,6 +113,9 @@ func (server *minioApi) listBucketsHandler(w http.ResponseWriter, req *http.Requ } } +// PUT Bucket +// ---------- +// This implementation of the PUT operation creates a new bucket for authenticated request func (server *minioApi) putBucketHandler(w http.ResponseWriter, req *http.Request) { vars := mux.Vars(req) bucket := vars["bucket"] diff --git a/pkg/api/minioapi/contenttype.go b/pkg/api/minioapi/contenttype.go index 075f1b4aa..efe0c1897 100644 --- a/pkg/api/minioapi/contenttype.go +++ b/pkg/api/minioapi/contenttype.go @@ -27,15 +27,19 @@ const ( jsonType ) +// content-type to human readable map var typeToString = map[contentType]string{ xmlType: "application/xml", jsonType: "application/json", } + +// human readbale to content-type map var acceptToType = map[string]contentType{ "application/xml": xmlType, "application/json": jsonType, } +// Get content type requested from 'Accept' header func getContentType(req *http.Request) contentType { if accept := req.Header.Get("Accept"); accept != "" { return acceptToType[accept] @@ -43,6 +47,7 @@ func getContentType(req *http.Request) contentType { return xmlType } +// Content type to human readable string func getContentString(content contentType) string { return typeToString[content] } diff --git a/pkg/api/minioapi/definitions.go b/pkg/api/minioapi/definitions.go index 28f17598d..cca9a8687 100644 --- a/pkg/api/minioapi/definitions.go +++ b/pkg/api/minioapi/definitions.go @@ -20,10 +20,12 @@ import ( "encoding/xml" ) +// Limit number of objects in a given response const ( MAX_OBJECT_LIST = 1000 ) +// Object list response format type ObjectListResponse struct { XMLName xml.Name `xml:"ListBucketResult" json:"-"` Name string @@ -33,6 +35,7 @@ type ObjectListResponse struct { Contents []*Item `xml:,innerxml` } +// Bucket list response format type BucketListResponse struct { XMLName xml.Name `xml:"ListAllMyBucketsResult" json:"-"` Owner Owner @@ -41,11 +44,13 @@ type BucketListResponse struct { } `xml:,innerxml` // Buckets are nested } +// Bucket struct type Bucket struct { Name string CreationDate string } +// Object struct type Item struct { Key string LastModified string @@ -60,6 +65,7 @@ type Owner struct { DisplayName string } +// List of not implemented bucket queries var unimplementedBucketResourceNames = map[string]bool{ "acl": true, "cors": true, @@ -75,6 +81,7 @@ var unimplementedBucketResourceNames = map[string]bool{ "uploads": true, } +// List of not implemented object queries var unimplementedObjectResourceNames = map[string]bool{ "uploadId": true, "acl": true, diff --git a/pkg/api/minioapi/error_response.go b/pkg/api/minioapi/error_response.go index b189b4c7c..019b88058 100644 --- a/pkg/api/minioapi/error_response.go +++ b/pkg/api/minioapi/error_response.go @@ -21,12 +21,14 @@ import ( "net/http" ) +// Error structure type Error struct { Code string Description string HttpStatusCode int } +// Error response format type ErrorResponse struct { XMLName xml.Name `xml:"Error" json:"-"` Code string @@ -36,7 +38,7 @@ type ErrorResponse struct { HostId string } -/// Error codes, non exhaustive list +// Error codes, non exhaustive list const ( AccessDenied = iota BadDigest @@ -63,6 +65,7 @@ const ( NoSuchBucketPolicy ) +// Error code to Error structure map var errorCodeResponse = map[int]Error{ AccessDenied: { Code: "AccessDenied", @@ -181,12 +184,13 @@ var errorCodeResponse = map[int]Error{ }, } -// errorCodeError provides errorCode to Error. It returns empty if -// the code provided is unknown +// errorCodeError provides errorCode to Error. It returns empty if the code provided is unknown func errorCodeError(code int) Error { return errorCodeResponse[code] } +// getErrorResponse gets in standard error and resource value and +// provides a encodable populated response values func getErrorResponse(err Error, resource string) ErrorResponse { var data = ErrorResponse{} data.Code = err.Code diff --git a/pkg/api/minioapi/generic_handlers.go b/pkg/api/minioapi/generic_handlers.go index 743496390..623b965b5 100644 --- a/pkg/api/minioapi/generic_handlers.go +++ b/pkg/api/minioapi/generic_handlers.go @@ -33,7 +33,7 @@ type rHandler struct { handler http.Handler } -// grab AccessKey from authorization header +// strip AccessKey from authorization header func stripAccessKey(r *http.Request) string { fields := strings.Fields(r.Header.Get("Authorization")) if len(fields) < 2 { @@ -46,6 +46,8 @@ func stripAccessKey(r *http.Request) string { return splits[0] } +// Validate handler is wrapper handler used for API request validation with authorization header. +// Current authorization layer supports S3's standard HMAC based signature request. func validateHandler(conf config.Config, h http.Handler) http.Handler { return vHandler{conf, h} } @@ -72,16 +74,23 @@ func (h vHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } } } else { - //No access key found, handle this more appropriately - //TODO: Remove this after adding tests to support signature - //request + // Control reaches when no access key is found, ideally we would + // like to throw back `403`. But for now with our tests lacking + // this functionality it is better for us to be serving anonymous + // requests as well. + // We should remove this after adding tests to support signature request h.handler.ServeHTTP(w, r) - //Add this line, to reply back for invalid requests - //w.WriteHeader(http.StatusUnauthorized) - //w.Write([]byte("Authorization header malformed") + // ## Uncommented below links of code after disabling anonymous requests + // error := errorCodeError(AccessDenied) + // errorResponse := getErrorResponse(error, "") + // w.WriteHeader(error.HttpStatusCode) + // w.Write(writeErrorResponse(w, errorResponse, acceptsContentType)) } } +// Ignore resources handler is wrapper handler used for API request resource validation +// Since we do not support all the S3 queries, it is necessary for us to throw back a +// valid error message indicating such a feature to have been not implemented. func ignoreResourcesHandler(h http.Handler) http.Handler { return rHandler{h} } diff --git a/pkg/api/minioapi/headers.go b/pkg/api/minioapi/headers.go index 10286f2b9..f6b2c9fc7 100644 --- a/pkg/api/minioapi/headers.go +++ b/pkg/api/minioapi/headers.go @@ -32,12 +32,15 @@ type encoder interface { Encode(v interface{}) error } -// Write Common Header helpers +//// helpers + +// Write http common headers func writeCommonHeaders(w http.ResponseWriter, acceptsType string) { w.Header().Set("Server", "Minio") w.Header().Set("Content-Type", acceptsType) } +// Write error response headers func writeErrorResponse(w http.ResponseWriter, response interface{}, acceptsType contentType) []byte { var bytesBuffer bytes.Buffer var encoder encoder @@ -53,10 +56,10 @@ func writeErrorResponse(w http.ResponseWriter, response interface{}, acceptsType return bytesBuffer.Bytes() } -// Write Object Header helper +// Write object header func writeObjectHeaders(w http.ResponseWriter, metadata mstorage.ObjectMetadata) { lastModified := metadata.Created.Format(time.RFC1123) - // write common headers + // common headers writeCommonHeaders(w, metadata.ContentType) w.Header().Set("ETag", metadata.ETag) w.Header().Set("Last-Modified", lastModified) @@ -64,10 +67,11 @@ func writeObjectHeaders(w http.ResponseWriter, metadata mstorage.ObjectMetadata) w.Header().Set("Connection", "close") } +// Write object header and response func writeObjectHeadersAndResponse(w http.ResponseWriter, response interface{}, acceptsType contentType) []byte { var bytesBuffer bytes.Buffer var encoder encoder - // write common headers + // common headers writeCommonHeaders(w, getContentString(acceptsType)) switch acceptsType { case xmlType: diff --git a/pkg/api/minioapi/muxer.go b/pkg/api/minioapi/muxer.go index 9c43d31a4..ce0fb2552 100644 --- a/pkg/api/minioapi/muxer.go +++ b/pkg/api/minioapi/muxer.go @@ -25,15 +25,13 @@ import ( "github.com/minio-io/minio/pkg/utils/config" ) -const ( - dateFormat = "2006-01-02T15:04:05.000Z" -) - +// private use type minioApi struct { domain string storage mstorage.Storage } +// Path based routing func pathMux(api minioApi, mux *x.Router) *x.Router { mux.HandleFunc("/", api.listBucketsHandler).Methods("GET") mux.HandleFunc("/{bucket}", api.listObjectsHandler).Methods("GET") @@ -45,6 +43,7 @@ func pathMux(api minioApi, mux *x.Router) *x.Router { return mux } +// Domain based routing func domainMux(api minioApi, mux *x.Router) *x.Router { mux.HandleFunc("/", api.listObjectsHandler).Host("{bucket}" + "." + api.domain).Methods("GET") @@ -60,6 +59,7 @@ func domainMux(api minioApi, mux *x.Router) *x.Router { return mux } +// Get proper router based on domain availability func getMux(api minioApi, mux *x.Router) *x.Router { switch true { case api.domain == "": @@ -71,6 +71,7 @@ func getMux(api minioApi, mux *x.Router) *x.Router { return nil } +// Http wrapper handler func HttpHandler(domain string, storage mstorage.Storage) http.Handler { var mux *x.Router var api = minioApi{} diff --git a/pkg/api/minioapi/object_handlers.go b/pkg/api/minioapi/object_handlers.go index 9982fc54c..9fe0c1ef5 100644 --- a/pkg/api/minioapi/object_handlers.go +++ b/pkg/api/minioapi/object_handlers.go @@ -1,3 +1,19 @@ +/* + * Mini Object Storage, (C) 2015 Minio, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package minioapi import ( @@ -8,6 +24,10 @@ import ( mstorage "github.com/minio-io/minio/pkg/storage" ) +// GET Object +// ---------- +// This implementation of the GET operation retrieves object. To use GET, +// you must have READ access to the object. func (server *minioApi) getObjectHandler(w http.ResponseWriter, req *http.Request) { var object, bucket string @@ -59,6 +79,9 @@ func (server *minioApi) getObjectHandler(w http.ResponseWriter, req *http.Reques } } +// HEAD Object +// ----------- +// The HEAD operation retrieves metadata from an object without returning the object itself. func (server *minioApi) headObjectHandler(w http.ResponseWriter, req *http.Request) { var object, bucket string acceptsContentType := getContentType(req) @@ -96,6 +119,9 @@ func (server *minioApi) headObjectHandler(w http.ResponseWriter, req *http.Reque } } +// PUT Object +// ---------- +// This implementation of the PUT operation adds an object to a bucket. func (server *minioApi) putObjectHandler(w http.ResponseWriter, req *http.Request) { var object, bucket string vars := mux.Vars(req) diff --git a/pkg/api/minioapi/policy_handlers.go b/pkg/api/minioapi/policy_handlers.go index b3773dcf0..b5a5362f1 100644 --- a/pkg/api/minioapi/policy_handlers.go +++ b/pkg/api/minioapi/policy_handlers.go @@ -1,3 +1,19 @@ +/* + * Mini Object Storage, (C) 2015 Minio, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package minioapi import ( @@ -10,6 +26,10 @@ import ( "github.com/minio-io/minio/pkg/utils/policy" ) +// PUT Bucket policy +// ----------------- +// This implementation of the PUT operation uses the policy subresource +// to add to or replace a policy on a bucket func (server *minioApi) putBucketPolicyHandler(w http.ResponseWriter, req *http.Request) { vars := mux.Vars(req) bucket := vars["bucket"] @@ -58,6 +78,10 @@ func (server *minioApi) putBucketPolicyHandler(w http.ResponseWriter, req *http. } } +// GET Bucket policy +// ----------------- +// This implementation of the GET operation uses the policy subresource +// to return the policy of a specified bucket. func (server *minioApi) getBucketPolicyHandler(w http.ResponseWriter, req *http.Request) { vars := mux.Vars(req) bucket := vars["bucket"] diff --git a/pkg/api/minioapi/resources.go b/pkg/api/minioapi/resources.go index 44e9fbbe6..2ccd4c633 100644 --- a/pkg/api/minioapi/resources.go +++ b/pkg/api/minioapi/resources.go @@ -1,3 +1,19 @@ +/* + * Mini Object Storage, (C) 2015 Minio, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package minioapi import ( @@ -5,6 +21,7 @@ import ( "strconv" ) +// support bucket resources go here type bucketResources struct { prefix string marker string @@ -14,6 +31,7 @@ type bucketResources struct { // uploads bool - TODO implemented with multipart support } +// parse bucket url queries func getBucketResources(values url.Values) (v bucketResources) { for key, value := range values { switch true { diff --git a/pkg/api/minioapi/response.go b/pkg/api/minioapi/response.go index 6789b4d7f..9f65fe3d5 100644 --- a/pkg/api/minioapi/response.go +++ b/pkg/api/minioapi/response.go @@ -1,9 +1,36 @@ +/* + * Mini Object Storage, (C) 2015 Minio, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package minioapi import ( mstorage "github.com/minio-io/minio/pkg/storage" ) +// Reply date format +const ( + dateFormat = "2006-01-02T15:04:05.000Z" +) + +// 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 func generateBucketsListResult(buckets []mstorage.BucketMetadata) BucketListResponse { var listbuckets []*Bucket var data = BucketListResponse{}