Home > Mobile >  How to access a response status in the middleware?
How to access a response status in the middleware?

Time:11-16

I have a WAI middleware:

myMiddleware :: WAI.Middleware
myMiddleware prevApp req respond = do
  resp :: ResponseReceived <- prevApp req respond  --  SIC!
  let path = T.intercalate "/" $ WAI.pathInfo req
      method = WAI.requestMethod req
      -- Q: how to get the response's status    <----  ???
      --respStatus = WAI.responseStatus resp    <----  ???
  pure resp

where I want to get a response's status (it was 404, or 200, or whatever). But how to do it if it is not a Response more but ResponseReceived? I have only one idea, to create, let's say, IORef and to pass it to my function:

-- an illustration of the idea:
...
  xxx <- newIORef []
  let myRespond resp = do
        atomicWriteIORef' xxx [1,2]
        r <- respond resp
        pure r
  resp <- prevApp req myRespond
...

but 1) I don't know is it the simplest and most typical solution; 2) how lightweight is a newIORef? Is it OK to create it on every request to my application?

I hit this problem many times before, the main question is: how to access the response in the middleware? The final response, I mean if the application answered with 404, so to be able to get access to the status 404 in the middleware.

CodePudding user response:

The general idea is to write a piece of middleware that looks like this:

mid :: Middleware
mid app req respond = app req respond'
  where respond' res = do
          let status = responseStatus res
          putStrLn $ "status="    show status
          respond res

That is, you don't try to access the ResponseReceived at all -- it's a sort of "sentinel" value that contains no information that can be accessed anyway. Instead, you override the respond' callback passed to the application with one that accesses the outgoing response before continuing with the original respond call.

Now, what you do with the status value depends on what you're trying to accomplish. Creating a new IORef might be useful, and it's a cheap operation, so you can certainly create one (or a few thousand) for every request. However, it doesn't seem like it would be tremendously helpful. What function are you going to pass it to once you've created it? And if you're able to pass a new IORef to your function for every request, why not just pass the status directly?

  • Related