haskell-servant / haskell-servant/servant
Passing values from `addAuthCheck` to `tweakResponse`
- Dominant language
- Haskell
- Stars
- 2k
- Forks
- 427
- Avg merge
- 2d 23h
- Merged PRs (30d)
- 5
Description
# Problem
How can I:
* `tweakResponse :: (RouteResult Response -> RouteResult Response) -> Router env -> Router env `
based on some value generated in `DelayedIO`, in
* `addAuthCheck :: Delayed env (a -> b) -> DelayedIO a -> Delayed env b`,
in `HasServer` for some custom combinator of mine?
# Use case
E.g. to add a response header based on auth check result — behind the combinator’s user’s back, i.e. without requiring the user to do anything particular in their handlers.
# Current solutions
`HasServer.route` is called only once ever.
So… for now, I went with `unsafePerformIO` to create a `TVar (Map (Mem.StableName Wai.Request) SomeData)` (or `StmContainers.Map`) shared by `tweakResponse` and `addAuthCheck` — in the scope of this particular `HasServer` instance.
It'’s not really `tweakResponse`, since it doesn’t have access to `Request` (to use as the `Map` key), but if you have a function like:
```haskell
addRespHeader :: Wai.Request -> RouteResult Wai.Response -> IO (RouteResult Wai.Response)
```
then it can be used:
```haskell
route Proxy context subserver =
map
(\app req cont -> app req (cont <=< addRespHeader req))
(route (Proxy @api) context (addAuthCheck subserver someAuthCheck))
```
Also, you have to remember to clean up these map’s entries in `Request`’s finalizer…
```haskell
liftIO $ Mem.addFinalizer req (atomically $ Map.delete reqId headerStore)
```
But this is sooooo hackish… Halp. \^.\^
-----
/cc @alpmestan
Contributor guide
Assessment
This issue has not been assessed yet.