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?