module Aws.S3.Commands.HeadObject
where

import           Aws.Core
import           Aws.S3.Core
import           Control.Applicative
import           Data.ByteString.Char8 ({- IsString -})
import qualified Data.ByteString.Char8 as B8
import           Data.Maybe
import qualified Data.Text             as T
import qualified Data.Text.Encoding    as T
import           Prelude
import qualified Network.HTTP.Conduit  as HTTP
import qualified Network.HTTP.Types    as HTTP

data HeadObject
    = HeadObject {
        HeadObject -> Bucket
hoBucket :: Bucket
      , HeadObject -> Bucket
hoObjectName :: Object
      , HeadObject -> Maybe Bucket
hoVersionId :: Maybe T.Text
      , HeadObject -> Maybe Bucket
hoIfMatch :: Maybe T.Text
      -- ^ Return the object only if its entity tag (ETag, which is an md5sum of the content) is the same as the one specified; otherwise, catch a 'StatusCodeException' with a status of 412 precondition failed.
      , HeadObject -> Maybe Bucket
hoIfNoneMatch :: Maybe T.Text
      -- ^ Return the object only if its entity tag (ETag, which is an md5sum of the content) is different from the one specified; otherwise, catch a 'StatusCodeException' with a status of 304 not modified.
      }
  deriving (Int -> HeadObject -> ShowS
[HeadObject] -> ShowS
HeadObject -> String
(Int -> HeadObject -> ShowS)
-> (HeadObject -> String)
-> ([HeadObject] -> ShowS)
-> Show HeadObject
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> HeadObject -> ShowS
showsPrec :: Int -> HeadObject -> ShowS
$cshow :: HeadObject -> String
show :: HeadObject -> String
$cshowList :: [HeadObject] -> ShowS
showList :: [HeadObject] -> ShowS
Show)

headObject :: Bucket -> T.Text -> HeadObject
headObject :: Bucket -> Bucket -> HeadObject
headObject Bucket
b Bucket
o = Bucket
-> Bucket
-> Maybe Bucket
-> Maybe Bucket
-> Maybe Bucket
-> HeadObject
HeadObject Bucket
b Bucket
o Maybe Bucket
forall a. Maybe a
Nothing Maybe Bucket
forall a. Maybe a
Nothing Maybe Bucket
forall a. Maybe a
Nothing

data HeadObjectResponse
    = HeadObjectResponse {
        HeadObjectResponse -> Maybe ObjectMetadata
horMetadata :: Maybe ObjectMetadata
      } deriving (Int -> HeadObjectResponse -> ShowS
[HeadObjectResponse] -> ShowS
HeadObjectResponse -> String
(Int -> HeadObjectResponse -> ShowS)
-> (HeadObjectResponse -> String)
-> ([HeadObjectResponse] -> ShowS)
-> Show HeadObjectResponse
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> HeadObjectResponse -> ShowS
showsPrec :: Int -> HeadObjectResponse -> ShowS
$cshow :: HeadObjectResponse -> String
show :: HeadObjectResponse -> String
$cshowList :: [HeadObjectResponse] -> ShowS
showList :: [HeadObjectResponse] -> ShowS
Show)

data HeadObjectMemoryResponse
    = HeadObjectMemoryResponse (Maybe ObjectMetadata)
    deriving (Int -> HeadObjectMemoryResponse -> ShowS
[HeadObjectMemoryResponse] -> ShowS
HeadObjectMemoryResponse -> String
(Int -> HeadObjectMemoryResponse -> ShowS)
-> (HeadObjectMemoryResponse -> String)
-> ([HeadObjectMemoryResponse] -> ShowS)
-> Show HeadObjectMemoryResponse
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> HeadObjectMemoryResponse -> ShowS
showsPrec :: Int -> HeadObjectMemoryResponse -> ShowS
$cshow :: HeadObjectMemoryResponse -> String
show :: HeadObjectMemoryResponse -> String
$cshowList :: [HeadObjectMemoryResponse] -> ShowS
showList :: [HeadObjectMemoryResponse] -> ShowS
Show)

-- | ServiceConfiguration: 'S3Configuration'
instance SignQuery HeadObject where
    type ServiceConfiguration HeadObject = S3Configuration
    signQuery :: forall queryType.
HeadObject
-> ServiceConfiguration HeadObject queryType
-> SignatureData
-> SignedQuery
signQuery HeadObject {Maybe Bucket
Bucket
hoBucket :: HeadObject -> Bucket
hoObjectName :: HeadObject -> Bucket
hoVersionId :: HeadObject -> Maybe Bucket
hoIfMatch :: HeadObject -> Maybe Bucket
hoIfNoneMatch :: HeadObject -> Maybe Bucket
hoBucket :: Bucket
hoObjectName :: Bucket
hoVersionId :: Maybe Bucket
hoIfMatch :: Maybe Bucket
hoIfNoneMatch :: Maybe Bucket
..} = S3Query
-> S3Configuration queryType -> SignatureData -> SignedQuery
forall qt.
S3Query -> S3Configuration qt -> SignatureData -> SignedQuery
s3SignQuery S3Query {
                                   s3QMethod :: Method
s3QMethod = Method
Head
                                 , s3QBucket :: Maybe ByteString
s3QBucket = ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just (ByteString -> Maybe ByteString) -> ByteString -> Maybe ByteString
forall a b. (a -> b) -> a -> b
$ Bucket -> ByteString
T.encodeUtf8 Bucket
hoBucket
                                 , s3QObject :: Maybe ByteString
s3QObject = ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just (ByteString -> Maybe ByteString) -> ByteString -> Maybe ByteString
forall a b. (a -> b) -> a -> b
$ Bucket -> ByteString
T.encodeUtf8 Bucket
hoObjectName
                                 , s3QSubresources :: Query
s3QSubresources = [Maybe (ByteString, Bucket)] -> Query
forall a. QueryLike a => a -> Query
HTTP.toQuery [
                                                       (ByteString
"versionId" :: B8.ByteString,) (Bucket -> (ByteString, Bucket))
-> Maybe Bucket -> Maybe (ByteString, Bucket)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Bucket
hoVersionId
                                                     ]
                                 , s3QQuery :: Query
s3QQuery = []
                                 , s3QContentType :: Maybe ByteString
s3QContentType = Maybe ByteString
forall a. Maybe a
Nothing
                                 , s3QContentMd5 :: Maybe (Digest MD5)
s3QContentMd5 = Maybe (Digest MD5)
forall a. Maybe a
Nothing
                                 , s3QAmzHeaders :: RequestHeaders
s3QAmzHeaders = []
                                 , s3QOtherHeaders :: RequestHeaders
s3QOtherHeaders = [Maybe Header] -> RequestHeaders
forall a. [Maybe a] -> [a]
catMaybes [
                                                       (HeaderName
"if-match",) (ByteString -> Header)
-> (Bucket -> ByteString) -> Bucket -> Header
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bucket -> ByteString
T.encodeUtf8 (Bucket -> Header) -> Maybe Bucket -> Maybe Header
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Bucket
hoIfMatch
                                                     , (HeaderName
"if-none-match",) (ByteString -> Header)
-> (Bucket -> ByteString) -> Bucket -> Header
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bucket -> ByteString
T.encodeUtf8 (Bucket -> Header) -> Maybe Bucket -> Maybe Header
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Bucket
hoIfNoneMatch
                                                     ]
                                 , s3QRequestBody :: Maybe RequestBody
s3QRequestBody = Maybe RequestBody
forall a. Maybe a
Nothing
                                 }

instance ResponseConsumer HeadObject HeadObjectResponse where
    type ResponseMetadata HeadObjectResponse = S3Metadata
    responseConsumer :: Request
-> HeadObject
-> IORef (ResponseMetadata HeadObjectResponse)
-> HTTPResponseConsumer HeadObjectResponse
responseConsumer Request
httpReq HeadObject{} IORef (ResponseMetadata HeadObjectResponse)
_ Response (ConduitM () ByteString (ResourceT IO) ())
resp
        | Status
status Status -> Status -> Bool
forall a. Eq a => a -> a -> Bool
== Status
HTTP.status200 = Maybe ObjectMetadata -> HeadObjectResponse
HeadObjectResponse (Maybe ObjectMetadata -> HeadObjectResponse)
-> (ObjectMetadata -> Maybe ObjectMetadata)
-> ObjectMetadata
-> HeadObjectResponse
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ObjectMetadata -> Maybe ObjectMetadata
forall a. a -> Maybe a
Just (ObjectMetadata -> HeadObjectResponse)
-> ResourceT IO ObjectMetadata -> ResourceT IO HeadObjectResponse
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> RequestHeaders -> ResourceT IO ObjectMetadata
forall (m :: * -> *).
MonadThrow m =>
RequestHeaders -> m ObjectMetadata
parseObjectMetadata RequestHeaders
headers
        | Status
status Status -> Status -> Bool
forall a. Eq a => a -> a -> Bool
== Status
HTTP.status404 = HeadObjectResponse -> ResourceT IO HeadObjectResponse
forall a. a -> ResourceT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (HeadObjectResponse -> ResourceT IO HeadObjectResponse)
-> HeadObjectResponse -> ResourceT IO HeadObjectResponse
forall a b. (a -> b) -> a -> b
$ Maybe ObjectMetadata -> HeadObjectResponse
HeadObjectResponse Maybe ObjectMetadata
forall a. Maybe a
Nothing
        | Bool
otherwise = Request -> HTTPResponseConsumer HeadObjectResponse
forall (m :: * -> *) a.
MonadThrow m =>
Request -> Response (ConduitM () ByteString m ()) -> m a
throwStatusCodeException Request
httpReq Response (ConduitM () ByteString (ResourceT IO) ())
resp
      where
        status :: Status
status  = Response (ConduitM () ByteString (ResourceT IO) ()) -> Status
forall body. Response body -> Status
HTTP.responseStatus    Response (ConduitM () ByteString (ResourceT IO) ())
resp
        headers :: RequestHeaders
headers = Response (ConduitM () ByteString (ResourceT IO) ())
-> RequestHeaders
forall body. Response body -> RequestHeaders
HTTP.responseHeaders   Response (ConduitM () ByteString (ResourceT IO) ())
resp

instance Transaction HeadObject HeadObjectResponse

instance AsMemoryResponse HeadObjectResponse where
    type MemoryResponse HeadObjectResponse = HeadObjectMemoryResponse
    loadToMemory :: HeadObjectResponse
-> ResourceT IO (MemoryResponse HeadObjectResponse)
loadToMemory (HeadObjectResponse Maybe ObjectMetadata
om) = HeadObjectMemoryResponse -> ResourceT IO HeadObjectMemoryResponse
forall a. a -> ResourceT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe ObjectMetadata -> HeadObjectMemoryResponse
HeadObjectMemoryResponse Maybe ObjectMetadata
om)