|
|
@ -62,95 +62,6 @@ func HttpHandler(storage mstorage.Storage) http.Handler { |
|
|
|
return mux |
|
|
|
return mux |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (server *minioApi) ignoreUnImplementedBucketResources(req *http.Request) bool { |
|
|
|
|
|
|
|
q := req.URL.Query() |
|
|
|
|
|
|
|
for name := range q { |
|
|
|
|
|
|
|
if unimplementedBucketResourceNames[name] { |
|
|
|
|
|
|
|
return true |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (server *minioApi) ignoreUnImplementedObjectResources(req *http.Request) bool { |
|
|
|
|
|
|
|
q := req.URL.Query() |
|
|
|
|
|
|
|
for name := range q { |
|
|
|
|
|
|
|
if unimplementedObjectResourceNames[name] { |
|
|
|
|
|
|
|
return true |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (server *minioApi) getObjectHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
|
|
|
|
if server.ignoreUnImplementedObjectResources(req) { |
|
|
|
|
|
|
|
w.WriteHeader(http.StatusNotImplemented) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vars := mux.Vars(req) |
|
|
|
|
|
|
|
bucket := vars["bucket"] |
|
|
|
|
|
|
|
object := vars["object"] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
metadata, err := server.storage.GetObjectMetadata(bucket, object) |
|
|
|
|
|
|
|
switch err := err.(type) { |
|
|
|
|
|
|
|
case nil: // success
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
log.Println("Found: " + bucket + "#" + object) |
|
|
|
|
|
|
|
writeObjectHeaders(w, metadata) |
|
|
|
|
|
|
|
if _, err := server.storage.CopyObjectToWriter(w, bucket, object); err != nil { |
|
|
|
|
|
|
|
log.Println(err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
case mstorage.ObjectNotFound: |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
log.Println(err) |
|
|
|
|
|
|
|
w.WriteHeader(http.StatusNotFound) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
log.Println(err) |
|
|
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (server *minioApi) headObjectHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
|
|
|
|
vars := mux.Vars(req) |
|
|
|
|
|
|
|
bucket := vars["bucket"] |
|
|
|
|
|
|
|
object := vars["object"] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
metadata, err := server.storage.GetObjectMetadata(bucket, object) |
|
|
|
|
|
|
|
switch err := err.(type) { |
|
|
|
|
|
|
|
case nil: |
|
|
|
|
|
|
|
writeObjectHeaders(w, metadata) |
|
|
|
|
|
|
|
case mstorage.ObjectNotFound: |
|
|
|
|
|
|
|
log.Println(err) |
|
|
|
|
|
|
|
w.WriteHeader(http.StatusNotFound) |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
log.Println(err) |
|
|
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func populateHeaders(w http.ResponseWriter, response interface{}, contentType int) []byte { |
|
|
|
|
|
|
|
var bytesBuffer bytes.Buffer |
|
|
|
|
|
|
|
var encoder encoder |
|
|
|
|
|
|
|
if contentType == xmlType { |
|
|
|
|
|
|
|
w.Header().Set("Content-Type", "application/xml") |
|
|
|
|
|
|
|
w.Header().Set("Server", "Minio") |
|
|
|
|
|
|
|
w.Header().Set("Connection", "close") |
|
|
|
|
|
|
|
encoder = xml.NewEncoder(&bytesBuffer) |
|
|
|
|
|
|
|
} else if contentType == jsonType { |
|
|
|
|
|
|
|
w.Header().Set("Content-Type", "application/json") |
|
|
|
|
|
|
|
w.Header().Set("Server", "Minio") |
|
|
|
|
|
|
|
w.Header().Set("Connection", "close") |
|
|
|
|
|
|
|
encoder = json.NewEncoder(&bytesBuffer) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
encoder.Encode(response) |
|
|
|
|
|
|
|
return bytesBuffer.Bytes() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (server *minioApi) listBucketsHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
func (server *minioApi) listBucketsHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
if server.ignoreUnImplementedBucketResources(req) { |
|
|
|
if server.ignoreUnImplementedBucketResources(req) { |
|
|
|
w.WriteHeader(http.StatusNotImplemented) |
|
|
|
w.WriteHeader(http.StatusNotImplemented) |
|
|
@ -176,7 +87,7 @@ func (server *minioApi) listBucketsHandler(w http.ResponseWriter, req *http.Requ |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
response := generateBucketsListResult(buckets) |
|
|
|
response := generateBucketsListResult(buckets) |
|
|
|
w.Write(populateHeaders(w, response, contentType)) |
|
|
|
w.Write(writeObjectHeadersAndResponse(w, response, contentType)) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (server *minioApi) listObjectsHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
func (server *minioApi) listObjectsHandler(w http.ResponseWriter, req *http.Request) { |
|
|
@ -206,10 +117,10 @@ func (server *minioApi) listObjectsHandler(w http.ResponseWriter, req *http.Requ |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
response := generateObjectsListResult(bucket, objects, isTruncated) |
|
|
|
response := generateObjectsListResult(bucket, objects, isTruncated) |
|
|
|
w.Write(populateHeaders(w, response, contentType)) |
|
|
|
w.Write(writeObjectHeadersAndResponse(w, response, contentType)) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (server *minioApi) putObjectHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
func (server *minioApi) putBucketHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
if server.ignoreUnImplementedBucketResources(req) { |
|
|
|
if server.ignoreUnImplementedBucketResources(req) { |
|
|
|
w.WriteHeader(http.StatusNotImplemented) |
|
|
|
w.WriteHeader(http.StatusNotImplemented) |
|
|
|
return |
|
|
|
return |
|
|
@ -217,8 +128,7 @@ func (server *minioApi) putObjectHandler(w http.ResponseWriter, req *http.Reques |
|
|
|
|
|
|
|
|
|
|
|
vars := mux.Vars(req) |
|
|
|
vars := mux.Vars(req) |
|
|
|
bucket := vars["bucket"] |
|
|
|
bucket := vars["bucket"] |
|
|
|
object := vars["object"] |
|
|
|
err := server.storage.StoreBucket(bucket) |
|
|
|
err := server.storage.StoreObject(bucket, object, req.Body) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
w.WriteHeader(http.StatusBadRequest) |
|
|
|
w.WriteHeader(http.StatusBadRequest) |
|
|
|
w.Write([]byte(err.Error())) |
|
|
|
w.Write([]byte(err.Error())) |
|
|
@ -228,7 +138,58 @@ func (server *minioApi) putObjectHandler(w http.ResponseWriter, req *http.Reques |
|
|
|
w.Header().Set("Connection", "close") |
|
|
|
w.Header().Set("Connection", "close") |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (server *minioApi) putBucketHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
func (server *minioApi) getObjectHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
|
|
|
|
if server.ignoreUnImplementedObjectResources(req) { |
|
|
|
|
|
|
|
w.WriteHeader(http.StatusNotImplemented) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vars := mux.Vars(req) |
|
|
|
|
|
|
|
bucket := vars["bucket"] |
|
|
|
|
|
|
|
object := vars["object"] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
metadata, err := server.storage.GetObjectMetadata(bucket, object) |
|
|
|
|
|
|
|
switch err := err.(type) { |
|
|
|
|
|
|
|
case nil: // success
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
log.Println("Found: " + bucket + "#" + object) |
|
|
|
|
|
|
|
writeObjectHeaders(w, metadata) |
|
|
|
|
|
|
|
if _, err := server.storage.CopyObjectToWriter(w, bucket, object); err != nil { |
|
|
|
|
|
|
|
log.Println(err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
case mstorage.ObjectNotFound: |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
log.Println(err) |
|
|
|
|
|
|
|
w.WriteHeader(http.StatusNotFound) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
log.Println(err) |
|
|
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (server *minioApi) headObjectHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
|
|
|
|
vars := mux.Vars(req) |
|
|
|
|
|
|
|
bucket := vars["bucket"] |
|
|
|
|
|
|
|
object := vars["object"] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
metadata, err := server.storage.GetObjectMetadata(bucket, object) |
|
|
|
|
|
|
|
switch err := err.(type) { |
|
|
|
|
|
|
|
case nil: |
|
|
|
|
|
|
|
writeObjectHeaders(w, metadata) |
|
|
|
|
|
|
|
case mstorage.ObjectNotFound: |
|
|
|
|
|
|
|
log.Println(err) |
|
|
|
|
|
|
|
w.WriteHeader(http.StatusNotFound) |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
log.Println(err) |
|
|
|
|
|
|
|
w.WriteHeader(http.StatusBadRequest) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (server *minioApi) putObjectHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
if server.ignoreUnImplementedBucketResources(req) { |
|
|
|
if server.ignoreUnImplementedBucketResources(req) { |
|
|
|
w.WriteHeader(http.StatusNotImplemented) |
|
|
|
w.WriteHeader(http.StatusNotImplemented) |
|
|
|
return |
|
|
|
return |
|
|
@ -236,7 +197,8 @@ func (server *minioApi) putBucketHandler(w http.ResponseWriter, req *http.Reques |
|
|
|
|
|
|
|
|
|
|
|
vars := mux.Vars(req) |
|
|
|
vars := mux.Vars(req) |
|
|
|
bucket := vars["bucket"] |
|
|
|
bucket := vars["bucket"] |
|
|
|
err := server.storage.StoreBucket(bucket) |
|
|
|
object := vars["object"] |
|
|
|
|
|
|
|
err := server.storage.StoreObject(bucket, object, req.Body) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
w.WriteHeader(http.StatusBadRequest) |
|
|
|
w.WriteHeader(http.StatusBadRequest) |
|
|
|
w.Write([]byte(err.Error())) |
|
|
|
w.Write([]byte(err.Error())) |
|
|
@ -246,6 +208,22 @@ func (server *minioApi) putBucketHandler(w http.ResponseWriter, req *http.Reques |
|
|
|
w.Header().Set("Connection", "close") |
|
|
|
w.Header().Set("Connection", "close") |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func writeObjectHeadersAndResponse(w http.ResponseWriter, response interface{}, contentType int) []byte { |
|
|
|
|
|
|
|
var bytesBuffer bytes.Buffer |
|
|
|
|
|
|
|
var encoder encoder |
|
|
|
|
|
|
|
if contentType == xmlType { |
|
|
|
|
|
|
|
w.Header().Set("Content-Type", "application/xml") |
|
|
|
|
|
|
|
encoder = xml.NewEncoder(&bytesBuffer) |
|
|
|
|
|
|
|
} else if contentType == jsonType { |
|
|
|
|
|
|
|
w.Header().Set("Content-Type", "application/json") |
|
|
|
|
|
|
|
encoder = json.NewEncoder(&bytesBuffer) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
w.Header().Set("Server", "Minio") |
|
|
|
|
|
|
|
w.Header().Set("Connection", "close") |
|
|
|
|
|
|
|
encoder.Encode(response) |
|
|
|
|
|
|
|
return bytesBuffer.Bytes() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Write Object Header helper
|
|
|
|
// Write Object Header helper
|
|
|
|
func writeObjectHeaders(w http.ResponseWriter, metadata mstorage.ObjectMetadata) { |
|
|
|
func writeObjectHeaders(w http.ResponseWriter, metadata mstorage.ObjectMetadata) { |
|
|
|
lastModified := metadata.Created.Format(time.RFC1123) |
|
|
|
lastModified := metadata.Created.Format(time.RFC1123) |
|
|
@ -278,6 +256,37 @@ func generateBucketsListResult(buckets []mstorage.BucketMetadata) BucketListResp |
|
|
|
return data |
|
|
|
return data |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//// Unimplemented Resources
|
|
|
|
|
|
|
|
func (server *minioApi) ignoreUnImplementedBucketResources(req *http.Request) bool { |
|
|
|
|
|
|
|
q := req.URL.Query() |
|
|
|
|
|
|
|
for name := range q { |
|
|
|
|
|
|
|
if unimplementedBucketResourceNames[name] { |
|
|
|
|
|
|
|
return true |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (server *minioApi) ignoreUnImplementedObjectResources(req *http.Request) bool { |
|
|
|
|
|
|
|
q := req.URL.Query() |
|
|
|
|
|
|
|
for name := range q { |
|
|
|
|
|
|
|
if unimplementedObjectResourceNames[name] { |
|
|
|
|
|
|
|
return true |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//// helpers
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
func generateObjectsListResult(bucket string, objects []mstorage.ObjectMetadata, isTruncated bool) ObjectListResponse { |
|
|
|
func generateObjectsListResult(bucket string, objects []mstorage.ObjectMetadata, isTruncated bool) ObjectListResponse { |
|
|
|
var contents []*Item |
|
|
|
var contents []*Item |
|
|
|
var owner = Owner{} |
|
|
|
var owner = Owner{} |
|
|
|