1

I'm using the following code to check if a file exists on S3. Unfortunately, I'm never getting an error. It seems to be that the AWS SDK should return an error but that it doesn't because the body is empty and cannot be deserialized in a S3 error.

How can I work around this issue? A solution would be to check myself for the 404 in the response but I don't find a way to do that with the task.

s3.headObject(headRequest).continue({ task in
            task.
            if let taskError = task.error {
                if let error = task.error as NSError? {
                    if error.domain == AWSS3ErrorDomain && AWSS3ErrorType(rawValue: error.code) == AWSS3ErrorType.noSuchKey {
                        return successBlock(false)
                    }
                }
                errorBlock(taskError)
                return nil
            }
            return successBlock(true)
        });

(The same issue arises if the error is a 403)

Kamchatka
  • 3,597
  • 4
  • 38
  • 69
  • Is there a `task.result`? Does it provide anything of interest? – Michael - sqlbot Dec 17 '16 at 18:49
  • no, task.result is nil (b/c the body is empty) – Kamchatka Dec 17 '16 at 19:19
  • May I ask why you are checking if the file exist? For many operations this is unnecessary and the check could be considered a noop (no-operation). Most requests will indicate if the file exists or not when executed with the exception of a PUT. – Joshua Briefman Dec 25 '16 at 02:42
  • @JoshuaBriefman I want to get the metadata of the file to check a MD5 header, and avoid re-uploading it. It wasn't precise enough of me to say that I'm only using the HEAD request to only check if the file exists. – Kamchatka Jan 03 '17 at 16:16
  • The object may or may not have an MD5, if the object was uploaded using Multipart then unless you know the part size which was used to upload it, you will not be able to compare and confirm an MD5 hash. This is because multipart doesn't store an MD5 hash itself. Objects must be at least 5MB and be 1 or more parts to use multipart. The SDK may select multipart for you in some cases depending on the API you uploaded with. – Joshua Briefman Jan 03 '17 at 17:17
  • To compute the hash for an object which was uploaded with multipart. You first must know the part size which was used during the original upload. Then you can calculate the hash to compare to the one on the S3 object using this SO Answer http://stackoverflow.com/questions/12186993/what-is-the-algorithm-to-compute-the-amazon-s3-etag-for-a-file-larger-than-5gb#answer-19896823 – Joshua Briefman Jan 03 '17 at 17:19
  • As far as getting that header, it should still be available in the Rest API HEAD response, but from the looks of that code I can't say it's being provided to the task. Here is a link to a snippet to get the headers: http://stackoverflow.com/questions/8530215/with-the-awsios-sdk-how-do-you-do-a-head-request-on-an-s3-object and here is the S3 Rest API spec for HEAD: http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectHEAD.html – Joshua Briefman Jan 03 '17 at 17:24

1 Answers1

-2

The issue here is that you will never receive a Body because a HEAD request is designed not to return one.

RFC7230 - Section 3.3

Responses to the HEAD request method (Section 4.3.2 of [RFC7231]) never include a message body because the associated response header fields (e.g., Transfer-Encoding, Content-Length, etc.), if present, indicate only what their values would have been if the request method had been GET (Section 4.3.1 of [RFC7231]).

However, you can still get an HTTP status code, which should indicate the state of any error which occurred.

Community
  • 1
  • 1
Joshua Briefman
  • 3,783
  • 2
  • 22
  • 33
  • 1
    I'm fine with not receiving a body, but the AWS SDK should deal with this and return the proper error. I think the AWS SDK tries to extract an error code from the body but cannot (b/c of what you said) and as a consequence returns a success code. – Kamchatka Jan 03 '17 at 16:14