Chris Stryczynski
Chris Stryczynski

Reputation: 33891

How can I inspect/debug the body of a servant-client's request?

Full minimal example project available here: https://github.com/chrissound/217

I've read through https://docs.servant.dev/en/v0.16/cookbook/using-free-client/UsingFreeClient.html

Where I end up with:

type API = "square"
  :> Capture "n" Int
  :> ReqBody '[JSON] ClientInfo
  :> Get '[JSON] Int

api :: Proxy API
api = Proxy

myapitest = I.client api

getSquare :: Int -> ClientInfo -> Free ClientF Int
getSquare = Servant.Client.Free.client api

test :: IO ()
test = case getSquare 12 (ClientInfo "" "" 123 []) of
    Pure n ->
        putStrLn $ "ERROR: got pure result: " ++ show n
    Free (Throw err) ->
        putStrLn $ "ERROR: got error right away: " ++ show err
    Free (RunRequest req k) -> do
      burl <- parseBaseUrl "http://localhost:8000"
      mgr <- HTTP.newManager HTTP.defaultManagerSettings
      let req' = I.requestToClientRequest burl req
      putStrLn $ "Making request: " ++ show req'

However this approach seems to just output the below:

Making request: Request {
  host                 = "localhost"
  port                 = 8000
  secure               = False
  requestHeaders       = [("Accept","application/json;charset=utf-8,application/json"),("Content-Type","application/json;charset=utf-8")]
  path                 = "/square/12"
  queryString          = ""
  method               = "GET"
  proxy                = Nothing
  rawBody              = False
  redirectCount        = 10
  responseTimeout      = ResponseTimeoutDefault
  requestVersion       = HTTP/1.1
}

While I'm expecting a body to have some text present. The reason I expect this - because if send a request to a server and debug/inspect that - I do see a body with text present. So my question here is, why is servant saying the rawBody is False, and how do I actually get it to show the body?

The non debug code which actually sends the HTTP request is:

main :: IO ()
main = do
  putStrLn "Hello, Haskell!"
  run
  test

queries = myapitest 10 (ClientInfo "" "" 123 [])

run :: IO ()
run = do
  manager' <- newManager defaultManagerSettings
  res <- runClientM queries (mkClientEnv manager' (BaseUrl Http "localhost" 8000 ""))
  case res of
    Right (message) -> do
      pPrint message
    Left err -> do
      putStrLn $ "Error: "
      pPrint err

Upvotes: 3

Views: 460

Answers (1)

Donna
Donna

Reputation: 657

The answer is that it's hard and most solutions are not usable for applications handling many requests. You need to read the entire body into something like an MVar which you can then use. You can do this through a Middleware. However, since you consume the entire body you will need to put it back into the stream if it's suppose to be used by another middleware etc. This is still an open issue on the servant repository: https://github.com/haskell-servant/servant/issues/1120

Upvotes: 1

Related Questions