haskell-servant / haskell-servant/servant

How to do some initialisation before a nested generic sub api to avoid code duplication?

Open
#1,600 3 comments 0 reactions 0 assignees View on GitHub
Dominant language
Haskell
Stars
2k
Forks
427
Avg merge
2d 23h
Merged PRs (30d)
5

Description

Right now I have something like this:

```haskell
data MainAPI mode = MainAPI
{ subRoute :: mode :- "sub" :> Auth '[JWT] User :> NamedRoutes SubAPI
}

data SubAPI mode = SubAPI
{ subSubRoute1 :: mode :- Post [JSON] Result
, subSubRoute2 :: mode :- "omg" :> Get [JSON] Result
}
```

When implementing this I'd have to give to the `subRoute` a function of type `AuthResult User -> SubAPI ( AsServerT AppM )`. This doesn't allow me to fail the whole sub API if user was not successfully authenticated. Instead, I have to do this check on each of the individual `subSubRoute`s.

This becomes a problem if I have many deeply nested records. Then I have to duplicate a lot of initialization steps on each tree leaf, instead of just on the root node of particular branch that share this common initialization step.

For example, besides checking for `AuthResult` I might also want to initialize a `Haxl` environment that's going to be used in all of the sub APIs. This makes me think that maybe instead of `AuthResult User -> SubAPI ( AsServerT AppM )` the `NamedRoutes` combinator should expect a `AuthResult User -> AppM ( SubAPI ( AsServerT AppM ) )` instead. This would allow me to immediately invalidate this whole branch if user is not authenticated, and I can also do some shared AppM stuff that relates to all of the sub nodes.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.