haskell-servant / haskell-servant/servant
Redirect combinator ?
- Dominant language
- Haskell
- Stars
- 2k
- Forks
- 427
- Avg merge
- 2d 23h
- Merged PRs (30d)
- 5
Description
Hi everyone,
This has been discussed a bit offline but I thought I should open an issue and throw some code in here for discussion and potential inclusion in _servant_. The deal here is to offer a proper generic combinator for redirection.
One thing however is that we have some decent machinery for generating type safe links, which of course looks like a good basis to build the redirect combinator on.
For a _servant-0.4_ compatible solution, one could consider such an implementation:
``` haskell
class KnownMethod (c :: [*] -> * -> *) where
methodOf :: Proxy c -> Method
instance KnownMethod Delete where
methodOf _ = methodDelete
instance KnownMethod Get where
methodOf _ = methodGet
instance KnownMethod Patch where
methodOf _ = methodPatch
instance KnownMethod Post where
methodOf _ = methodPost
instance KnownMethod Put where
methodOf _ = methodPut
data Redirect (c :: [*] -> * -> *) lnk api
instance (KnownMethod c, IsElem lnk api, HasLink lnk)
=> HasServer (Redirect c lnk api) where
type ServerT (Redirect c lnk api) m
= m URI
route Proxy getLink req respond
| null (pathInfo req) && requestMethod req == methodOf pc = do
res <- runEitherT getLink
case res of
Left err -> respond . succeedWith $ responseServantErr err
Right lnk -> respond . succeedWith $
responseLBS seeOther303 [("Location", fromString ("/" ++ show lnk))] ""
| null (pathInfo req) && requestMethod req /= methodOf pc =
respond $ failWith WrongMethod
| otherwise = respond $ failWith NotFound
where pc = Proxy :: Proxy c
```
(complete usable code [here](http://lpaste.net/134244))
The only thing I'm not happy about is that I hardcode the `303` status code. We could probably take an additional parameter of kind `Natural` (type-level natural number) and only have the `HasServer` instance when that number is a valid status code used for redirects.
Thoughts?
PS: I use the above combinator in a work project already and hence would be keen to eventually include such a combinator in _servant_ itself since I would otherwise have to maintain that combinator independently and adapt it for any change to _servant_/_servant-server_.
Contributor guide
Assessment
This issue has not been assessed yet.