|
|
@ -21,8 +21,8 @@ import ( |
|
|
|
"strconv" |
|
|
|
"strconv" |
|
|
|
|
|
|
|
|
|
|
|
"github.com/gorilla/mux" |
|
|
|
"github.com/gorilla/mux" |
|
|
|
"github.com/minio/minio/pkg/fs" |
|
|
|
|
|
|
|
"github.com/minio/minio-xl/pkg/probe" |
|
|
|
"github.com/minio/minio-xl/pkg/probe" |
|
|
|
|
|
|
|
"github.com/minio/minio/pkg/fs" |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
const ( |
|
|
|
const ( |
|
|
@ -39,6 +39,15 @@ func (api API) GetObjectHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
bucket = vars["bucket"] |
|
|
|
bucket = vars["bucket"] |
|
|
|
object = vars["object"] |
|
|
|
object = vars["object"] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !api.Anonymous { |
|
|
|
|
|
|
|
if isRequestRequiresACLCheck(req) { |
|
|
|
|
|
|
|
if api.Filesystem.IsPrivateBucket(bucket) { |
|
|
|
|
|
|
|
writeErrorResponse(w, req, AccessDenied, req.URL.Path) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
metadata, err := api.Filesystem.GetObjectMetadata(bucket, object) |
|
|
|
metadata, err := api.Filesystem.GetObjectMetadata(bucket, object) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
errorIf(err.Trace(), "GetObject failed.", nil) |
|
|
|
errorIf(err.Trace(), "GetObject failed.", nil) |
|
|
@ -78,6 +87,15 @@ func (api API) HeadObjectHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
bucket = vars["bucket"] |
|
|
|
bucket = vars["bucket"] |
|
|
|
object = vars["object"] |
|
|
|
object = vars["object"] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !api.Anonymous { |
|
|
|
|
|
|
|
if isRequestRequiresACLCheck(req) { |
|
|
|
|
|
|
|
if api.Filesystem.IsPrivateBucket(bucket) { |
|
|
|
|
|
|
|
writeErrorResponse(w, req, AccessDenied, req.URL.Path) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
metadata, err := api.Filesystem.GetObjectMetadata(bucket, object) |
|
|
|
metadata, err := api.Filesystem.GetObjectMetadata(bucket, object) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
switch err.ToGoError().(type) { |
|
|
|
switch err.ToGoError().(type) { |
|
|
@ -107,6 +125,15 @@ func (api API) PutObjectHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
bucket = vars["bucket"] |
|
|
|
bucket = vars["bucket"] |
|
|
|
object = vars["object"] |
|
|
|
object = vars["object"] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !api.Anonymous { |
|
|
|
|
|
|
|
if isRequestRequiresACLCheck(req) { |
|
|
|
|
|
|
|
if api.Filesystem.IsPrivateBucket(bucket) { |
|
|
|
|
|
|
|
writeErrorResponse(w, req, AccessDenied, req.URL.Path) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// get Content-MD5 sent by client and verify if valid
|
|
|
|
// get Content-MD5 sent by client and verify if valid
|
|
|
|
md5 := req.Header.Get("Content-MD5") |
|
|
|
md5 := req.Header.Get("Content-MD5") |
|
|
|
if !isValidMD5(md5) { |
|
|
|
if !isValidMD5(md5) { |
|
|
@ -136,7 +163,7 @@ func (api API) PutObjectHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
|
|
|
|
|
|
|
|
var signature *fs.Signature |
|
|
|
var signature *fs.Signature |
|
|
|
if !api.Anonymous { |
|
|
|
if !api.Anonymous { |
|
|
|
if _, ok := req.Header["Authorization"]; ok { |
|
|
|
if isRequestSignatureV4(req) { |
|
|
|
// Init signature V4 verification
|
|
|
|
// Init signature V4 verification
|
|
|
|
var err *probe.Error |
|
|
|
var err *probe.Error |
|
|
|
signature, err = initSignatureV4(req) |
|
|
|
signature, err = initSignatureV4(req) |
|
|
@ -181,16 +208,19 @@ func (api API) PutObjectHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
|
|
|
|
|
|
|
|
// NewMultipartUploadHandler - New multipart upload
|
|
|
|
// NewMultipartUploadHandler - New multipart upload
|
|
|
|
func (api API) NewMultipartUploadHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
func (api API) NewMultipartUploadHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
if !isRequestUploads(req.URL.Query()) { |
|
|
|
|
|
|
|
writeErrorResponse(w, req, MethodNotAllowed, req.URL.Path) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var object, bucket string |
|
|
|
var object, bucket string |
|
|
|
vars := mux.Vars(req) |
|
|
|
vars := mux.Vars(req) |
|
|
|
bucket = vars["bucket"] |
|
|
|
bucket = vars["bucket"] |
|
|
|
object = vars["object"] |
|
|
|
object = vars["object"] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !api.Anonymous { |
|
|
|
|
|
|
|
// Unauthorized multipart uploads are not supported
|
|
|
|
|
|
|
|
if isRequestRequiresACLCheck(req) { |
|
|
|
|
|
|
|
writeErrorResponse(w, req, AccessDenied, req.URL.Path) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
uploadID, err := api.Filesystem.NewMultipartUpload(bucket, object) |
|
|
|
uploadID, err := api.Filesystem.NewMultipartUpload(bucket, object) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
errorIf(err.Trace(), "NewMultipartUpload failed.", nil) |
|
|
|
errorIf(err.Trace(), "NewMultipartUpload failed.", nil) |
|
|
@ -219,11 +249,15 @@ func (api API) NewMultipartUploadHandler(w http.ResponseWriter, req *http.Reques |
|
|
|
|
|
|
|
|
|
|
|
// PutObjectPartHandler - Upload part
|
|
|
|
// PutObjectPartHandler - Upload part
|
|
|
|
func (api API) PutObjectPartHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
func (api API) PutObjectPartHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
// get Content-MD5 sent by client and verify if valid
|
|
|
|
vars := mux.Vars(req) |
|
|
|
md5 := req.Header.Get("Content-MD5") |
|
|
|
bucket := vars["bucket"] |
|
|
|
if !isValidMD5(md5) { |
|
|
|
object := vars["object"] |
|
|
|
writeErrorResponse(w, req, InvalidDigest, req.URL.Path) |
|
|
|
|
|
|
|
return |
|
|
|
if !api.Anonymous { |
|
|
|
|
|
|
|
if isRequestRequiresACLCheck(req) { |
|
|
|
|
|
|
|
writeErrorResponse(w, req, AccessDenied, req.URL.Path) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// if Content-Length missing, throw away
|
|
|
|
/// if Content-Length missing, throw away
|
|
|
@ -233,6 +267,13 @@ func (api API) PutObjectPartHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// get Content-MD5 sent by client and verify if valid
|
|
|
|
|
|
|
|
md5 := req.Header.Get("Content-MD5") |
|
|
|
|
|
|
|
if !isValidMD5(md5) { |
|
|
|
|
|
|
|
writeErrorResponse(w, req, InvalidDigest, req.URL.Path) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// maximum Upload size for multipart objects in a single operation
|
|
|
|
/// maximum Upload size for multipart objects in a single operation
|
|
|
|
if isMaxObjectSize(size) { |
|
|
|
if isMaxObjectSize(size) { |
|
|
|
writeErrorResponse(w, req, EntityTooLarge, req.URL.Path) |
|
|
|
writeErrorResponse(w, req, EntityTooLarge, req.URL.Path) |
|
|
@ -249,10 +290,6 @@ func (api API) PutObjectPartHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
vars := mux.Vars(req) |
|
|
|
|
|
|
|
bucket := vars["bucket"] |
|
|
|
|
|
|
|
object := vars["object"] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uploadID := req.URL.Query().Get("uploadId") |
|
|
|
uploadID := req.URL.Query().Get("uploadId") |
|
|
|
partIDString := req.URL.Query().Get("partNumber") |
|
|
|
partIDString := req.URL.Query().Get("partNumber") |
|
|
|
|
|
|
|
|
|
|
@ -268,7 +305,7 @@ func (api API) PutObjectPartHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
|
|
|
|
|
|
|
|
var signature *fs.Signature |
|
|
|
var signature *fs.Signature |
|
|
|
if !api.Anonymous { |
|
|
|
if !api.Anonymous { |
|
|
|
if _, ok := req.Header["Authorization"]; ok { |
|
|
|
if isRequestSignatureV4(req) { |
|
|
|
// Init signature V4 verification
|
|
|
|
// Init signature V4 verification
|
|
|
|
var err *probe.Error |
|
|
|
var err *probe.Error |
|
|
|
signature, err = initSignatureV4(req) |
|
|
|
signature, err = initSignatureV4(req) |
|
|
@ -311,6 +348,13 @@ func (api API) AbortMultipartUploadHandler(w http.ResponseWriter, req *http.Requ |
|
|
|
bucket := vars["bucket"] |
|
|
|
bucket := vars["bucket"] |
|
|
|
object := vars["object"] |
|
|
|
object := vars["object"] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !api.Anonymous { |
|
|
|
|
|
|
|
if isRequestRequiresACLCheck(req) { |
|
|
|
|
|
|
|
writeErrorResponse(w, req, AccessDenied, req.URL.Path) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
objectResourcesMetadata := getObjectResources(req.URL.Query()) |
|
|
|
objectResourcesMetadata := getObjectResources(req.URL.Query()) |
|
|
|
|
|
|
|
|
|
|
|
err := api.Filesystem.AbortMultipartUpload(bucket, object, objectResourcesMetadata.UploadID) |
|
|
|
err := api.Filesystem.AbortMultipartUpload(bucket, object, objectResourcesMetadata.UploadID) |
|
|
@ -338,6 +382,17 @@ func (api API) AbortMultipartUploadHandler(w http.ResponseWriter, req *http.Requ |
|
|
|
|
|
|
|
|
|
|
|
// ListObjectPartsHandler - List object parts
|
|
|
|
// ListObjectPartsHandler - List object parts
|
|
|
|
func (api API) ListObjectPartsHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
func (api API) ListObjectPartsHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
|
|
|
|
vars := mux.Vars(req) |
|
|
|
|
|
|
|
bucket := vars["bucket"] |
|
|
|
|
|
|
|
object := vars["object"] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !api.Anonymous { |
|
|
|
|
|
|
|
if isRequestRequiresACLCheck(req) { |
|
|
|
|
|
|
|
writeErrorResponse(w, req, AccessDenied, req.URL.Path) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
objectResourcesMetadata := getObjectResources(req.URL.Query()) |
|
|
|
objectResourcesMetadata := getObjectResources(req.URL.Query()) |
|
|
|
if objectResourcesMetadata.PartNumberMarker < 0 { |
|
|
|
if objectResourcesMetadata.PartNumberMarker < 0 { |
|
|
|
writeErrorResponse(w, req, InvalidPartNumberMarker, req.URL.Path) |
|
|
|
writeErrorResponse(w, req, InvalidPartNumberMarker, req.URL.Path) |
|
|
@ -351,10 +406,6 @@ func (api API) ListObjectPartsHandler(w http.ResponseWriter, req *http.Request) |
|
|
|
objectResourcesMetadata.MaxParts = maxPartsList |
|
|
|
objectResourcesMetadata.MaxParts = maxPartsList |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
vars := mux.Vars(req) |
|
|
|
|
|
|
|
bucket := vars["bucket"] |
|
|
|
|
|
|
|
object := vars["object"] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
objectResourcesMetadata, err := api.Filesystem.ListObjectParts(bucket, object, objectResourcesMetadata) |
|
|
|
objectResourcesMetadata, err := api.Filesystem.ListObjectParts(bucket, object, objectResourcesMetadata) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
errorIf(err.Trace(), "ListObjectParts failed.", nil) |
|
|
|
errorIf(err.Trace(), "ListObjectParts failed.", nil) |
|
|
@ -388,11 +439,17 @@ func (api API) CompleteMultipartUploadHandler(w http.ResponseWriter, req *http.R |
|
|
|
bucket := vars["bucket"] |
|
|
|
bucket := vars["bucket"] |
|
|
|
object := vars["object"] |
|
|
|
object := vars["object"] |
|
|
|
|
|
|
|
|
|
|
|
objectResourcesMetadata := getObjectResources(req.URL.Query()) |
|
|
|
if !api.Anonymous { |
|
|
|
|
|
|
|
if isRequestRequiresACLCheck(req) { |
|
|
|
|
|
|
|
writeErrorResponse(w, req, AccessDenied, req.URL.Path) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
objectResourcesMetadata := getObjectResources(req.URL.Query()) |
|
|
|
var signature *fs.Signature |
|
|
|
var signature *fs.Signature |
|
|
|
if !api.Anonymous { |
|
|
|
if !api.Anonymous { |
|
|
|
if _, ok := req.Header["Authorization"]; ok { |
|
|
|
if isRequestSignatureV4(req) { |
|
|
|
// Init signature V4 verification
|
|
|
|
// Init signature V4 verification
|
|
|
|
var err *probe.Error |
|
|
|
var err *probe.Error |
|
|
|
signature, err = initSignatureV4(req) |
|
|
|
signature, err = initSignatureV4(req) |
|
|
@ -449,6 +506,15 @@ func (api API) DeleteObjectHandler(w http.ResponseWriter, req *http.Request) { |
|
|
|
bucket := vars["bucket"] |
|
|
|
bucket := vars["bucket"] |
|
|
|
object := vars["object"] |
|
|
|
object := vars["object"] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !api.Anonymous { |
|
|
|
|
|
|
|
if isRequestRequiresACLCheck(req) { |
|
|
|
|
|
|
|
if api.Filesystem.IsPrivateBucket(bucket) { |
|
|
|
|
|
|
|
writeErrorResponse(w, req, AccessDenied, req.URL.Path) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
err := api.Filesystem.DeleteObject(bucket, object) |
|
|
|
err := api.Filesystem.DeleteObject(bucket, object) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
errorIf(err.Trace(), "DeleteObject failed.", nil) |
|
|
|
errorIf(err.Trace(), "DeleteObject failed.", nil) |
|
|
|