Update minioapi documentation

This commit is contained in:
Harshavardhana 2015-02-23 16:46:48 -08:00
parent 0c36dc24f5
commit b7868d23ac
11 changed files with 172 additions and 18 deletions

View File

@ -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"]

View File

@ -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]
}

View File

@ -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,

View File

@ -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

View File

@ -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}
}

View File

@ -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:

View File

@ -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{}

View File

@ -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)

View File

@ -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"]

View File

@ -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 {

View File

@ -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{}