packages feed

pagerduty-0.0.0: src/Network/PagerDuty/Internal/IO.hs

{-# LANGUAGE OverloadedStrings   #-}
{-# LANGUAGE ScopedTypeVariables #-}

-- Module      : Network.PagerDuty.Internal.IO
-- Copyright   : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
-- License     : This Source Code Form is subject to the terms of
--               the Mozilla Public License, v. 2.0.
--               A copy of the MPL can be found in the LICENSE file or
--               you can obtain it at http://mozilla.org/MPL/2.0/.
-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
-- Stability   : experimental
-- Portability : non-portable (GHC extensions)

module Network.PagerDuty.Internal.IO where

import           Control.Monad
import           Control.Monad.IO.Class
import           Data.Aeson                       hiding (Error)
import qualified Data.ByteString.Lazy             as LBS
import           Data.Monoid
import qualified Data.Text                        as Text
import           Network.HTTP.Client              (Manager, httpLbs)
import qualified Network.HTTP.Client              as Client
import           Network.HTTP.Types
import           Network.PagerDuty.Internal.Types

request :: (MonadIO m, ToJSON a, FromJSON b)
        => Manager
        -> Logger
        -> a
        -> Client.Request
        -> m (Either Error b)
request m l x rq = msg >> liftIO (httpLbs raw m) >>= response l
  where
    msg = debug l ("[Raw Request]\n" <> Text.pack (show raw))

    raw = rq
        { Client.secure         = True
        , Client.port           = 443
        , Client.requestHeaders = headers
        , Client.requestBody    = Client.RequestBodyLBS (encode x)
        }

    headers =
        [ ("Content-Type", "application/json")
        , ("Accept",       "application/json")
        ]

response :: forall m b. (MonadIO m, FromJSON b)
         => Logger
         -> Client.Response LBS.ByteString
         -> m (Either Error b)
response l rs = case statusCode (Client.responseStatus rs) of
    200 -> success
    201 -> success
    400 -> failure
    500 -> failure
    n   -> return . Left $ unhandled n
  where
    success = maybe (Left unknown) Right `liftM` parse
    failure = maybe (Left unknown) Left  `liftM` parse

    unhandled n = Internal $
        "PagerDuty returned unhandled status code: "
            <> Text.pack (show n)

    unknown = Internal $
        "Unable to parse response into a PagerDuty API compatible type: "
            <> Text.pack (show body)

    parse :: FromJSON a => m (Maybe a)
    parse = msg >> return (decode body)

    msg = debug l ("[Raw Response]\n" <> Text.pack (show rs))

    body = Client.responseBody rs