module HTTP.Runner ( mkRunner, HttpRunner (..) ) where import Data.Aeson (FromJSON (..), Value, withObject, (.:)) import Data.Aeson.Types (Parser, Value (..), parseEither, parseMaybe) import Data.Function ((&)) import GHC.Exception (throw) import IOUtils (DemoActions (..)) import Network.HTTP.Req ( Scheme (..), Url, ) import UnliftIO (catchAny) import WebDriverPreCore.HTTP.Protocol ( Command(..), WebDriverException(..), parseWebDriverException) import Prelude hiding (log) import HTTP.HttpClient ( callWebDriver', mkRequest) import Data.Text (pack) -- ############# Runner ############# data HttpRunner = MkHttpRunner { run :: forall r. (FromJSON r) => Command r -> IO r, fullResponse :: forall r. (FromJSON r) => Command r -> IO Value } mkRunner :: Url 'Http -> Int -> DemoActions -> HttpRunner mkRunner driverUrl port da = MkHttpRunner { run = run driverUrl port da, fullResponse = logCall driverUrl port da } logCall :: forall r. Url 'Http -> Int -> DemoActions -> Command r -> IO Value logCall driverUrl port da cmd = do logCommand da cmd callWebDriver' da $ mkRequest driverUrl port cmd run :: forall r. (FromJSON r) => Url 'Http -> Int -> DemoActions -> Command r -> IO r run driverUrl port da@MkDemoActions {logShow} cmd = do rsp <- logCall driverUrl port da cmd r <- catchAny (parseResultIO rsp) ( \e -> logShow "Command Execution Failed" e >> throw e ) pure r logCommand :: DemoActions -> Command r -> IO () logCommand da@MkDemoActions {logShow} cmd = do logShow (">>>>> Command: " <> cmd.description <> " >>>>>\n") cmd case cmd of Get {} -> pure () Post {body} -> do da.logJSON "body" $ Object body PostEmpty {} -> pure () Delete {} -> pure () parseResultIO :: forall r. (FromJSON r) => Value -> IO r parseResultIO body = parseMaybe valueParser body & maybe ( throw $ ResponseParseException "No value property found in WebDriver response" body ) ( \val -> parseEither @_ @r parseJSON val & either (\e -> throw $ parseWebDriverException (pack e) val) pure ) valueParser :: Value -> Parser Value valueParser body = body & withObject "body value" (.: "value")