content: --
  -- MinIO Haskell SDK, (C) 2018 MinIO, Inc.
  --
  -- Licensed under the Apache License, Version 2.0 (the "License");
  -- you may not use this file except in compliance with the License.
  -- You may obtain a copy of the License at
  --
  --     http://www.apache.org/licenses/LICENSE-2.0
  --
  -- Unless required by applicable law or agreed to in writing, software
  -- distributed under the License is distributed on an "AS IS" BASIS,
  -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  -- See the License for the specific language governing permissions and
  -- limitations under the License.
  --
  
  module Network.Minio.APICommon where
  
  import qualified Conduit as C
  import qualified Data.ByteString as BS
  import qualified Data.ByteString.Lazy as LB
  import Data.Conduit.Binary (sourceHandleRange)
  import qualified Data.Text as T
  import Lib.Prelude
  import qualified Network.HTTP.Conduit as NC
  import qualified Network.HTTP.Types as HT
  import Network.Minio.Data
  import Network.Minio.Data.Crypto
  import Network.Minio.Errors
  
  sha256Header :: ByteString -> HT.Header
  sha256Header = ("x-amz-content-sha256",)
  
  -- | This function throws an error if the payload is a conduit (as it
  -- will not be possible to re-read the conduit after it is consumed).
  getPayloadSHA256Hash :: Payload -> Minio ByteString
  getPayloadSHA256Hash (PayloadBS bs) = return $ hashSHA256 bs
  getPayloadSHA256Hash (PayloadH h off size) =
    hashSHA256FromSource $
      sourceHandleRange
        h
        (return . fromIntegral $ off)
        (return . fromIntegral $ size)
  getPayloadSHA256Hash (PayloadC _ _) = throwIO MErrVUnexpectedPayload
  
  getRequestBody :: Payload -> NC.RequestBody
  getRequestBody (PayloadBS bs) = NC.RequestBodyBS bs
  getRequestBody (PayloadH h off size) =
    NC.requestBodySource size $
      sourceHandleRange
        h
        (return . fromIntegral $ off)
        (return . fromIntegral $ size)
  getRequestBody (PayloadC n src) = NC.requestBodySource n src
  
  mkStreamingPayload :: Payload -> Payload
  mkStreamingPayload payload =
    case payload of
      PayloadBS bs ->
        PayloadC
          (fromIntegral $ BS.length bs)
          (C.sourceLazy $ LB.fromStrict bs)
      PayloadH h off len ->
        PayloadC len $
          sourceHandleRange
            h
            (return . fromIntegral $ off)
            (return . fromIntegral $ len)
      _ -> payload
  
  isStreamingPayload :: Payload -> Bool
  isStreamingPayload (PayloadC _ _) = True
  isStreamingPayload _ = False
  
  -- | Checks if the connect info is for Amazon S3.
  isAWSConnectInfo :: ConnectInfo -> Bool
  isAWSConnectInfo ci = ".amazonaws.com" `T.isSuffixOf` connectHost ci
  
  bucketHasPeriods :: Bucket -> Bool
  bucketHasPeriods b = isJust $ T.find (== '.') b
  