Skip to content

Commit

Permalink
api-core: Cleanup code to handle deleteObject() cleanly
Browse files Browse the repository at this point in the history
  • Loading branch information
Harshavardhana committed Nov 14, 2015
1 parent 69b9d2f commit 1fe9233
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 87 deletions.
8 changes: 4 additions & 4 deletions api.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,8 +233,8 @@ func (c *Config) setBucketRegion() {
tempConfig.Endpoint = u.String()
tempConfig.Region = getRegion(u.Host)
tempConfig.isVirtualHostedStyle = false
s3api := API{apiCore{&tempConfig}}
region, err := s3api.getBucketLocation(bucket)
s3API := API{s3API{&tempConfig}}
region, err := s3API.getBucketLocation(bucket)
if err != nil {
c.Region = getRegion(host)
return
Expand Down Expand Up @@ -282,7 +282,7 @@ func (c *Config) SetUserAgent(name string, version string, comments ...string) {

// API is a container which delegates methods that comply with CloudStorageAPI interface.
type API struct {
apiCore
s3API
}

func isVirtualHostedStyle(host string) bool {
Expand All @@ -308,7 +308,7 @@ func New(config Config) (CloudStorageAPI, error) {
}
config.SetUserAgent(LibraryName, LibraryVersion, runtime.GOOS, runtime.GOARCH)
config.isUserAgentSet = false // default
return API{apiCore{&config}}, nil
return API{s3API{&config}}, nil
}

// PresignedPostPolicy return POST form data that can be used for object upload.
Expand Down
7 changes: 0 additions & 7 deletions api_public_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,13 +196,6 @@ func TestObjectOperations(t *testing.T) {
if err != nil {
t.Fatal("Error")
}
err = a.RemoveObject("bucket", "object1")
if err == nil {
t.Fatal("Error")
}
if err.Error() != "The specified key does not exist." {
t.Fatal("Error")
}
}

func TestPresignedURL(t *testing.T) {
Expand Down
99 changes: 35 additions & 64 deletions api-core.go → s3-api.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ const (
separator = "/"
)

// apiCore container to hold unexported internal functions.
type apiCore struct {
// s3API container to hold unexported internal functions.
type s3API struct {
config *Config
}

Expand All @@ -46,7 +46,7 @@ func closeResp(resp *http.Response) {
}

// putBucketRequest wrapper creates a new putBucket request.
func (a apiCore) putBucketRequest(bucket, acl, location string) (*Request, error) {
func (a s3API) putBucketRequest(bucket, acl, location string) (*Request, error) {
var r *Request
var err error
op := &operation{
Expand Down Expand Up @@ -121,7 +121,7 @@ func (a apiCore) putBucketRequest(bucket, acl, location string) (*Request, error
// ------------------
// [ us-west-1 | us-west-2 | eu-west-1 | eu-central-1 | ap-southeast-1 | ap-northeast-1 | ap-southeast-2 | sa-east-1 ]
// Default - US standard
func (a apiCore) putBucket(bucket, acl, location string) error {
func (a s3API) putBucket(bucket, acl, location string) error {
req, err := a.putBucketRequest(bucket, acl, location)
if err != nil {
return err
Expand All @@ -140,7 +140,7 @@ func (a apiCore) putBucket(bucket, acl, location string) error {
}

// putBucketRequestACL wrapper creates a new putBucketACL request.
func (a apiCore) putBucketACLRequest(bucket, acl string) (*Request, error) {
func (a s3API) putBucketACLRequest(bucket, acl string) (*Request, error) {
op := &operation{
HTTPServer: a.config.Endpoint,
HTTPMethod: "PUT",
Expand All @@ -155,7 +155,7 @@ func (a apiCore) putBucketACLRequest(bucket, acl string) (*Request, error) {
}

// putBucketACL set the permissions on an existing bucket using Canned ACL's.
func (a apiCore) putBucketACL(bucket, acl string) error {
func (a s3API) putBucketACL(bucket, acl string) error {
req, err := a.putBucketACLRequest(bucket, acl)
if err != nil {
return err
Expand All @@ -174,7 +174,7 @@ func (a apiCore) putBucketACL(bucket, acl string) error {
}

// getBucketACLRequest wrapper creates a new getBucketACL request.
func (a apiCore) getBucketACLRequest(bucket string) (*Request, error) {
func (a s3API) getBucketACLRequest(bucket string) (*Request, error) {
op := &operation{
HTTPServer: a.config.Endpoint,
HTTPMethod: "GET",
Expand All @@ -188,7 +188,7 @@ func (a apiCore) getBucketACLRequest(bucket string) (*Request, error) {
}

// getBucketACL get the acl information on an existing bucket.
func (a apiCore) getBucketACL(bucket string) (accessControlPolicy, error) {
func (a s3API) getBucketACL(bucket string) (accessControlPolicy, error) {
req, err := a.getBucketACLRequest(bucket)
if err != nil {
return accessControlPolicy{}, err
Expand Down Expand Up @@ -226,7 +226,7 @@ func (a apiCore) getBucketACL(bucket string) (accessControlPolicy, error) {
}

// getBucketLocationRequest wrapper creates a new getBucketLocation request.
func (a apiCore) getBucketLocationRequest(bucket string) (*Request, error) {
func (a s3API) getBucketLocationRequest(bucket string) (*Request, error) {
op := &operation{
HTTPServer: a.config.Endpoint,
HTTPMethod: "GET",
Expand All @@ -240,7 +240,7 @@ func (a apiCore) getBucketLocationRequest(bucket string) (*Request, error) {
}

// getBucketLocation uses location subresource to return a bucket's region.
func (a apiCore) getBucketLocation(bucket string) (string, error) {
func (a s3API) getBucketLocation(bucket string) (string, error) {
req, err := a.getBucketLocationRequest(bucket)
if err != nil {
return "", err
Expand All @@ -264,7 +264,7 @@ func (a apiCore) getBucketLocation(bucket string) (string, error) {
}

// listObjectsRequest wrapper creates a new listObjects request.
func (a apiCore) listObjectsRequest(bucket, marker, prefix, delimiter string, maxkeys int) (*Request, error) {
func (a s3API) listObjectsRequest(bucket, marker, prefix, delimiter string, maxkeys int) (*Request, error) {
// resourceQuery - get resources properly escaped and lined up before using them in http request.
resourceQuery := func() (*string, error) {
switch {
Expand Down Expand Up @@ -307,7 +307,7 @@ func (a apiCore) listObjectsRequest(bucket, marker, prefix, delimiter string, ma
// ?delimiter - A delimiter is a character you use to group keys.
// ?prefix - Limits the response to keys that begin with the specified prefix.
// ?max-keys - Sets the maximum number of keys returned in the response body.
func (a apiCore) listObjects(bucket, marker, prefix, delimiter string, maxkeys int) (listBucketResult, error) {
func (a s3API) listObjects(bucket, marker, prefix, delimiter string, maxkeys int) (listBucketResult, error) {
if err := invalidBucketError(bucket); err != nil {
return listBucketResult{}, err
}
Expand Down Expand Up @@ -335,7 +335,7 @@ func (a apiCore) listObjects(bucket, marker, prefix, delimiter string, maxkeys i
}

// headBucketRequest wrapper creates a new headBucket request.
func (a apiCore) headBucketRequest(bucket string) (*Request, error) {
func (a s3API) headBucketRequest(bucket string) (*Request, error) {
op := &operation{
HTTPServer: a.config.Endpoint,
HTTPMethod: "HEAD",
Expand All @@ -345,7 +345,7 @@ func (a apiCore) headBucketRequest(bucket string) (*Request, error) {
}

// headBucket useful to determine if a bucket exists and you have permission to access it.
func (a apiCore) headBucket(bucket string) error {
func (a s3API) headBucket(bucket string) error {
if err := invalidBucketError(bucket); err != nil {
return err
}
Expand Down Expand Up @@ -395,7 +395,7 @@ func (a apiCore) headBucket(bucket string) error {
}

// deleteBucketRequest wrapper creates a new deleteBucket request.
func (a apiCore) deleteBucketRequest(bucket string) (*Request, error) {
func (a s3API) deleteBucketRequest(bucket string) (*Request, error) {
op := &operation{
HTTPServer: a.config.Endpoint,
HTTPMethod: "DELETE",
Expand All @@ -409,7 +409,7 @@ func (a apiCore) deleteBucketRequest(bucket string) (*Request, error) {
// NOTE: -
// All objects (including all object versions and delete markers)
// in the bucket must be deleted before successfully attempting this request.
func (a apiCore) deleteBucket(bucket string) error {
func (a s3API) deleteBucket(bucket string) error {
if err := invalidBucketError(bucket); err != nil {
return err
}
Expand Down Expand Up @@ -468,7 +468,7 @@ func (a apiCore) deleteBucket(bucket string) error {
/// Object Read/Write/Stat Operations

// putObjectUnAuthenticatedRequest - putObjectUnauthenticated request.
func (a apiCore) putObjectUnAuthenticatedRequest(bucket, object, contentType string,
func (a s3API) putObjectUnAuthenticatedRequest(bucket, object, contentType string,
size int64, body io.Reader) (*Request, error) {
if strings.TrimSpace(contentType) == "" {
contentType = "application/octet-stream"
Expand All @@ -490,7 +490,7 @@ func (a apiCore) putObjectUnAuthenticatedRequest(bucket, object, contentType str

// putObjectUnAuthenticated - add an object to a bucket anonymously.
// NOTE: You must have WRITE permissions on a bucket to add an object to it. Bucket should have 'public-read-write' ACL.
func (a apiCore) putObjectUnAuthenticated(bucket, object, contentType string,
func (a s3API) putObjectUnAuthenticated(bucket, object, contentType string,
size int64, body io.Reader) (ObjectStat, error) {
req, err := a.putObjectUnAuthenticatedRequest(bucket, object, contentType, size, body)
if err != nil {
Expand All @@ -512,7 +512,7 @@ func (a apiCore) putObjectUnAuthenticated(bucket, object, contentType string,
}

// putObjectRequest wrapper creates a new PutObject request.
func (a apiCore) putObjectRequest(bucket, object, contentType string,
func (a s3API) putObjectRequest(bucket, object, contentType string,
md5SumBytes []byte, size int64, body io.ReadSeeker) (*Request, error) {
if strings.TrimSpace(contentType) == "" {
contentType = "application/octet-stream"
Expand All @@ -537,7 +537,7 @@ func (a apiCore) putObjectRequest(bucket, object, contentType string,

// putObject - add an object to a bucket.
// NOTE: You must have WRITE permissions on a bucket to add an object to it.
func (a apiCore) putObject(bucket, object, contentType string,
func (a s3API) putObject(bucket, object, contentType string,
md5SumBytes []byte, size int64, body io.ReadSeeker) (ObjectStat, error) {
req, err := a.putObjectRequest(bucket, object, contentType, md5SumBytes, size, body)
if err != nil {
Expand All @@ -559,7 +559,7 @@ func (a apiCore) putObject(bucket, object, contentType string,
}

// presignedPostPolicy - generate post form data.
func (a apiCore) presignedPostPolicy(p *PostPolicy) map[string]string {
func (a s3API) presignedPostPolicy(p *PostPolicy) map[string]string {
t := time.Now().UTC()
r := new(Request)
r.config = a.config
Expand Down Expand Up @@ -601,7 +601,7 @@ func (a apiCore) presignedPostPolicy(p *PostPolicy) map[string]string {
}

// presignedPutObject - generate presigned PUT url.
func (a apiCore) presignedPutObject(bucket, object string, expires int64) (string, error) {
func (a s3API) presignedPutObject(bucket, object string, expires int64) (string, error) {
op := &operation{
HTTPServer: a.config.Endpoint,
HTTPMethod: "PUT",
Expand All @@ -618,7 +618,7 @@ func (a apiCore) presignedPutObject(bucket, object string, expires int64) (strin
}

// presignedGetObjectRequest - presigned get object request
func (a apiCore) presignedGetObjectRequest(bucket, object string, expires, offset, length int64) (*Request, error) {
func (a s3API) presignedGetObjectRequest(bucket, object string, expires, offset, length int64) (*Request, error) {
op := &operation{
HTTPServer: a.config.Endpoint,
HTTPMethod: "GET",
Expand All @@ -640,7 +640,7 @@ func (a apiCore) presignedGetObjectRequest(bucket, object string, expires, offse
}

// presignedGetObject - generate presigned get object URL.
func (a apiCore) presignedGetObject(bucket, object string, expires, offset, length int64) (string, error) {
func (a s3API) presignedGetObject(bucket, object string, expires, offset, length int64) (string, error) {
if err := invalidArgumentError(object); err != nil {
return "", err
}
Expand All @@ -655,7 +655,7 @@ func (a apiCore) presignedGetObject(bucket, object string, expires, offset, leng
}

// getObjectRequest wrapper creates a new getObject request.
func (a apiCore) getObjectRequest(bucket, object string, offset, length int64) (*Request, error) {
func (a s3API) getObjectRequest(bucket, object string, offset, length int64) (*Request, error) {
op := &operation{
HTTPServer: a.config.Endpoint,
HTTPMethod: "GET",
Expand Down Expand Up @@ -684,7 +684,7 @@ func (a apiCore) getObjectRequest(bucket, object string, offset, length int64) (
//
// For more information about the HTTP Range header.
// go to http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.
func (a apiCore) getObject(bucket, object string, offset, length int64) (io.ReadCloser, ObjectStat, error) {
func (a s3API) getObject(bucket, object string, offset, length int64) (io.ReadCloser, ObjectStat, error) {
if err := invalidArgumentError(object); err != nil {
return nil, ObjectStat{}, err
}
Expand Down Expand Up @@ -730,7 +730,7 @@ func (a apiCore) getObject(bucket, object string, offset, length int64) (io.Read
}

// deleteObjectRequest wrapper creates a new deleteObject request.
func (a apiCore) deleteObjectRequest(bucket, object string) (*Request, error) {
func (a s3API) deleteObjectRequest(bucket, object string) (*Request, error) {
op := &operation{
HTTPServer: a.config.Endpoint,
HTTPMethod: "DELETE",
Expand All @@ -740,7 +740,7 @@ func (a apiCore) deleteObjectRequest(bucket, object string) (*Request, error) {
}

// deleteObject deletes a given object from a bucket.
func (a apiCore) deleteObject(bucket, object string) error {
func (a s3API) deleteObject(bucket, object string) error {
if err := invalidBucketError(bucket); err != nil {
return err
}
Expand All @@ -756,43 +756,14 @@ func (a apiCore) deleteObject(bucket, object string) error {
if err != nil {
return err
}
if resp != nil {
if resp.StatusCode != http.StatusNoContent {
var errorResponse ErrorResponse
switch resp.StatusCode {
case http.StatusNotFound:
errorResponse = ErrorResponse{
Code: "NoSuchKey",
Message: "The specified key does not exist.",
Resource: separator + bucket + separator + object,
RequestID: resp.Header.Get("x-amz-request-id"),
HostID: resp.Header.Get("x-amz-id-2"),
}
case http.StatusForbidden:
errorResponse = ErrorResponse{
Code: "AccessDenied",
Message: "Access Denied.",
Resource: separator + bucket + separator + object,
RequestID: resp.Header.Get("x-amz-request-id"),
HostID: resp.Header.Get("x-amz-id-2"),
}
default:
errorResponse = ErrorResponse{
Code: resp.Status,
Message: resp.Status,
Resource: separator + bucket + separator + object,
RequestID: resp.Header.Get("x-amz-request-id"),
HostID: resp.Header.Get("x-amz-id-2"),
}
}
return errorResponse
}
}
// DeleteObject always responds with http '204' even for
// objects which do not exist. So no need to handle them
// specifically.
return nil
}

// headObjectRequest wrapper creates a new headObject request.
func (a apiCore) headObjectRequest(bucket, object string) (*Request, error) {
func (a s3API) headObjectRequest(bucket, object string) (*Request, error) {
op := &operation{
HTTPServer: a.config.Endpoint,
HTTPMethod: "HEAD",
Expand All @@ -802,7 +773,7 @@ func (a apiCore) headObjectRequest(bucket, object string) (*Request, error) {
}

// headObject retrieves metadata from an object without returning the object itself.
func (a apiCore) headObject(bucket, object string) (ObjectStat, error) {
func (a s3API) headObject(bucket, object string) (ObjectStat, error) {
if err := invalidBucketError(bucket); err != nil {
return ObjectStat{}, err
}
Expand Down Expand Up @@ -887,7 +858,7 @@ func (a apiCore) headObject(bucket, object string) (ObjectStat, error) {
/// Service Operations.

// listBucketRequest wrapper creates a new listBuckets request.
func (a apiCore) listBucketsRequest() (*Request, error) {
func (a s3API) listBucketsRequest() (*Request, error) {
op := &operation{
HTTPServer: a.config.Endpoint,
HTTPMethod: "GET",
Expand All @@ -897,7 +868,7 @@ func (a apiCore) listBucketsRequest() (*Request, error) {
}

// listBuckets list of all buckets owned by the authenticated sender of the request.
func (a apiCore) listBuckets() (listAllMyBucketsResult, error) {
func (a s3API) listBuckets() (listAllMyBucketsResult, error) {
req, err := a.listBucketsRequest()
if err != nil {
return listAllMyBucketsResult{}, err
Expand Down
Loading

0 comments on commit 1fe9233

Please sign in to comment.