module Redmine.Rest(expandOptions
, increaseQueryRange
, initOpt
, toJsonBody
, queryRedmineAvecOptions
, runQuery
, ParamRest
) where
import Data.Aeson
import Data.Monoid
import qualified Data.Map as Map
import Redmine.Types
import Redmine.Manager
import qualified Data.ByteString as S
import qualified Data.ByteString.Char8 as S8
import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString.Lazy.Char8 as L8
import Network.Connection (TLSSettings (..))
import Network.HTTP.Conduit
import Network.HTTP.Base (RequestMethod(..))
import Network.HTTP.Types.Header (Header, hContentType)
import qualified Data.Text as T
import Debug.Trace
queryRedmine :: RedmineMng -> RequestMethod -> S.ByteString -> (Maybe S.ByteString) -> IO L.ByteString
queryRedmine mng m req b = do
request <- creerRqt mng m req b
let settings = mkManagerSettings (TLSSettingsSimple True False False) Nothing
response <- withManagerSettings settings $ httpLbs request
return $ responseBody response
creerRqt :: RedmineMng -> RequestMethod -> S.ByteString -> Maybe S.ByteString -> IO Request
creerRqt (RedmineMng h) m r body = fmap (f body) $ parseUrl $ S8.unpack (h <> r)
where
ct = (hContentType, "application/json") :: Header
f (Just b) req = trace (S8.unpack b) req'
where req' = req{method = S8.pack . show $ m, requestHeaders = ct : requestHeaders req, requestBody = RequestBodyBS b}
f Nothing req = req{method = S8.pack . show $ m, requestHeaders = ct : requestHeaders req}
creerRqt (RedmineMngWithProxy h u p) m r b = fmap (addProxy u p) (creerRqt (RedmineMng h) m r b)
creerRqt (RedmineMngWithAuth h l pass) m r b = fmap (applyBasicAuth l pass) (creerRqt (RedmineMng h) m r b)
creerRqt (RedmineMngWithAuthAndProxy h l pass u p) m r b = fmap (applyBasicAuth l pass) (creerRqt (RedmineMngWithProxy h u p) m r b)
type ParamRest = Map.Map S.ByteString S.ByteString
expandOptions :: ParamRest -> S.ByteString
expandOptions = Map.foldrWithKey (\k a res -> res <> k <> "=" <> a <> "&") "?"
bsAInt :: S.ByteString -> Int
bsAInt = read . S8.unpack
increaseQueryRange :: ParamRest -> ParamRest
increaseQueryRange param =
let offset = bsAInt $ Map.findWithDefault "0" "offset" param
limit = bsAInt $ Map.findWithDefault "100" "limit" param
nouvelOffset = offset + limit
in Map.insert "offset" (S8.pack $ show nouvelOffset) param
queryRedmineAvecOptions :: (FromJSON a, Monoid a, Collection a) =>
RedmineMng -> RequestMethod -> S.ByteString -> ParamRest -> Maybe S.ByteString -> Manager -> IO( Maybe a)
queryRedmineAvecOptions redmineMng m req param body mng =
do
request <- creerRqt redmineMng m (req <> expandOptions param) body
let settings = mkManagerSettings (TLSSettingsSimple True False False) Nothing
response <- withManagerSettings settings $ httpLbs request
parsedRes <- debugResult . eitherDecode . responseBody $ response
case parsedRes of
Just a | 0 == longueur a -> return $ Just a
| otherwise ->
do let hausse = increaseQueryRange param
reste <- queryRedmineAvecOptions redmineMng m req hausse body mng
case reste of
Just b -> return . Just $ mappend a b
Nothing -> return $ Just a
Nothing -> return Nothing
debugResult :: Either String a -> IO(Maybe a)
debugResult res = case res of
Left msg -> putStrLn msg >> return Nothing
Right v -> return (Just v)
runQuery :: FromJSON a => RedmineMng -> RequestMethod -> S.ByteString -> Maybe S.ByteString -> IO( Maybe a)
runQuery mng m requete body = do
toto <- queryRedmine mng m requete body
(debugResult . eitherDecode) toto
toJsonBody :: ToJSON a => a -> Maybe S8.ByteString
toJsonBody = Just . L8.toStrict . encode . toJSON
initOpt = Map.fromList [("offset","0"), ("limit","100")] :: Map.Map S8.ByteString S8.ByteString