Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- {-# LANGUAGE DataKinds #-}
- {-# LANGUAGE DeriveGeneric #-}
- {-# LANGUAGE FlexibleContexts #-}
- {-# LANGUAGE FlexibleInstances #-}
- {-# LANGUAGE GeneralizedNewtypeDeriving #-}
- {-# LANGUAGE MultiParamTypeClasses #-}
- {-# LANGUAGE OverloadedStrings #-}
- {-# LANGUAGE RecordWildCards #-}
- {-# LANGUAGE TypeFamilies #-}
- {-# LANGUAGE TupleSections #-}
- module Api (
- Api,
- Connection,
- MonadApi(..),
- call,
- getJ,
- postJ,
- putJ,
- req,
- reqJ,
- reqS,
- withApi,
- withApiConfig,
- withApiHttp,
- withApiHttps,
- withEndpoint,
- withOption,
- withPath,
- withPaths
- )
- where
- import Control.Applicative
- import Control.Monad.Catch
- import Control.Monad.IO.Class
- import Control.Monad.Reader
- import Data.Aeson
- import Data.ByteString (ByteString)
- import Data.Proxy (Proxy)
- import Data.Semigroup hiding (Option)
- import Data.Text
- import Data.Typeable
- import GHC.Generics
- import Network.HTTP.Client.MultipartFormData (Part)
- import Network.HTTP.Req hiding (req)
- import qualified Network.HTTP.Req as Req
- type Connection scheme = (Url scheme, Option scheme)
- data InvalidUrlException = InvalidUrlException ByteString deriving (Show, Typeable)
- instance Exception InvalidUrlException
- newtype Api scheme a = Api (ReaderT (Connection scheme) (ReaderT HttpConfig IO) a) deriving (Functor, Applicative, Monad, MonadIO, MonadReader (Connection scheme), MonadCatch, MonadThrow, MonadPlus, Alternative)
- instance MonadHttp (Api scheme) where
- handleHttpException = throwM
- getHttpConfig = Api $ lift ask
- class (MonadReader (Connection scheme) m, MonadHttp m) => MonadApi scheme m
- instance MonadApi scheme (Api scheme)
- withApiConfig :: MonadIO m => HttpConfig -> Connection scheme -> Api scheme a -> m a
- withApiConfig config connection (Api call) = liftIO $ runReaderT (runReaderT call connection) config
- withApi :: MonadIO m => Connection scheme -> Api scheme a -> m a
- withApi = withApiConfig defaultHttpConfig
- withApiHttp :: (MonadIO m, MonadThrow m) => ByteString -> Api Http a -> m a
- withApiHttp url call = case parseUrlHttp url of
- Nothing -> throwM $ InvalidUrlException url
- Just connection -> withApi connection call
- withApiHttps :: (MonadIO m, MonadThrow m) => ByteString -> Api Https a -> m a
- withApiHttps url call = case parseUrlHttps url of
- Nothing -> throwM $ InvalidUrlException url
- Just connection -> withApi connection call
- withOption :: MonadReader (Connection scheme) m => Option scheme -> m a -> m a
- withOption option call = local modify call
- where
- modify (url, options) = (url, options <> option)
- withPath :: MonadReader (Connection scheme) m => Text -> m a -> m a
- withPath path call = local modify call
- where
- modify (url, options) = (url /: path, options)
- withPaths :: MonadReader (Connection scheme) m => [Text] -> m a -> m a
- withPaths [] call = call
- withPaths (p:ps) call = withPath p $ withPaths ps call
- withEndpoint :: MonadReader (Connection scheme) m => Text -> m a -> m a
- withEndpoint endpoint = withPaths $ splitOn "/" endpoint
- call :: (MonadApi scheme m, HttpBodyAllowed (AllowsBody method) (ProvidesBody body), HttpMethod method, HttpBody body, HttpResponse response) => method -> body -> Proxy response -> m response
- call method body response = do
- (url, options) <- ask
- Req.req method url body response options
- req :: (MonadApi scheme m, HttpBodyAllowed (AllowsBody method) (ProvidesBody body), HttpMethod method, HttpBody body, HttpResponse response) => method -> body -> Proxy response -> m (HttpResponseBody response)
- req method body response = responseBody <$> call method body response
- reqJ :: (MonadApi scheme m, HttpBodyAllowed (AllowsBody method) (ProvidesBody body), HttpMethod method, HttpBody body, FromJSON a) => method -> body -> m a
- reqJ method body = req method body jsonResponse
- reqS :: (MonadApi scheme m, HttpBodyAllowed (AllowsBody method) (ProvidesBody body), HttpMethod method, HttpBody body) => method -> body -> m ByteString
- reqS method body = req method body bsResponse
- req_ :: (MonadApi scheme m, HttpBodyAllowed (AllowsBody method) (ProvidesBody body), HttpMethod method, HttpBody body) => method -> body -> m ()
- req_ method body = req method body ignoreResponse
- getJ :: (MonadApi scheme m, FromJSON a) => m a
- getJ = reqJ GET NoReqBody
- getS :: MonadApi scheme m => m ByteString
- getS = reqS GET NoReqBody
- postJ :: (MonadApi scheme m, ToJSON up, FromJSON down) => up -> m down
- postJ = reqJ POST . ReqBodyJson
- postJ_ :: (MonadApi scheme m, ToJSON up) => up -> m ()
- postJ_ = req_ POST . ReqBodyJson
- putJ :: (MonadApi scheme m, ToJSON up, FromJSON down) => up -> m down
- putJ = reqJ PUT . ReqBodyJson
- delete_ :: MonadApi scheme m => m ()
- delete_ = req_ DELETE NoReqBody
- deleteJ :: (MonadApi scheme m, FromJSON a) => m a
- deleteJ = req DELETE NoReqBody jsonResponse
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement