module Snap.AtlassianConnect.NetworkCommon
( HttpResponseCode
, ProductErrorResponse(..)
, AccessTokenResponse(..)
, AccessToken(..)
, AccessTokenType(..)
, responder
) where
import Data.Aeson
import qualified Data.ByteString.Lazy as BL
import Data.Maybe (fromMaybe)
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import Data.Time.Units
import GHC.Generics
import Text.Read (readMaybe)
type HttpResponseCode = Int
data ProductErrorResponse = ProductErrorResponse
{ perCode :: HttpResponseCode
, perMessage :: T.Text
} deriving (Show, Generic)
data AccessTokenResponse = AccessTokenResponse
{ atrAccessToken :: AccessToken
, atrExpiresIn :: Second
, atrTokenType :: AccessTokenType
}
instance FromJSON AccessTokenResponse where
parseJSON = withObject "AccessTokenResponse" $ \v -> AccessTokenResponse
<$> (AccessToken <$> v .: "access_token")
<*> (fromInteger <$> v .: "expires_in")
<*> ((fromMaybe UnknownAccessTokenType . readMaybe) <$> v .: "token_type")
data AccessToken = AccessToken T.Text
data AccessTokenType
= Bearer
| UnknownAccessTokenType
deriving (Eq, Enum, Read)
responder :: FromJSON a => Int -> BL.ByteString -> Either ProductErrorResponse (Maybe a)
responder responseCode body
| responseCode == 204 = Right Nothing
| 200 <= responseCode && responseCode < 300 =
case eitherDecode body of
Right jsonResponse -> Right . Just $ jsonResponse
Left err -> Left $ ProductErrorResponse responseCode (T.pack $ "Could not parse the json response: " ++ show err)
| otherwise = Left $ ProductErrorResponse responseCode (T.decodeUtf8 . BL.toStrict $ body)