{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE ScopedTypeVariables #-} module Servant.API.Alternative where import Data.Monoid import Data.Proxy import Servant.Server -- | Union of two APIs, first takes precedence in case of overlap. -- -- Example: -- -- > type MyApi = "books" :> Get [Book] -- GET /books -- > :<|> "books" :> ReqBody Book :> Post Book -- POST /books data a :<|> b = a :<|> b infixr 8 :<|> -- | A server for @a ':<|>' b@ first tries to match the request again the route -- represented by @a@ and if it fails tries @b@. You must provide a request -- handler for each route. -- -- > type MyApi = "books" :> Get [Book] -- GET /books -- > :<|> "books" :> ReqBody Book :> Post Book -- POST /books -- > -- > server :: Server MyApi -- > server = listAllBooks :<|> postBook -- > where listAllBooks = ... -- > postBook book = ... instance (HasServer a, HasServer b) => HasServer (a :<|> b) where type Server (a :<|> b) = Server a :<|> Server b route Proxy (a :<|> b) request respond = route pa a request $ \ mResponse -> if isMismatch mResponse then route pb b request $ \mResponse' -> respond (mResponse <> mResponse') else respond mResponse where pa = Proxy :: Proxy a pb = Proxy :: Proxy b