2015-03-09 13:39:40 +01:00
|
|
|
{-# LANGUAGE TypeFamilies #-}
|
|
|
|
{-# LANGUAGE TypeOperators #-}
|
|
|
|
{-# LANGUAGE UndecidableInstances #-}
|
2014-10-28 10:12:25 +01:00
|
|
|
module Servant.API (
|
|
|
|
|
|
|
|
-- * Combinators
|
|
|
|
module Servant.API.Sub,
|
2015-02-24 10:28:23 +01:00
|
|
|
-- | Type-level combinator for expressing subrouting: @':>'@
|
2014-10-30 11:37:58 +01:00
|
|
|
module Servant.API.Alternative,
|
2015-02-24 10:28:23 +01:00
|
|
|
-- | Type-level combinator for alternative endpoints: @':<|>'@
|
2014-10-28 10:12:25 +01:00
|
|
|
|
|
|
|
-- * Accessing information from the request
|
|
|
|
module Servant.API.Capture,
|
2015-02-24 10:28:23 +01:00
|
|
|
-- | Capturing parts of the url path as parsed values: @'Capture'@
|
2014-12-08 12:28:11 +01:00
|
|
|
module Servant.API.Header,
|
2015-02-24 10:28:23 +01:00
|
|
|
-- | Retrieving specific headers from the request
|
2014-10-28 15:06:47 +01:00
|
|
|
module Servant.API.QueryParam,
|
2015-02-24 10:28:23 +01:00
|
|
|
-- | Retrieving parameters from the query string of the 'URI': @'QueryParam'@
|
2014-10-28 16:29:04 +01:00
|
|
|
module Servant.API.ReqBody,
|
2015-02-24 10:28:23 +01:00
|
|
|
-- | Accessing the request body as a JSON-encoded type: @'ReqBody'@
|
2014-12-28 22:56:58 +01:00
|
|
|
module Servant.API.MatrixParam,
|
2015-02-24 10:28:23 +01:00
|
|
|
-- | Retrieving matrix parameters from the 'URI' segment: @'MatrixParam'@
|
2014-10-28 10:12:25 +01:00
|
|
|
|
|
|
|
-- * Actual endpoints, distinguished by HTTP method
|
|
|
|
module Servant.API.Get,
|
2015-02-24 10:28:23 +01:00
|
|
|
-- | @GET@ requests
|
2014-10-28 10:12:25 +01:00
|
|
|
module Servant.API.Post,
|
2015-02-24 10:28:23 +01:00
|
|
|
-- | @POST@ requests
|
2014-10-28 10:23:52 +01:00
|
|
|
module Servant.API.Delete,
|
2015-02-24 10:28:23 +01:00
|
|
|
-- | @DELETE@ requests
|
2014-10-28 10:23:52 +01:00
|
|
|
module Servant.API.Put,
|
2015-02-24 10:28:23 +01:00
|
|
|
-- | @PUT@ requests
|
2015-02-10 01:06:42 +01:00
|
|
|
module Servant.API.Patch,
|
2015-02-24 10:28:23 +01:00
|
|
|
-- | @PATCH@ requests
|
2014-10-28 15:22:28 +01:00
|
|
|
|
2015-01-08 16:24:19 +01:00
|
|
|
-- * Content Types
|
|
|
|
module Servant.API.ContentTypes,
|
2015-02-24 10:28:23 +01:00
|
|
|
-- | Serializing and deserializing types based on @Accept@ and
|
|
|
|
-- @Content-Type@ headers.
|
2015-01-08 16:24:19 +01:00
|
|
|
|
2014-11-12 05:55:23 +01:00
|
|
|
-- * Untyped endpoints
|
|
|
|
module Servant.API.Raw,
|
2015-02-24 10:28:23 +01:00
|
|
|
-- | Plugging in a wai 'Network.Wai.Application', serving directories
|
|
|
|
|
|
|
|
-- * FromText and ToText
|
|
|
|
module Servant.Common.Text,
|
|
|
|
-- | Classes and instances for types that can be converted to and from @Text@
|
2014-11-12 05:55:23 +01:00
|
|
|
|
2015-03-09 13:39:40 +01:00
|
|
|
-- * Canonicalizing (flattening) API types
|
|
|
|
Canonicalize,
|
2015-03-09 19:23:26 +01:00
|
|
|
canonicalize,
|
2015-03-09 13:39:40 +01:00
|
|
|
|
2014-10-28 15:22:28 +01:00
|
|
|
-- * Utilities
|
2014-11-07 09:58:53 +01:00
|
|
|
module Servant.Utils.Links,
|
2015-02-24 10:28:23 +01:00
|
|
|
-- | Type-safe internal URIs
|
2014-10-25 01:27:39 +02:00
|
|
|
) where
|
|
|
|
|
2015-03-09 19:23:26 +01:00
|
|
|
import Data.Proxy (Proxy(..))
|
2015-02-24 10:28:23 +01:00
|
|
|
import Servant.Common.Text (FromText(..), ToText(..))
|
|
|
|
import Servant.API.Alternative ((:<|>) (..))
|
|
|
|
import Servant.API.Capture (Capture)
|
|
|
|
import Servant.API.ContentTypes (JSON, MimeRender (..),
|
|
|
|
MimeUnrender (..), OctetStream,
|
2015-03-03 23:04:21 +01:00
|
|
|
PlainText, FormUrlEncoded,
|
|
|
|
FromFormUrlEncoded(..), ToFormUrlEncoded(..))
|
2015-02-24 10:28:23 +01:00
|
|
|
import Servant.API.Delete (Delete)
|
|
|
|
import Servant.API.Get (Get)
|
|
|
|
import Servant.API.Header (Header)
|
|
|
|
import Servant.API.MatrixParam (MatrixFlag, MatrixParam,
|
|
|
|
MatrixParams)
|
|
|
|
import Servant.API.Patch (Patch)
|
|
|
|
import Servant.API.Post (Post)
|
|
|
|
import Servant.API.Put (Put)
|
|
|
|
import Servant.API.QueryParam (QueryFlag, QueryParam, QueryParams)
|
|
|
|
import Servant.API.Raw (Raw)
|
|
|
|
import Servant.API.ReqBody (ReqBody)
|
|
|
|
import Servant.API.Sub ((:>))
|
|
|
|
import Servant.Utils.Links (HasLink (..), IsElem, IsElem',
|
|
|
|
URI (..), safeLink)
|
2015-03-09 13:39:40 +01:00
|
|
|
|
|
|
|
-- | Turn an API type into its canonical form.
|
|
|
|
--
|
2015-03-11 11:46:35 +01:00
|
|
|
-- The canonical form of an API type is basically the all-flattened form
|
|
|
|
-- of the original type. More formally, it takes a type as input and hands you
|
|
|
|
-- back an /equivalent/ type formed of toplevel `:<|>`-separated chains of `:>`s,
|
|
|
|
-- i.e with all `:>`s distributed inside the `:<|>`s.
|
|
|
|
--
|
|
|
|
-- It basically turns:
|
2015-03-09 13:39:40 +01:00
|
|
|
--
|
|
|
|
-- > "hello" :> (Get Hello :<|> ReqBody Hello :> Put Hello)
|
|
|
|
--
|
|
|
|
-- into
|
|
|
|
--
|
|
|
|
-- > ("hello" :> Get Hello) :<|> ("hello" :> ReqBody Hello :> Put Hello)
|
|
|
|
--
|
|
|
|
-- i.e distributing all ':>'-separated bits into the subsequent ':<|>'s.
|
|
|
|
type family Canonicalize api :: * where
|
|
|
|
-- requires UndecidableInstances
|
2015-03-10 12:08:17 +01:00
|
|
|
Canonicalize (a :> (b :<|> c)) = a :> Canonicalize b :<|> a :> Canonicalize c
|
|
|
|
Canonicalize ((a :<|> b) :> c) = a :> Canonicalize c :<|> b :> Canonicalize c
|
2015-03-09 13:39:40 +01:00
|
|
|
Canonicalize (a :> b) = Redex b (Canonicalize b) a
|
|
|
|
Canonicalize (a :<|> b) = Canonicalize a :<|> Canonicalize b
|
|
|
|
Canonicalize a = a
|
|
|
|
|
|
|
|
type family Redex a b c :: * where
|
|
|
|
Redex a a first = Canonicalize first :> a
|
|
|
|
Redex a b first = Canonicalize (first :> b)
|
2015-03-09 19:23:26 +01:00
|
|
|
|
2015-03-11 11:46:35 +01:00
|
|
|
canonicalize :: Proxy layout -> Proxy (Canonicalize layout)
|
2015-03-09 19:23:26 +01:00
|
|
|
canonicalize Proxy = Proxy
|