module Web.Uploadcare.Internal
(
makeSignature
, apiHeaders
, request
) where
import qualified Crypto.Hash.MD5 as MD5
import qualified Crypto.Hash.SHA1 as SHA1
import Crypto.MAC.HMAC (hmac)
import Data.ByteString.Char8 (ByteString)
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Lazy as LBS
import Data.Char (toLower)
import Data.Hex (hex)
import Data.Time.Clock (getCurrentTime)
import Data.Time.Format (formatTime)
import Network.HTTP.Conduit
import Network.HTTP.Types.Header (RequestHeaders, hAccept, hContentType, hDate)
import Network.HTTP.Types.Method (Method)
import System.Locale (defaultTimeLocale)
import Web.Uploadcare.Client
jsonContentType :: ByteString
jsonContentType = "application/json"
makeSignature :: Client -> Method -> ByteString -> ByteString -> ByteString
-> ByteString
makeSignature client rMethod rPath rBody timestamp =
lowerHex . sign $ BS.intercalate "\n" [
rMethod
, lowerHex . MD5.hash $ rBody
, jsonContentType
, timestamp
, rPath
]
where
lowerHex = BS.map toLower . hex
sign = hmac SHA1.hash 64 $ secretKey client
apiHeaders :: Client -> ByteString -> ByteString -> RequestHeaders
apiHeaders client signature timestamp = [
("Authentication", auth)
, (hAccept, "application/vnd.uploadcare-v0.2+json")
, (hDate, timestamp)
, (hContentType, jsonContentType)
]
where
auth = BS.concat ["UploadCare ", publicKey client, ":", signature]
request :: Client -> Method -> ByteString -> IO (Response LBS.ByteString)
request client rMethod rPath = do
time <- getCurrentTime
let timestamp = toTimestamp time
let signature = makeSignature client rMethod rPath "" timestamp
let req = def {
method = rMethod
, host = "api.uploadcare.com"
, path = rPath
, requestHeaders = apiHeaders client signature timestamp
}
res <- withManager $ httpLbs req
return res
where
toTimestamp = BS.pack . formatTime defaultTimeLocale httpDateFormat
httpDateFormat = "%a, %d %b %Y %H:%M:%S GMT"