Merge pull request #202 from harshavardhana/pr_out_update_minioapi_documentation
This commit is contained in:
commit
2b8adef454
11 changed files with 172 additions and 18 deletions
|
@ -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"]
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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{}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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{}
|
||||
|
|
Loading…
Reference in a new issue