haskell-servant / haskell-servant/servant

Redirect combinator ?

Open
#117 28 comments 5 reactions 0 assignees View on GitHub
enhancement rfc servant-api servant-server
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

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.