-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A web framework that integrates Servant, RIO, EKG, fast-logger, wai-cli… -- -- Inspired by Dropwizard, Magicbane provides a packaged framework for -- developing web services using the best available libraries, including -- Servant, RIO, Aeson, EKG/monad-metrics, fast-logger, wai-cli and -- others. @package magicbane @version 0.4.0 -- | Extends Servant with context, based on RIO. The context should be a -- tuple of all your moudles and configs and stuff, so that the Data.Has -- module would let you access these items by type. module Magicbane.App -- | asProxyTypeOf is a type-restricted version of const. It -- is usually used as an infix operator, and its typing forces its first -- argument (which is usually overloaded) to have the same type as the -- tag of the second. -- --
-- >>> import Data.Word -- -- >>> :type asProxyTypeOf 123 (Proxy :: Proxy Word8) -- asProxyTypeOf 123 (Proxy :: Proxy Word8) :: Word8 ---- -- Note the lower-case proxy in the definition. This allows any -- type constructor with just one argument to be passed to the function, -- for example we could also write -- --
-- >>> import Data.Word -- -- >>> :type asProxyTypeOf 123 (Just (undefined :: Word8)) -- asProxyTypeOf 123 (Just (undefined :: Word8)) :: Word8 --asProxyTypeOf :: () => a -> proxy a -> a -- | Proxy is a type that holds no data, but has a phantom parameter -- of arbitrary type (or even kind). Its use is to provide type -- information, even though there is no value available of that type (or -- it may be too costly to create one). -- -- Historically, Proxy :: Proxy a is a safer -- alternative to the 'undefined :: a' idiom. -- --
-- >>> Proxy :: Proxy (Void, Int -> Int) -- Proxy ---- -- Proxy can even hold types of higher kinds, -- --
-- >>> Proxy :: Proxy Either -- Proxy ---- --
-- >>> Proxy :: Proxy Functor -- Proxy ---- --
-- >>> Proxy :: Proxy complicatedStructure -- Proxy --data Proxy (t :: k) :: forall k. () => k -> * Proxy :: Proxy -- | A concrete, promotable proxy type, for use at the kind level There are -- no instances for this because it is intended at the kind level only data KProxy t KProxy :: KProxy t -- | Type-level If. If True a b ==> a; If -- False a b ==> b -- | Convert value to HTTP API data. -- -- WARNING: Do not derive this using DeriveAnyClass as -- the generated instance will loop indefinitely. class ToHttpApiData a -- | Convert to URL path piece. toUrlPiece :: ToHttpApiData a => a -> Text -- | Convert to a URL path piece, making sure to encode any special chars. -- The default definition uses encodePathSegmentsRelative, but -- this may be overriden with a more efficient version. toEncodedUrlPiece :: ToHttpApiData a => a -> Builder -- | Convert to HTTP header value. toHeader :: ToHttpApiData a => a -> ByteString -- | Convert to query param value. toQueryParam :: ToHttpApiData a => a -> Text -- | Parse value from HTTP API data. -- -- WARNING: Do not derive this using DeriveAnyClass as -- the generated instance will loop indefinitely. class FromHttpApiData a -- | Parse URL path piece. parseUrlPiece :: FromHttpApiData a => Text -> Either Text a -- | Parse HTTP header value. parseHeader :: FromHttpApiData a => ByteString -> Either Text a -- | Parse query param value. parseQueryParam :: FromHttpApiData a => Text -> Either Text a -- | Represents a general universal resource identifier using its component -- parts. -- -- For example, for the URI -- --
-- foo://anonymous@www.haskell.org:42/ghc?query#frag ---- -- the components are: data URI URI :: String -> Maybe URIAuth -> String -> String -> String -> URI -- |
-- foo: --[uriScheme] :: URI -> String -- |
-- //anonymous@www.haskell.org:42 --[uriAuthority] :: URI -> Maybe URIAuth -- |
-- /ghc --[uriPath] :: URI -> String -- |
-- ?query --[uriQuery] :: URI -> String -- |
-- #frag --[uriFragment] :: URI -> String -- | HTTP Version. -- -- Note that the Show instance is intended merely for debugging. data HttpVersion HttpVersion :: !Int -> !Int -> HttpVersion [httpMajor] :: HttpVersion -> !Int [httpMinor] :: HttpVersion -> !Int -- | HTTP standard method (as defined by RFC 2616, and PATCH which is -- defined by RFC 5789). data StdMethod GET :: StdMethod POST :: StdMethod HEAD :: StdMethod PUT :: StdMethod DELETE :: StdMethod TRACE :: StdMethod CONNECT :: StdMethod OPTIONS :: StdMethod PATCH :: StdMethod -- | Is used within a monadic computation to begin exception processing. throwError :: MonadError e m => e -> m a -- | More general version of allFieldLinks. allFieldLinks' :: (HasLink ToServantApi routes, GenericServant routes AsLink a, ToServant routes AsLink a ~ MkLink ToServantApi routes a) => Link -> a -> routes AsLink a -- | Get all links as a record. allFieldLinks :: (HasLink ToServantApi routes, GenericServant routes AsLink Link, ToServant routes AsLink Link ~ MkLink ToServantApi routes Link) => routes AsLink Link -- | More general version of fieldLink fieldLink' :: (IsElem endpoint ToServantApi routes, HasLink endpoint, GenericServant routes AsApi) => Link -> a -> routes AsApi -> endpoint -> MkLink endpoint a -- | Given an API record field, create a link for that route. Only the -- field's type is used. -- --
-- data Record route = Record
-- { _get :: route :- Capture "id" Int :> Get '[JSON] String
-- , _put :: route :- ReqBody '[JSON] Int :> Put '[JSON] Bool
-- }
-- deriving (Generic)
--
-- getLink :: Int -> Link
-- getLink = fieldLink _get
--
fieldLink :: (IsElem endpoint ToServantApi routes, HasLink endpoint, GenericServant routes AsApi) => routes AsApi -> endpoint -> MkLink endpoint Link
-- | More general allLinks. See safeLink'.
allLinks' :: HasLink api => Link -> a -> Proxy api -> MkLink api a
-- | Create all links in an API.
--
-- Note that the api type must be restricted to the endpoints
-- that have valid links to them.
--
-- -- >>> type API = "foo" :> Capture "name" Text :> Get '[JSON] Text :<|> "bar" :> Capture "name" Int :> Get '[JSON] Double -- -- >>> let fooLink :<|> barLink = allLinks (Proxy :: Proxy API) -- -- >>> :t fooLink -- fooLink :: Text -> Link -- -- >>> :t barLink -- barLink :: Int -> Link ---- -- Note: nested APIs don't work well with this approach -- --
-- >>> :kind! MkLink (Capture "nest" Char :> (Capture "x" Int :> Get '[JSON] Int :<|> Capture "y" Double :> Get '[JSON] Double)) Link -- MkLink (Capture "nest" Char :> (Capture "x" Int :> Get '[JSON] Int :<|> Capture "y" Double :> Get '[JSON] Double)) Link :: * -- = Char -> (Int -> Link) :<|> (Double -> Link) --allLinks :: HasLink api => Proxy api -> MkLink api Link -- | More general safeLink. safeLink' :: (IsElem endpoint api, HasLink endpoint) => Link -> a -> Proxy api -> Proxy endpoint -> MkLink endpoint a -- | Create a valid (by construction) relative URI with query params. -- -- This function will only typecheck if endpoint is part of the -- API api safeLink :: (IsElem endpoint api, HasLink endpoint) => Proxy api -> Proxy endpoint -> MkLink endpoint Link -- | Configurable linkURI. -- --
-- >>> type API = "sum" :> QueryParams "x" Int :> Get '[JSON] Int -- -- >>> linkURI' LinkArrayElementBracket $ safeLink (Proxy :: Proxy API) (Proxy :: Proxy API) [1, 2, 3] -- sum?x[]=1&x[]=2&x[]=3 ---- --
-- >>> linkURI' LinkArrayElementPlain $ safeLink (Proxy :: Proxy API) (Proxy :: Proxy API) [1, 2, 3] -- sum?x=1&x=2&x=3 --linkURI' :: LinkArrayElementStyle -> Link -> URI -- | Transform Link into URI. -- --
-- >>> type API = "something" :> Get '[JSON] Int -- -- >>> linkURI $ safeLink (Proxy :: Proxy API) (Proxy :: Proxy API) -- something ---- --
-- >>> type API = "sum" :> QueryParams "x" Int :> Get '[JSON] Int -- -- >>> linkURI $ safeLink (Proxy :: Proxy API) (Proxy :: Proxy API) [1, 2, 3] -- sum?x[]=1&x[]=2&x[]=3 ---- --
-- >>> type API = "foo/bar" :> Get '[JSON] Int -- -- >>> linkURI $ safeLink (Proxy :: Proxy API) (Proxy :: Proxy API) -- foo%2Fbar ---- --
-- >>> type SomeRoute = "abc" :> Capture "email" String :> Put '[JSON] ()
--
-- >>> let someRoute = Proxy :: Proxy SomeRoute
--
-- >>> safeLink someRoute someRoute "test@example.com"
-- Link {_segments = ["abc","test%40example.com"], _queryParams = []}
--
--
-- -- >>> linkURI $ safeLink someRoute someRoute "test@example.com" -- abc/test%40example.com --linkURI :: Link -> URI linkQueryParams :: Link -> [Param] linkSegments :: Link -> [String] -- | A safe link datatype. The only way of constructing a Link is -- using safeLink, which means any Link is guaranteed to be -- part of the mentioned API. data Link -- | Query parameter. data Param SingleParam :: String -> Text -> Param ArrayElemParam :: String -> Text -> Param FlagParam :: String -> Param -- | How to encode array query elements. data LinkArrayElementStyle -- |
-- foo[]=1&foo[]=2 --LinkArrayElementBracket :: LinkArrayElementStyle -- |
-- foo=1&foo=2 --LinkArrayElementPlain :: LinkArrayElementStyle -- | A type that specifies that an API record contains a set of links. data AsLink a -- | Construct a toLink for an endpoint. class HasLink (endpoint :: k) where { type family MkLink (endpoint :: k) a :: *; } toLink :: HasLink endpoint => Link -> a -> Proxy endpoint -> Link -> MkLink endpoint a -- | WithNamedContext names a specific tagged context to use for the -- combinators in the API. (See also in servant-server, -- Servant.Server.Context.) For example: -- --
-- type UseNamedContextAPI = WithNamedContext "myContext" '[String] ( -- ReqBody '[JSON] Int :> Get '[JSON] Int) ---- -- Both the ReqBody and Get combinators will use the -- WithNamedContext with type tag "myContext" as their context. -- -- Contexts are only relevant for servant-server. -- -- For more information, see the tutorial. data WithNamedContext (name :: Symbol) (subContext :: [*]) subApi -- | Flatten API into a list of endpoints. -- --
-- >>> Refl :: Endpoints SampleAPI :~: '["hello" :> Verb 'GET 200 '[JSON] Int, "bye" :> (Capture "name" String :> Verb 'POST 200 '[JSON, PlainText] Bool)] -- Refl ---- | You may use this type family to tell the type checker that your custom -- type may be skipped as part of a link. This is useful for things like -- QueryParam that are optional in a URI and do not -- affect them if they are omitted. -- --
-- >>> data CustomThing -- -- >>> type instance IsElem' e (CustomThing :> s) = IsElem e s ---- -- Note that IsElem is called, which will mutually -- recurse back to IsElem' if it exhausts all other -- options again. -- -- Once you have written a HasLink instance for -- CustomThing you are ready to go. -- | Closed type family, check if endpoint is within api. -- Uses IsElem' if it exhausts all other options. -- --
-- >>> ok (Proxy :: Proxy (IsElem ("hello" :> Get '[JSON] Int) SampleAPI))
-- OK
--
--
--
-- >>> ok (Proxy :: Proxy (IsElem ("bye" :> Get '[JSON] Int) SampleAPI))
-- ...
-- ... Could not deduce...
-- ...
--
--
-- An endpoint is considered within an api even if it is missing
-- combinators that don't affect the URL:
--
-- -- >>> ok (Proxy :: Proxy (IsElem (Get '[JSON] Int) (Header "h" Bool :> Get '[JSON] Int))) -- OK ---- --
-- >>> ok (Proxy :: Proxy (IsElem (Get '[JSON] Int) (ReqBody '[JSON] Bool :> Get '[JSON] Int))) -- OK ---- --
-- >>> ok (Proxy :: Proxy (IsSubAPI SampleAPI (SampleAPI :<|> Get '[JSON] Int))) -- OK ---- --
-- >>> ok (Proxy :: Proxy (IsSubAPI (SampleAPI :<|> Get '[JSON] Int) SampleAPI)) -- ... -- ... Could not deduce... -- ... ---- -- This uses IsElem for checking; thus the note there applies -- here. -- | Check that every element of xs is an endpoint of api -- (using IsElem). -- | Closed type family, check if endpoint is exactly within -- api. -- --
-- >>> ok (Proxy :: Proxy (IsIn ("hello" :> Get '[JSON] Int) SampleAPI))
-- OK
--
--
-- Unlike IsElem, this requires an *exact* match.
--
-- -- >>> ok (Proxy :: Proxy (IsIn (Get '[JSON] Int) (Header "h" Bool :> Get '[JSON] Int))) -- ... -- ... Could not deduce... -- ... ---- | Check whether sub is a sub API of api. -- -- Like IsSubAPI, but uses IsIn rather than IsElem. -- | Check that every element of xs is an endpoint of api -- (using IsIn). -- -- ok (Proxy :: Proxy (AllIsIn (Endpoints SampleAPI) SampleAPI)) OK -- | Apply (e :>) to every API in xs. -- | Append two type-level lists. -- | Check that a value is an element of a list: -- --
-- >>> ok (Proxy :: Proxy (Elem Bool '[Int, Bool])) -- OK ---- --
-- >>> ok (Proxy :: Proxy (Elem String '[Int, Bool])) -- ... -- ... [Char]...'[Int, Bool... -- ... --type Elem (e :: t) (es :: [t]) = ElemGo e es es -- | If either a or b produce an empty constraint, produce an empty -- constraint. -- | Verb is a general type for representing HTTP verbs (a.k.a. -- methods). For convenience, type synonyms for each verb with a 200 -- response code are provided, but you are free to define your own: -- --
-- >>> type Post204 contentTypes a = Verb 'POST 204 contentTypes a --data Verb (method :: k1) (statusCode :: Nat) (contentTypes :: [*]) a :: forall k1. () => k1 -> Nat -> [*] -> * -> * -- | GET with 200 status code. type Get = Verb GET 200 -- | POST with 200 status code. type Post = Verb POST 200 -- | PUT with 200 status code. type Put = Verb PUT 200 -- | DELETE with 200 status code. type Delete = Verb DELETE 200 -- | PATCH with 200 status code. type Patch = Verb PATCH 200 -- | POST with 201 status code. type PostCreated = Verb POST 201 -- | GET with 202 status code. type GetAccepted = Verb GET 202 -- | POST with 202 status code. type PostAccepted = Verb POST 202 -- | DELETE with 202 status code. type DeleteAccepted = Verb DELETE 202 -- | PATCH with 202 status code. type PatchAccepted = Verb PATCH 202 -- | PUT with 202 status code. type PutAccepted = Verb PUT 202 -- | GET with 203 status code. type GetNonAuthoritative = Verb GET 203 -- | POST with 203 status code. type PostNonAuthoritative = Verb POST 203 -- | DELETE with 203 status code. type DeleteNonAuthoritative = Verb DELETE 203 -- | PATCH with 203 status code. type PatchNonAuthoritative = Verb PATCH 203 -- | PUT with 203 status code. type PutNonAuthoritative = Verb PUT 203 -- | GET with 204 status code. type GetNoContent = Verb GET 204 -- | POST with 204 status code. type PostNoContent = Verb POST 204 -- | DELETE with 204 status code. type DeleteNoContent = Verb DELETE 204 -- | PATCH with 204 status code. type PatchNoContent = Verb PATCH 204 -- | PUT with 204 status code. type PutNoContent = Verb PUT 204 -- | GET with 205 status code. type GetResetContent = Verb GET 205 -- | POST with 205 status code. type PostResetContent = Verb POST 205 -- | GET with 206 status code. type GetPartialContent = Verb GET 206 class ReflectMethod (a :: k) reflectMethod :: ReflectMethod a => Proxy a -> Method -- | The contained API (second argument) can be found under ("/" ++ -- path) (path being the first argument). -- -- Example: -- --
-- >>> -- GET /hello/world -- -- >>> -- returning a JSON encoded World value -- -- >>> type MyApi = "hello" :> "world" :> Get '[JSON] World --data (:>) (path :: k) a :: forall k. () => k -> * -> * -- | A Stream endpoint for a given method emits a stream of encoded values -- at a given Content-Type, delimited by a framing strategy. Stream -- endpoints always return response code 200 on success. Type synonyms -- are provided for standard methods. data Stream (method :: k1) (status :: Nat) framing contentType a :: forall k1. () => k1 -> Nat -> * -> * -> * -> * type StreamGet = Stream GET 200 type StreamPost = Stream POST 200 -- | Stream endpoints may be implemented as producing a -- StreamGenerator -- a function that itself takes two emit -- functions -- the first to be used on the first value the stream emits, -- and the second to be used on all subsequent values (to allow -- interspersed framing strategies such as comma separation). newtype StreamGenerator a StreamGenerator :: a -> IO () -> a -> IO () -> IO () -> StreamGenerator a [getStreamGenerator] :: StreamGenerator a -> a -> IO () -> a -> IO () -> IO () -- | ToStreamGenerator is intended to be implemented for types such as -- Conduit, Pipe, etc. By implementing this class, all such streaming -- abstractions can be used directly as endpoints. class ToStreamGenerator a b | a -> b toStreamGenerator :: ToStreamGenerator a b => a -> StreamGenerator b -- | Clients reading from streaming endpoints can be implemented as -- producing a ResultStream that captures the setup, takedown, -- and incremental logic for a read, being an IO continuation that takes -- a producer of Just either values or errors that terminates with a -- Nothing. newtype ResultStream a ResultStream :: forall b. () => IO Maybe Either String a -> IO b -> IO b -> ResultStream a -- | BuildFromStream is intended to be implemented for types such as -- Conduit, Pipe, etc. By implementing this class, all such streaming -- abstractions can be used directly on the client side for talking to -- streaming endpoints. class BuildFromStream a b buildFromStream :: BuildFromStream a b => ResultStream a -> b -- | The FramingRender class provides the logic for emitting a framing -- strategy. The strategy emits a header, followed by boundary-delimited -- data, and finally a termination character. For many strategies, some -- of these will just be empty bytestrings. class FramingRender (strategy :: k) (a :: k1) header :: FramingRender strategy a => Proxy strategy -> Proxy a -> ByteString boundary :: FramingRender strategy a => Proxy strategy -> Proxy a -> BoundaryStrategy trailer :: FramingRender strategy a => Proxy strategy -> Proxy a -> ByteString -- | The bracketing strategy generates things to precede and follow the -- content, as with netstrings. The intersperse strategy inserts -- seperators between things, as with newline framing. Finally, the -- general strategy performs an arbitrary rewrite on the content, to -- allow escaping rules and such. data BoundaryStrategy BoundaryStrategyBracket :: ByteString -> (ByteString, ByteString) -> BoundaryStrategy BoundaryStrategyIntersperse :: ByteString -> BoundaryStrategy BoundaryStrategyGeneral :: ByteString -> ByteString -> BoundaryStrategy -- | A type of parser that can never fail, and has different parsing -- strategies (incremental, or EOF) depending if more input can be sent. -- The incremental parser should return Nothing if it would like -- to be sent a longer ByteString. If it returns a value, it also returns -- the remainder following that value. data ByteStringParser a ByteStringParser :: ByteString -> Maybe (a, ByteString) -> ByteString -> (a, ByteString) -> ByteStringParser a [parseIncremental] :: ByteStringParser a -> ByteString -> Maybe (a, ByteString) [parseEOF] :: ByteStringParser a -> ByteString -> (a, ByteString) -- | The FramingUnrender class provides the logic for parsing a framing -- strategy. The outer ByteStringParser strips the header from a -- stream of bytes, and yields a parser that can handle the remainder, -- stepwise. Each frame may be a ByteString, or a String indicating the -- error state for that frame. Such states are per-frame, so that -- protocols that can resume after errors are able to do so. Eventually -- this returns an empty ByteString to indicate termination. class FramingUnrender (strategy :: k) (a :: k1) unrenderFrames :: FramingUnrender strategy a => Proxy strategy -> Proxy a -> ByteStringParser ByteStringParser Either String ByteString -- | A framing strategy that does not do any framing at all, it just passes -- the input data This will be used most of the time with binary data, -- such as files data NoFraming -- | A simple framing strategy that has no header or termination, and -- inserts a newline character between each frame. This assumes that it -- is used with a Content-Type that encodes without newlines (e.g. JSON). data NewlineFraming -- | The netstring framing strategy as defined by djb: -- http://cr.yp.to/proto/netstrings.txt data NetstringFraming -- | Deliberately do not add a header to a value. -- --
-- >>> let example1 = noHeader "hi" :: Headers '[Header "someheader" Int] String -- -- >>> getHeaders example1 -- [] --noHeader :: AddHeader h v orig new => orig -> new -- | addHeader adds a header to a response. Note that it changes -- the type of the value in the following ways: -- --
-- >>> let example1 = addHeader 5 "hi" :: Headers '[Header "someheader" Int] String;
--
-- >>> getHeaders example1
-- [("someheader","5")]
--
--
--
-- >>> let example1 = addHeader 5 "hi" :: Headers '[Header "someheader" Int] String;
--
-- >>> let example2 = addHeader True example1 :: Headers '[Header "1st" Bool, Header "someheader" Int] String
--
-- >>> getHeaders example2
-- [("1st","true"),("someheader","5")]
--
--
-- Note that while in your handlers type annotations are not required,
-- since the type can be inferred from the API type, in other cases you
-- may find yourself needing to add annotations.
addHeader :: AddHeader h v orig new => v -> orig -> new
-- | Response Header objects. You should never need to construct one
-- directly. Instead, use addOptionalHeader.
data Headers (ls :: [*]) a
Headers :: a -> HList ls -> Headers a
-- | The underlying value of a Headers
[getResponse] :: Headers a -> a
-- | HList of headers.
[getHeadersHList] :: Headers a -> HList ls
data ResponseHeader (sym :: Symbol) a
Header :: a -> ResponseHeader a
MissingHeader :: ResponseHeader a
UndecodableHeader :: ByteString -> ResponseHeader a
data HList (a :: [*])
[HNil] :: HList ([] :: [*])
[HCons] :: HList Header h x : xs
class BuildHeadersTo (hs :: [*])
-- | Note: if there are multiple occurences of a header in the argument,
-- the values are interspersed with commas before deserialization (see
-- RFC2616 Sec 4.2)
buildHeadersTo :: BuildHeadersTo hs => [Header] -> HList hs
class GetHeaders ls
getHeaders :: GetHeaders ls => ls -> [Header]
class AddHeader (h :: Symbol) v orig new | h v orig -> new, new -> h, new -> v, new -> orig
-- | Extract the request body as a value of type a.
--
-- Example:
--
-- -- >>> -- POST /books -- -- >>> type MyApi = "books" :> ReqBody '[JSON] Book :> Post '[JSON] Book --type ReqBody = ReqBody' Required : Strict : ([] :: [*]) -- | Note: ReqBody' is always Required. data ReqBody' (mods :: [*]) (contentTypes :: [*]) a -- | Provides access to the host or IP address from which the HTTP request -- was sent. data RemoteHost -- | Endpoint for plugging in your own Wai Applications. -- -- The given Application will get the request as received by the -- server, potentially with a modified (stripped) pathInfo if -- the Application is being routed with :>. -- -- In addition to just letting you plug in your existing WAI -- Applications, this can also be used with -- serveDirectory to serve static files stored in a particular -- directory on your filesystem data Raw -- | Lookup the value associated to the sym query string parameter -- and try to extract it as a value of type a. -- -- Example: -- --
-- >>> -- /books?author=<author name> -- -- >>> type MyApi = "books" :> QueryParam "author" Text :> Get '[JSON] [Book] --type QueryParam = QueryParam' Optional : Strict : ([] :: [*]) -- | QueryParam which can be Required, Lenient, or -- modified otherwise. data QueryParam' (mods :: [*]) (sym :: Symbol) a -- | Lookup the values associated to the sym query string -- parameter and try to extract it as a value of type [a]. This -- is typically meant to support query string parameters of the form -- param[]=val1¶m[]=val2 and so on. Note that servant -- doesn't actually require the []s and will fetch the values -- just fine with param=val1¶m=val2, too. -- -- Example: -- --
-- >>> -- /books?authors[]=<author1>&authors[]=<author2>&... -- -- >>> type MyApi = "books" :> QueryParams "authors" Text :> Get '[JSON] [Book] --data QueryParams (sym :: Symbol) a -- | Lookup a potentially value-less query string parameter with boolean -- semantics. If the param sym is there without any value, or if -- it's there with value "true" or "1", it's interpreted as True. -- Otherwise, it's interpreted as False. -- -- Example: -- --
-- >>> -- /books?published -- -- >>> type MyApi = "books" :> QueryFlag "published" :> Get '[JSON] [Book] --data QueryFlag (sym :: Symbol) -- | Extract the given header's value as a value of type a. I.e. -- header sent by client, parsed by server. -- -- Example: -- --
-- >>> newtype Referer = Referer Text deriving (Eq, Show) -- -- >>> -- -- >>> -- GET /view-my-referer -- -- >>> type MyApi = "view-my-referer" :> Header "from" Referer :> Get '[JSON] Referer --type Header = (Header' Optional : Strict : ([] :: [*]) :: Symbol -> k -> *) data Header' (mods :: [*]) (sym :: Symbol) (a :: k) :: forall k. () => [*] -> Symbol -> k -> * -- | Required argument. Not wrapped. data Required -- | Optional argument. Wrapped in Maybe. data Optional -- | Leniently parsed argument, i.e. parsing never fail. Wrapped in -- Either Text. data Lenient -- | Strictly parsed argument. Not wrapped. data Strict -- | Was this request made over an SSL connection? -- -- Note that this value will not tell you if the client originally made -- this request over SSL, but rather whether the current connection is -- SSL. The distinction lies with reverse proxies. In many cases, the -- client will connect to a load balancer over SSL, but connect to the -- WAI handler without SSL. In such a case, the handlers would get -- NotSecure, but from a user perspective, there is a secure -- connection. data IsSecure -- | the connection to the server is secure (HTTPS) Secure :: IsSecure -- | the connection to the server is not secure (HTTP) NotSecure :: IsSecure -- | A generalized Authentication combinator. Use this if you have a -- non-standard authentication technique. -- -- NOTE: THIS API IS EXPERIMENTAL AND SUBJECT TO CHANGE. data AuthProtect (tag :: k) :: forall k. () => k -> * -- | An empty API: one which serves nothing. Morally speaking, this should -- be the unit of :<|>. Implementors of interpretations of -- API types should treat EmptyAPI as close to the unit as -- possible. data EmptyAPI EmptyAPI :: EmptyAPI -- | Add a short summary for (part of) API. -- -- Example: -- --
-- >>> type MyApi = Summary "Get book by ISBN." :> "books" :> Capture "isbn" Text :> Get '[JSON] Book --data Summary (sym :: Symbol) -- | Add more verbose description for (part of) API. -- -- Example: -- --
-- >>> :{
-- type MyApi = Description
-- "This comment is visible in multiple Servant interpretations \
-- \and can be really long if necessary. \
-- \Haskell multiline support is not perfect \
-- \but it's still very readable."
-- :> Get '[JSON] Book
-- :}
--
data Description (sym :: Symbol)
data JSON
data PlainText
data FormUrlEncoded
data OctetStream
-- | Instances of Accept represent mimetypes. They are used for
-- matching against the Accept HTTP header of the request, and
-- for setting the Content-Type header of the response
--
-- Example:
--
--
-- >>> import Network.HTTP.Media ((//), (/:))
--
-- >>> data HTML
--
-- >>> :{
-- instance Accept HTML where
-- contentType _ = "text" // "html" /: ("charset", "utf-8")
-- :}
--
class Accept (ctype :: k)
contentType :: Accept ctype => Proxy ctype -> MediaType
contentTypes :: Accept ctype => Proxy ctype -> NonEmpty MediaType
-- | Instantiate this class to register a way of serializing a type based
-- on the Accept header.
--
-- Example:
--
--
-- data MyContentType
--
-- instance Accept MyContentType where
-- contentType _ = "example" // "prs.me.mine" /: ("charset", "utf-8")
--
-- instance Show a => MimeRender MyContentType a where
-- mimeRender _ val = pack ("This is MINE! " ++ show val)
--
-- type MyAPI = "path" :> Get '[MyContentType] Int
--
class Accept ctype => MimeRender (ctype :: k) a
mimeRender :: MimeRender ctype a => Proxy ctype -> a -> ByteString
-- | Instantiate this class to register a way of deserializing a type based
-- on the request's Content-Type header.
--
-- -- >>> import Network.HTTP.Media hiding (Accept) -- -- >>> import qualified Data.ByteString.Lazy.Char8 as BSC -- -- >>> data MyContentType = MyContentType String ---- --
-- >>> :{
-- instance Accept MyContentType where
-- contentType _ = "example" // "prs.me.mine" /: ("charset", "utf-8")
-- :}
--
--
--
-- >>> :{
-- instance Read a => MimeUnrender MyContentType a where
-- mimeUnrender _ bs = case BSC.take 12 bs of
-- "MyContentType" -> return . read . BSC.unpack $ BSC.drop 12 bs
-- _ -> Left "didn't start with the magic incantation"
-- :}
--
--
-- -- >>> type MyAPI = "path" :> ReqBody '[MyContentType] Int :> Get '[JSON] Int --class Accept ctype => MimeUnrender (ctype :: k) a mimeUnrender :: MimeUnrender ctype a => Proxy ctype -> ByteString -> Either String a -- | Variant which is given the actual MediaType provided by the -- other party. -- -- In the most cases you don't want to branch based on the -- MediaType. See pr552 for a motivating example. mimeUnrenderWithType :: MimeUnrender ctype a => Proxy ctype -> MediaType -> ByteString -> Either String a -- | A type for responses without content-body. data NoContent NoContent :: NoContent -- | Capture a value from the request path under a certain type a. -- -- Example: -- --
-- >>> -- GET /books/:isbn -- -- >>> type MyApi = "books" :> Capture "isbn" Text :> Get '[JSON] Book --type Capture = Capture' ([] :: [*]) -- | Capture which can be modified. For example with -- Description. data Capture' (mods :: [*]) (sym :: Symbol) a -- | Capture all remaining values from the request path under a certain -- type a. -- -- Example: -- --
-- >>> -- GET /src/* -- -- >>> type MyAPI = "src" :> CaptureAll "segments" Text :> Get '[JSON] SourceFile --data CaptureAll (sym :: Symbol) a -- | Combinator for Basic Access Authentication. -- --
-- >>> :{
-- type MyApi = "books" :> Get '[JSON] [Book] -- GET /books
-- :<|> "books" :> ReqBody '[JSON] Book :> Post '[JSON] () -- POST /books
-- :}
--
data (:<|>) a b
(:<|>) :: a -> b -> (:<|>) a b
-- | A persistent store for values of arbitrary types.
--
-- This variant is the simplest and creates keys in the IO monad.
-- See the module Data.Vault.ST if you want to use it with the
-- ST monad instead.
type Vault = Vault RealWorld
class SBoolI (b :: Bool)
sbool :: SBoolI b => SBool b
data SBool (b :: Bool)
[STrue] :: SBool True
[SFalse] :: SBool False
-- | Same as serveDirectoryFileServer. It used to be the only file
-- serving function in servant pre-0.10 and will be kept around for a few
-- versions, but is deprecated.
serveDirectory :: () => FilePath -> ServerT Raw m
-- | Alias for staticApp. Lets you serve a directory with arbitrary
-- StaticSettings. Useful when you want particular settings not
-- covered by the four other variants. This is the most flexible method.
serveDirectoryWith :: () => StaticSettings -> ServerT Raw m
-- | Uses embeddedSettings.
serveDirectoryEmbedded :: () => [(FilePath, ByteString)] -> ServerT Raw m
-- | Same as serveDirectoryWebApp, but uses
-- webAppSettingsWithLookup.
serveDirectoryWebAppLookup :: () => ETagLookup -> FilePath -> ServerT Raw m
-- | Same as serveDirectoryWebApp, but uses
-- defaultFileServerSettings.
serveDirectoryFileServer :: () => FilePath -> ServerT Raw m
-- | Serve anything under the specified directory as a Raw endpoint.
--
-- -- type MyApi = "static" :> Raw -- -- server :: Server MyApi -- server = serveDirectoryWebApp "/var/www" ---- -- would capture any request to /static/<something> and -- look for <something> under /var/www. -- -- It will do its best to guess the MIME type for that file, based on the -- extension, and send an appropriate Content-Type header if -- possible. -- -- If your goal is to serve HTML, CSS and Javascript files that use the -- rest of the API as a webapp backend, you will most likely not want the -- static files to be hidden behind a /static/ prefix. In that -- case, remember to put the serveDirectoryWebApp handler in the -- last position, because servant will try to match the handlers -- in order. -- -- Corresponds to the defaultWebAppSettings StaticSettings -- value. serveDirectoryWebApp :: () => FilePath -> ServerT Raw m -- | Variant of layout that takes an additional Context. layoutWithContext :: HasServer api context => Proxy api -> Context context -> Text -- | The function layout produces a textual description of the -- internal router layout for debugging purposes. Note that the router -- layout is determined just by the API, not by the handlers. -- -- Example: -- -- For the following API -- --
-- type API = -- "a" :> "d" :> Get '[JSON] NoContent -- :<|> "b" :> Capture "x" Int :> Get '[JSON] Bool -- :<|> "c" :> Put '[JSON] Bool -- :<|> "a" :> "e" :> Get '[JSON] Int -- :<|> "b" :> Capture "x" Int :> Put '[JSON] Bool -- :<|> Raw ---- -- we get the following output: -- --
-- / -- ├─ a/ -- │ ├─ d/ -- │ │ └─• -- │ └─ e/ -- │ └─• -- ├─ b/ -- │ └─ <capture>/ -- │ ├─• -- │ ┆ -- │ └─• -- ├─ c/ -- │ └─• -- ┆ -- └─ <raw> ---- -- Explanation of symbols: -- --
-- >>> import Control.Monad.Reader -- -- >>> type ReaderAPI = "ep1" :> Get '[JSON] Int :<|> "ep2" :> Get '[JSON] String :<|> Raw :<|> EmptyAPI -- -- >>> let readerApi = Proxy :: Proxy ReaderAPI -- -- >>> let readerServer = return 1797 :<|> ask :<|> Tagged (error "raw server") :<|> emptyServer :: ServerT ReaderAPI (Reader String) -- -- >>> let nt x = return (runReader x "hi") -- -- >>> let mainServer = hoistServer readerApi nt readerServer :: Server ReaderAPI --hoistServer :: HasServer api ([] :: [*]) => Proxy api -> forall x. () => m x -> n x -> ServerT api m -> ServerT api n serveWithContext :: HasServer api context => Proxy api -> Context context -> Server api -> Application -- | serve allows you to implement an API and produce a wai -- Application. -- -- Example: -- --
-- type MyApi = "books" :> Get '[JSON] [Book] -- GET /books -- :<|> "books" :> ReqBody Book :> Post '[JSON] Book -- POST /books -- -- server :: Server MyApi -- server = listAllBooks :<|> postBook -- where listAllBooks = ... -- postBook book = ... -- -- myApi :: Proxy MyApi -- myApi = Proxy -- -- app :: Application -- app = serve myApi server -- -- main :: IO () -- main = Network.Wai.Handler.Warp.run 8080 app --serve :: HasServer api ([] :: [*]) => Proxy api -> Server api -> Application -- | Server for EmptyAPI emptyServer :: () => ServerT EmptyAPI m class HasServer (api :: k) (context :: [*]) where { type family ServerT (api :: k) (m :: * -> *) :: *; } route :: HasServer api context => Proxy api -> Context context -> Delayed env Server api -> Router env hoistServerWithContext :: HasServer api context => Proxy api -> Proxy context -> forall x. () => m x -> n x -> ServerT api m -> ServerT api n type Server (api :: k) = ServerT api Handler -- | Singleton type representing a server that serves an empty API. data EmptyServer -- | servant-server's current implementation of basic authentication is not -- immune to certian kinds of timing attacks. Decoding payloads does not -- take a fixed amount of time. -- -- The result of authentication/authorization data BasicAuthResult usr Unauthorized :: BasicAuthResult usr BadPassword :: BasicAuthResult usr NoSuchUser :: BasicAuthResult usr Authorized :: usr -> BasicAuthResult usr -- | Datatype wrapping a function used to check authentication. newtype BasicAuthCheck usr BasicAuthCheck :: BasicAuthData -> IO BasicAuthResult usr -> BasicAuthCheck usr [unBasicAuthCheck] :: BasicAuthCheck usr -> BasicAuthData -> IO BasicAuthResult usr -- | Apply a transformation to the response of a Router. tweakResponse :: () => RouteResult Response -> RouteResult Response -> Router env -> Router env toApplication :: RoutingApplication -> Application runHandler :: () => Handler a -> IO Either ServantErr a runHandler' :: Handler a -> ExceptT ServantErr IO a -- | err505 HTTP Version not supported -- -- Example usage: -- --
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err505 { errBody = "I support HTTP/4.0 only." }
--
err505 :: ServantErr
-- | err504 Gateway Time-out
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err504 { errBody = "Backend foobar did not respond in 5 seconds." }
--
err504 :: ServantErr
-- | err503 Service Unavailable
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err503 { errBody = "We're rewriting in PHP." }
--
err503 :: ServantErr
-- | err502 Bad Gateway
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err502 { errBody = "Tried gateway foo, bar, and baz. None responded." }
--
err502 :: ServantErr
-- | err501 Not Implemented
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err501 { errBody = "/v1/foo is not supported with quux in the request." }
--
err501 :: ServantErr
-- | err500 Internal Server Error
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err500 { errBody = "Exception in module A.B.C:55. Have a great day!" }
--
err500 :: ServantErr
-- | err422 Unprocessable Entity
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err422 { errBody = "I understood your request, but can't process it." }
--
err422 :: ServantErr
-- | err418 Expectation Failed
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err418 { errBody = "Apologies, this is not a webserver but a teapot." }
--
err418 :: ServantErr
-- | err417 Expectation Failed
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err417 { errBody = "I found a quux in the request. This isn't going to work." }
--
err417 :: ServantErr
-- | err416 Request range not satisfiable
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err416 { errBody = "Valid range is [0, 424242]." }
--
err416 :: ServantErr
-- | err415 Unsupported Media Type
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err415 { errBody = "Supported media types: gif, png" }
--
err415 :: ServantErr
-- | err414 Request-URI Too Large
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err414 { errBody = "Maximum length is 64." }
--
err414 :: ServantErr
-- | err413 Request Entity Too Large
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err413 { errBody = "Request exceeded 64k." }
--
err413 :: ServantErr
-- | err412 Precondition Failed
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err412 { errBody = "Precondition fail: x < 42 && y > 57" }
--
err412 :: ServantErr
-- | err411 Length Required
--
-- Example:
--
-- -- failingHandler :: Handler () -- failingHandler = throwError err411 --err411 :: ServantErr -- | err410 Gone -- -- Example: -- --
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err410 { errBody = "I know it was here at some point, but.. I blame bad luck." }
--
err410 :: ServantErr
-- | err409 Conflict
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err409 { errBody = "Transaction conflicts with 59879cb56c7c159231eeacdd503d755f7e835f74" }
--
err409 :: ServantErr
-- | err407 Proxy Authentication Required
--
-- Example:
--
-- -- failingHandler :: Handler () -- failingHandler = throwError err407 --err407 :: ServantErr -- | err406 Not Acceptable -- -- Example: -- --
-- failingHandler :: Handler () -- failingHandler = throwError err406 --err406 :: ServantErr -- | err405 Method Not Allowed -- -- Example: -- --
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err405 { errBody = "Your account privileges does not allow for this. Please pay $$$." }
--
err405 :: ServantErr
-- | err404 Not Found
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err404 { errBody = "(╯°□°)╯︵ ┻━┻)." }
--
err404 :: ServantErr
-- | err403 Forbidden
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err403 { errBody = "Please login first." }
--
err403 :: ServantErr
-- | err402 Payment Required
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err402 { errBody = "You have 0 credits. Please give me $$$." }
--
err402 :: ServantErr
-- | err401 Unauthorized
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err401 { errBody = "Your credentials are invalid." }
--
err401 :: ServantErr
-- | err400 Bad Request
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err400 { errBody = "Your request makes no sense to me." }
--
err400 :: ServantErr
-- | err307 Temporary Redirect
--
-- Example:
--
-- -- failingHandler :: Handler () -- failingHandler = throwError err307 --err307 :: ServantErr -- | err305 Use Proxy -- -- Example: -- --
-- failingHandler :: Handler () -- failingHandler = throwError err305 --err305 :: ServantErr -- | err304 Not Modified -- -- Example: -- --
-- failingHandler :: Handler () -- failingHandler = throwError err304 --err304 :: ServantErr -- | err303 See Other -- -- Example: -- --
-- failingHandler :: Handler () -- failingHandler = throwError err303 --err303 :: ServantErr -- | err302 Found -- -- Example: -- --
-- failingHandler :: Handler () -- failingHandler = throwError err302 --err302 :: ServantErr -- | err301 Moved Permanently -- -- Example: -- --
-- failingHandler :: Handler () -- failingHandler = throwError err301 --err301 :: ServantErr -- | err300 Multiple Choices -- -- Example: -- --
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err300 { errBody = "I can't choose." }
--
err300 :: ServantErr
data ServantErr
ServantErr :: Int -> String -> ByteString -> [Header] -> ServantErr
[errHTTPCode] :: ServantErr -> Int
[errReasonPhrase] :: ServantErr -> String
[errBody] :: ServantErr -> ByteString
[errHeaders] :: ServantErr -> [Header]
-- | descendIntoNamedContext allows you to access
-- NamedContexts. Usually you won't have to use it yourself but
-- instead use a combinator like WithNamedContext.
--
-- This is how descendIntoNamedContext works:
--
-- -- >>> :set -XFlexibleContexts -- -- >>> let subContext = True :. EmptyContext -- -- >>> :type subContext -- subContext :: Context '[Bool] -- -- >>> let parentContext = False :. (NamedContext subContext :: NamedContext "subContext" '[Bool]) :. EmptyContext -- -- >>> :type parentContext -- parentContext :: Context '[Bool, NamedContext "subContext" '[Bool]] -- -- >>> descendIntoNamedContext (Proxy :: Proxy "subContext") parentContext :: Context '[Bool] -- True :. EmptyContext --descendIntoNamedContext :: HasContextEntry context NamedContext name subContext => Proxy name -> Context context -> Context subContext -- | Contexts are used to pass values to combinators. (They are -- not meant to be used to pass parameters to your handlers, i.e. -- they should not replace any custom ReaderT-monad-stack that -- you're using with hoistServer.) If you don't use combinators -- that require any context entries, you can just use serve as -- always. -- -- If you are using combinators that require a non-empty Context -- you have to use serveWithContext and pass it a Context -- that contains all the values your combinators need. A Context -- is essentially a heterogenous list and accessing the elements is being -- done by type (see getContextEntry). The parameter of the type -- Context is a type-level list reflecting the types of the -- contained context entries. To create a Context with entries, -- use the operator (:.): -- --
-- >>> :type True :. () :. EmptyContext -- True :. () :. EmptyContext :: Context '[Bool, ()] --data Context (contextTypes :: [*]) [EmptyContext] :: Context ([] :: [*]) [:.] :: Context x : xs -- | This class is used to access context entries in Contexts. -- getContextEntry returns the first value where the type matches: -- --
-- >>> getContextEntry (True :. False :. EmptyContext) :: Bool -- True ---- -- If the Context does not contain an entry of the requested type, -- you'll get an error: -- --
-- >>> getContextEntry (True :. False :. EmptyContext) :: String -- ... -- ...No instance for (HasContextEntry '[] [Char]) -- ... --class HasContextEntry (context :: [*]) val getContextEntry :: HasContextEntry context val => Context context -> val -- | Normally context entries are accessed by their types. In case you need -- to have multiple values of the same type in your Context and -- need to access them, we provide NamedContext. You can think of -- it as sub-namespaces for Contexts. data NamedContext (name :: Symbol) (subContext :: [*]) NamedContext :: Context subContext -> NamedContext -- | The WAI application. -- -- Note that, since WAI 3.0, this type is structured in continuation -- passing style to allow for proper safe resource handling. This was -- handled in the past via other means (e.g., ResourceT). As a -- demonstration: -- --
-- app :: Application -- app req respond = bracket_ -- (putStrLn "Allocating scarce resource") -- (putStrLn "Cleaning up") -- (respond $ responseLBS status200 [] "Hello World") --type Application = Request -> Response -> IO ResponseReceived -> IO ResponseReceived -- | A Tagged s b value is a value b with an -- attached phantom type s. This can be used in place of the -- more traditional but less safe idiom of passing in an undefined value -- with the type, because unlike an (s -> b), a -- Tagged s b can't try to use the argument s as -- a real value. -- -- Moreover, you don't have to rely on the compiler to inline away the -- extra argument, because the newtype is "free" -- -- Tagged has kind k -> * -> * if the compiler -- supports PolyKinds, therefore there is an extra k -- showing in the instance haddocks that may cause confusion. newtype Tagged (s :: k) b :: forall k. () => k -> * -> * Tagged :: b -> Tagged b [unTagged] :: Tagged b -> b runMagicbaneHandler :: β -> RIO β α -> Handler α -- | Constructs a WAI application from an API definition, a Servant context -- (used for auth mainly), the app context and the actual action -- handlers. magicbaneApp :: forall β χ ψ. (HasServer χ ψ) => Proxy χ -> Context ψ -> β -> ServerT χ (RIO β) -> Application -- | The Reader+IO monad. This is different from a ReaderT because: -- --
-- +RTS -T ---- -- or compile it with -- --
-- -with-rtsopts=-T ---- -- The runtime overhead of -T is very small so it's safe to -- always leave it enabled. -- -- Registered counters: -- --
-- timedList Seconds ["request.byUser." <> userName, "request.byType." <> requestType] $ do -- ... ---- -- So you will have "request.byUser.someuser" storing duration -- distribution for requests of user "someuser" of any type; and -- "request.byType.sometype" storing duration distribution for -- requests of type "sometype" from any user. timedList :: (MonadIO m, MonadMetrics m, MonadMask m) => Resolution -> [Text] -> m a -> m a -- | Record the time taken to perform the named action. The number is -- stored in a Distribution and is converted to the specified -- Resolution. -- --
namespace.wai.request_count
namespace.wai.response_status_1xx
namespace.wai.response_status_2xx
namespace.wai.response_status_3xx
namespace.wai.response_status_4xx
namespace.wai.response_status_5xx
namespace.wai.latency_distribution
wai.request_count
wai.response_status_1xx
wai.response_status_2xx
wai.response_status_3xx
wai.response_status_4xx
wai.response_status_5xx
wai.latency_distribution
-- >>> :set -XOverloadedStrings -- -- >>> slugify "Hello & World!" -- "hello-and-world" --slugify :: Text -> Text -- | Creates a simple text/plain ServantErr. errText :: ServantErr -> ByteString -> ServantErr -- | Creates and throws a simple text/plain ServantErr. throwErrText :: MonadThrow μ => ServantErr -> ByteString -> μ α -- | Provides an HTTP(S) client via http-client(-tls) in a Magicbane app -- context. Also provides a simple composable interface for making -- arbitrary requests, based on http-client-conduit. That lets you plug -- stream parsers (e.g. html-conduit: 'performWithFn (.| sinkDoc)') -- directly into the reading of the response body. module Magicbane.HTTPClient type MonadHTTP ψ μ = (HasHttpManager ψ, MonadReader ψ μ, MonadUnliftIO μ) newtype ModHttpClient ModHttpClient :: Manager -> ModHttpClient newHttpClient :: IO ModHttpClient runHTTP :: ExceptT ε μ α -> μ (Either ε α) -- | Creates a request from a URI. reqU :: (MonadHTTP ψ μ) => URI -> ExceptT Text μ Request -- | Creates a request from a string of any type, parsing it into a URI. reqS :: (MonadHTTP ψ μ, ConvertibleStrings σ String) => σ -> ExceptT Text μ Request -- | Configures the request to not throw errors on error status codes. anyStatus :: (MonadHTTP ψ μ) => Request -> ExceptT Text μ Request -- | Sets a x-www-form-urlencoded form as the request body (also sets the -- content-type). postForm :: (MonadHTTP ψ μ) => [(Text, Text)] -> Request -> ExceptT Text μ Request -- | Sets a JSON value as the request body (via ToJSON; also sets the -- content-type). postJson :: (MonadHTTP ψ μ, ToJSON α) => α -> Request -> ExceptT Text μ Request -- | Performs the request, using a given function to read the body. This is -- what all other performWith functions are based on. performWithFn :: (MonadHTTP ψ μ, MonadCatch μ) => (ConduitM ι ByteString μ () -> ConduitT () Void μ ρ) -> Request -> ExceptT Text μ (Response ρ) -- | Performs the request, ignoring the body. performWithVoid :: (MonadHTTP ψ μ, MonadCatch μ) => Request -> ExceptT Text μ (Response ()) -- | Performs the request, reading the body into a lazy ByteString. performWithBytes :: (MonadHTTP ψ μ, MonadCatch μ) => Request -> ExceptT Text μ (Response ByteString) -- | Add headers to the request, preserving any existing headers not -- specified in the new set. applyHeaders :: RequestHeaders -> Request -> Request -- | Remove listed headers from the request. removeHeaders :: [HeaderName] -> Request -> Request -- | A monad transformer that adds exceptions to other monads. -- -- ExceptT constructs a monad parameterized over two things: -- --
unliftIO u . return = return
unliftIO u (m >>= f) = unliftIO u m >>= unliftIO -- u . f
askUnliftIO >>= (u -> liftIO (unliftIO u m)) = -- m
-- catch (throwM e) f = f e ---- -- Note that the ability to catch an exception does not guarantee -- that we can deal with all possible exit points from a computation. -- Some monads, such as continuation-based stacks, allow for more than -- just a success/failure strategy, and therefore catch -- cannot be used by those monads to properly implement a function -- such as finally. For more information, see MonadMask. class MonadThrow m => MonadCatch (m :: * -> *) -- | Represents a general universal resource identifier using its component -- parts. -- -- For example, for the URI -- --
-- foo://anonymous@www.haskell.org:42/ghc?query#frag ---- -- the components are: data URI URI :: String -> Maybe URIAuth -> String -> String -> String -> URI -- |
-- foo: --[uriScheme] :: URI -> String -- |
-- //anonymous@www.haskell.org:42 --[uriAuthority] :: URI -> Maybe URIAuth -- |
-- /ghc --[uriPath] :: URI -> String -- |
-- ?query --[uriQuery] :: URI -> String -- |
-- #frag --[uriFragment] :: URI -> String -- | Use the default response timeout -- -- When used on a Request, means: use the manager's timeout value -- -- When used on a ManagerSettings, means: default to 30 seconds responseTimeoutDefault :: ResponseTimeout -- | Do not have a response timeout responseTimeoutNone :: ResponseTimeout -- | Specify a response timeout in microseconds responseTimeoutMicro :: Int -> ResponseTimeout -- | Set the proxy override value, for both HTTP (insecure) and HTTPS -- (insecure) connections. -- -- Since 0.4.7 managerSetProxy :: ProxyOverride -> ManagerSettings -> ManagerSettings -- | Set the proxy override value, only for HTTPS (secure) connections. -- -- Since 0.4.7 managerSetSecureProxy :: ProxyOverride -> ManagerSettings -> ManagerSettings -- | Set the proxy override value, only for HTTP (insecure) connections. -- -- Since 0.4.7 managerSetInsecureProxy :: ProxyOverride -> ManagerSettings -> ManagerSettings -- | A variant of withResponse which keeps a history of all -- redirects performed in the interim, together with the first 1024 bytes -- of their response bodies. -- -- Since 0.4.1 withResponseHistory :: () => Request -> Manager -> HistoriedResponse BodyReader -> IO a -> IO a -- | A variant of responseOpen which keeps a history of all -- redirects performed in the interim, together with the first 1024 bytes -- of their response bodies. -- -- Since 0.4.1 responseOpenHistory :: Request -> Manager -> IO HistoriedResponse BodyReader -- | A datatype holding information on redirected requests and the final -- response. -- -- Since 0.4.1 data HistoriedResponse body -- | Perform an action using a Connection acquired from the given -- Manager. -- -- You should use this only when you have to read and write interactively -- through the connection (e.g. connection by the WebSocket protocol). withConnection :: () => Request -> Manager -> Connection -> IO a -> IO a -- | Close any open resources associated with the given Response. -- In general, this will either close an active Connection or -- return it to the Manager to be reused. -- -- Since 0.1.0 responseClose :: () => Response a -> IO () -- | The most low-level function for initiating an HTTP request. -- -- The first argument to this function gives a full specification on the -- request: the host to connect to, whether to use SSL, headers, etc. -- Please see Request for full details. The second argument -- specifies which Manager should be used. -- -- This function then returns a Response with a BodyReader. -- The Response contains the status code and headers that were -- sent back to us, and the BodyReader contains the body of the -- request. Note that this BodyReader allows you to have fully -- interleaved IO actions during your HTTP download, making it possible -- to download very large responses in constant memory. -- -- An important note: the response body returned by this function -- represents a live HTTP connection. As such, if you do not use the -- response body, an open socket will be retained indefinitely. You must -- be certain to call responseClose on this response to free up -- resources. -- -- This function automatically performs any necessary redirects, as -- specified by the redirectCount setting. -- -- When implementing a (reverse) proxy using this function or relating -- functions, it's wise to remove Transfer-Encoding:, Content-Length:, -- Content-Encoding: and Accept-Encoding: from request and response -- headers to be relayed. -- -- Since 0.1.0 responseOpen :: Request -> Manager -> IO Response BodyReader -- | A convenient wrapper around withResponse which ignores the -- response body. This is useful, for example, when performing a HEAD -- request. -- -- Since 0.3.2 httpNoBody :: Request -> Manager -> IO Response () -- | A convenience wrapper around withResponse which reads in the -- entire response body and immediately closes the connection. Note that -- this function performs fully strict I/O, and only uses a lazy -- ByteString in its response for memory efficiency. If you are -- anticipating a large response body, you are encouraged to use -- withResponse and brRead instead. -- -- Since 0.1.0 httpLbs :: Request -> Manager -> IO Response ByteString -- | Perform a Request using a connection acquired from the given -- Manager, and then provide the Response to the given -- function. This function is fully exception safe, guaranteeing that the -- response will be closed when the inner function exits. It is defined -- as: -- --
-- withResponse req man f = bracket (responseOpen req man) responseClose f ---- -- It is recommended that you use this function in place of explicit -- calls to responseOpen and responseClose. -- -- You will need to use functions such as brRead to consume the -- response body. -- -- Since 0.1.0 withResponse :: () => Request -> Manager -> Response BodyReader -> IO a -> IO a -- | Turn a SetCookie into a Cookie, if it is valid generateCookie :: SetCookie -> Request -> UTCTime -> Bool -> Maybe Cookie -- | Insert a cookie created by generateCookie into the cookie jar (or not -- if it shouldn't be allowed in) insertCheckedCookie :: Cookie -> CookieJar -> Bool -> CookieJar -- | This corresponds to the algorithm described in Section 5.3 "Storage -- Model" This function consists of calling generateCookie -- followed by insertCheckedCookie. Use this function if you plan -- to do both in a row. generateCookie and -- insertCheckedCookie are only provided for more fine-grained -- control. receiveSetCookie :: SetCookie -> Request -> UTCTime -> Bool -> CookieJar -> CookieJar -- | This applies receiveSetCookie to a given Response updateCookieJar :: () => Response a -> Request -> UTCTime -> CookieJar -> (CookieJar, Response a) -- | This corresponds to the algorithm described in Section 5.4 "The Cookie -- Header" computeCookieString :: Request -> CookieJar -> UTCTime -> Bool -> (ByteString, CookieJar) -- | This applies the computeCookieString to a given Request insertCookiesIntoRequest :: Request -> CookieJar -> UTCTime -> (Request, CookieJar) -- | This corresponds to the eviction algorithm described in Section 5.3 -- "Storage Model" evictExpiredCookies :: CookieJar -> UTCTime -> CookieJar removeExistingCookieFromCookieJar :: Cookie -> CookieJar -> (Maybe Cookie, CookieJar) destroyCookieJar :: CookieJar -> [Cookie] createCookieJar :: [Cookie] -> CookieJar -- | This corresponds to the subcomponent algorithm entitled "Path-Match" -- detailed in section 5.1.4 pathMatches :: ByteString -> ByteString -> Bool -- | This corresponds to the subcomponent algorithm entitled "Paths" -- detailed in section 5.1.4 defaultPath :: Request -> ByteString -- | This corresponds to the subcomponent algorithm entitled "Domain -- Matching" detailed in section 5.1.3 domainMatches :: ByteString -> ByteString -> Bool isIpAddress :: ByteString -> Bool -- | The default proxy settings for a manager. In particular: if the -- http_proxy (or https_proxy) environment variable is -- set, use it. Otherwise, use the values in the Request. -- -- Since 0.4.7 defaultProxy :: ProxyOverride -- | Same as proxyEnvironment, but instead of default environment -- variable names, allows you to set your own name. -- -- Since 0.4.7 proxyEnvironmentNamed :: Text -> Maybe Proxy -> ProxyOverride -- | Get the proxy settings from the default environment variable -- (http_proxy for insecure, https_proxy for secure). -- If no variable is set, then fall back to the given value. -- Nothing is equivalent to noProxy, Just is -- equivalent to useProxy. -- -- Since 0.4.7 proxyEnvironment :: Maybe Proxy -> ProxyOverride -- | Use the given proxy settings, regardless of the proxy value in the -- Request. -- -- Since 0.4.7 useProxy :: Proxy -> ProxyOverride -- | Never connect using a proxy, regardless of the proxy value in the -- Request. -- -- Since 0.4.7 noProxy :: ProxyOverride -- | Get the proxy settings from the Request itself. -- -- Since 0.4.7 proxyFromRequest :: ProxyOverride -- | Create, use and close a Manager. -- -- Since 0.2.1 withManager :: () => ManagerSettings -> Manager -> IO a -> IO a -- | Close all connections in a Manager. -- -- Note that this doesn't affect currently in-flight connections, meaning -- you can safely use it without hurting any queries you may have -- concurrently running. -- -- Since 0.1.0 closeManager :: Manager -> IO () -- | Create a Manager. The Manager will be shut down -- automatically via garbage collection. -- -- Creating a new Manager is a relatively expensive operation, you -- are advised to share a single Manager between requests instead. -- -- The first argument to this function is often -- defaultManagerSettings, though add-on libraries may provide a -- recommended replacement. -- -- Since 0.1.0 newManager :: ManagerSettings -> IO Manager -- | Default value for ManagerSettings. -- -- Note that this value does not have support for SSL/TLS. If you -- need to make any https connections, please use the http-client-tls -- package, which provides a tlsManagerSettings value. -- -- Since 0.1.0 defaultManagerSettings :: ManagerSettings -- | Same as rawConnectionModifySocket, but also takes in a chunk -- size. rawConnectionModifySocketSize :: Socket -> IO () -> IO Int -> Maybe HostAddress -> String -> Int -> IO Connection -- | A value for the managerRawConnection setting, but also allows -- you to modify the underlying Socket to set additional -- settings. For a motivating use case, see: -- https://github.com/snoyberg/http-client/issues/71. -- -- Since 0.3.8 rawConnectionModifySocket :: Socket -> IO () -> IO Maybe HostAddress -> String -> Int -> IO Connection -- | Send a file as the request body, while observing streaming progress -- via a PopObserver. Observations are made between reading and -- sending a chunk. -- -- It is expected that the file size does not change between calling -- observedStreamFile and making any requests using this request -- body. -- -- Since 0.4.9 observedStreamFile :: StreamFileStatus -> IO () -> FilePath -> IO RequestBody -- | Send a file as the request body. -- -- It is expected that the file size does not change between calling -- streamFile and making any requests using this request body. -- -- Since 0.4.9 streamFile :: FilePath -> IO RequestBody -- | Set the query string to the given key/value pairs. setQueryStringPartialEscape :: [(ByteString, [EscapeItem])] -> Request -> Request -- | Set the query string to the given key/value pairs. -- -- Since 0.3.6 setQueryString :: [(ByteString, Maybe ByteString)] -> Request -> Request -- | Modify the request so that non-2XX status codes generate a runtime -- StatusCodeException, by using throwErrorStatusCodes setRequestCheckStatus :: Request -> Request -- | Modify the request so that non-2XX status codes do not generate a -- runtime StatusCodeException. setRequestIgnoreStatus :: Request -> Request -- | Add url-encoded parameters to the Request. -- -- This sets a new requestBody, adds a content-type request header -- and changes the method to POST. -- -- Since 0.1.0 urlEncodedBody :: [(ByteString, ByteString)] -> Request -> Request -- | Add a Proxy-Authorization header (with the specified username and -- password) to the given Request. Ignore error handling: -- --
-- applyBasicProxyAuth "user" "pass" <$> parseRequest "http://example.org" ---- -- Since 0.3.4 applyBasicProxyAuth :: ByteString -> ByteString -> Request -> Request -- | Add a Basic Auth header (with the specified user name and password) to -- the given Request. Ignore error handling: -- --
-- applyBasicAuth "user" "pass" $ parseRequest_ url ---- -- NOTE: The function applyDigestAuth is provided by the -- http-client-tls package instead of this package due to extra -- dependencies. Please use that package if you need to use digest -- authentication. -- -- Since 0.1.0 applyBasicAuth :: ByteString -> ByteString -> Request -> Request -- | A default request value, a GET request of localhost/:80, with an empty -- request body. -- -- Note that the default checkResponse does nothing. defaultRequest :: Request -- | Extract a URI from the request. -- -- Since 0.1.0 getUri :: Request -> URI -- | Same as requestFromURI, but if the conversion would fail, -- throws an impure exception. requestFromURI_ :: URI -> Request -- | Convert a URI into a Request. -- -- This can fail if the given URI is not absolute, or if the -- URI scheme is not "http" or "https". In these -- cases the function will throw an error via MonadThrow. -- -- This function defaults some of the values in Request, such as -- setting method to GET and requestHeaders -- to []. -- -- A Request created by this function won't cause exceptions on -- non-2XX response status codes. requestFromURI :: MonadThrow m => URI -> m Request -- | Same as parseRequest, but parse errors cause an impure -- exception. Mostly useful for static strings which are known to be -- correctly formatted. parseRequest_ :: String -> Request -- | Convert a URL into a Request. -- -- This function defaults some of the values in Request, such as -- setting method to GET and requestHeaders -- to []. -- -- Since this function uses MonadThrow, the return monad can be -- anything that is an instance of MonadThrow, such as IO -- or Maybe. -- -- You can place the request method at the beginning of the URL separated -- by a space, e.g.: -- -- @@ parseRequest "POST http://httpbin.org/post" @@ -- -- Note that the request method must be provided as all capital letters. -- -- A Request created by this function won't cause exceptions on -- non-2XX response status codes. -- -- To create a request which throws on non-2XX status codes, see -- parseUrlThrow parseRequest :: MonadThrow m => String -> m Request -- | Throws a StatusCodeException wrapped in -- HttpExceptionRequest, if the response's status code indicates -- an error (if it isn't 2xx). This can be used to implement -- checkResponse. throwErrorStatusCodes :: MonadIO m => Request -> Response BodyReader -> m () -- | Same as parseRequest, except will throw an HttpException -- in the event of a non-2XX response. This uses -- throwErrorStatusCodes to implement checkResponse. parseUrlThrow :: MonadThrow m => String -> m Request -- | Deprecated synonym for parseUrlThrow. You probably want -- parseRequest or parseRequest_ instead. parseUrl :: MonadThrow m => String -> m Request -- | Strictly consume all remaining chunks of data from the stream. -- -- Since 0.1.0 brConsume :: BodyReader -> IO [ByteString] -- | Continuously call brRead, building up a lazy ByteString until a -- chunk is constructed that is at least as many bytes as requested. -- -- Since 0.4.20 brReadSome :: BodyReader -> Int -> IO ByteString -- | Get a single chunk of data from the response body, or an empty -- bytestring if no more data is available. -- -- Note that in order to consume the entire request body, you will need -- to repeatedly call this function until you receive an empty -- ByteString as a result. -- -- Since 0.1.0 brRead :: BodyReader -> IO ByteString -- | Create a new Connection from a Socket. socketConnection :: Socket -> Int -> IO Connection -- | Create a new Connection from a read, write, and close function. makeConnection :: IO ByteString -> ByteString -> IO () -> IO () -> IO Connection -- | An IO action that represents an incoming response body coming -- from the server. Data provided by this action has already been -- gunzipped and de-chunked, and respects any content-length headers -- present. -- -- The action gets a single chunk of data from the response body, or an -- empty bytestring if no more data is available. -- -- Since 0.4.0 type BodyReader = IO ByteString -- | An exception which may be generated by this library data HttpException -- | Most exceptions are specific to a Request. Inspect the -- HttpExceptionContent value for details on what occurred. HttpExceptionRequest :: Request -> HttpExceptionContent -> HttpException -- | A URL (first field) is invalid for a given reason (second argument). InvalidUrlException :: String -> String -> HttpException data HttpExceptionContent -- | Generated by the parseUrlThrow function when the server -- returns a non-2XX response status code. -- -- May include the beginning of the response body. StatusCodeException :: Response () -> ByteString -> HttpExceptionContent -- | The server responded with too many redirects for a request. -- -- Contains the list of encountered responses containing redirects in -- reverse chronological order; including last redirect, which triggered -- the exception and was not followed. TooManyRedirects :: [Response ByteString] -> HttpExceptionContent -- | Either too many headers, or too many total bytes in a single header, -- were returned by the server, and the memory exhaustion protection in -- this library has kicked in. OverlongHeaders :: HttpExceptionContent -- | The server took too long to return a response. This can be altered via -- responseTimeout or managerResponseTimeout. ResponseTimeout :: HttpExceptionContent -- | Attempting to connect to the server timed out. ConnectionTimeout :: HttpExceptionContent -- | An exception occurred when trying to connect to the server. ConnectionFailure :: SomeException -> HttpExceptionContent -- | The status line returned by the server could not be parsed. InvalidStatusLine :: ByteString -> HttpExceptionContent -- | The given response header line could not be parsed InvalidHeader :: ByteString -> HttpExceptionContent -- | An exception was raised by an underlying library when performing the -- request. Most often, this is caused by a failing socket action or a -- TLS exception. InternalException :: SomeException -> HttpExceptionContent -- | A non-200 status code was returned when trying to connect to the proxy -- server on the given host and port. ProxyConnectException :: ByteString -> Int -> Status -> HttpExceptionContent -- | No response data was received from the server at all. This exception -- may deserve special handling within the library, since it may indicate -- that a pipelining has been used, and a connection thought to be open -- was in fact closed. NoResponseDataReceived :: HttpExceptionContent -- | Exception thrown when using a Manager which does not have -- support for secure connections. Typically, you will want to use -- tlsManagerSettings from http-client-tls to overcome -- this. TlsNotSupported :: HttpExceptionContent -- | The request body provided did not match the expected size. -- -- Provides the expected and actual size. WrongRequestBodyStreamSize :: Word64 -> Word64 -> HttpExceptionContent -- | The returned response body is too short. Provides the expected size -- and actual size. ResponseBodyTooShort :: Word64 -> Word64 -> HttpExceptionContent -- | A chunked response body had invalid headers. InvalidChunkHeaders :: HttpExceptionContent -- | An incomplete set of response headers were returned. IncompleteHeaders :: HttpExceptionContent -- | The host we tried to connect to is invalid (e.g., an empty string). InvalidDestinationHost :: ByteString -> HttpExceptionContent -- | An exception was thrown when inflating a response body. HttpZlibException :: ZlibException -> HttpExceptionContent -- | Values in the proxy environment variable were invalid. Provides the -- environment variable name and its value. InvalidProxyEnvironmentVariable :: Text -> Text -> HttpExceptionContent -- | Attempted to use a Connection which was already closed ConnectionClosed :: HttpExceptionContent -- | Proxy settings are not valid (Windows specific currently) @since 0.5.7 InvalidProxySettings :: Text -> HttpExceptionContent data Cookie Cookie :: ByteString -> ByteString -> UTCTime -> ByteString -> ByteString -> UTCTime -> UTCTime -> Bool -> Bool -> Bool -> Bool -> Cookie [cookie_name] :: Cookie -> ByteString [cookie_value] :: Cookie -> ByteString [cookie_expiry_time] :: Cookie -> UTCTime [cookie_domain] :: Cookie -> ByteString [cookie_path] :: Cookie -> ByteString [cookie_creation_time] :: Cookie -> UTCTime [cookie_last_access_time] :: Cookie -> UTCTime [cookie_persistent] :: Cookie -> Bool [cookie_host_only] :: Cookie -> Bool [cookie_secure_only] :: Cookie -> Bool [cookie_http_only] :: Cookie -> Bool data CookieJar -- | The host name of the HTTP proxy. proxyHost :: Proxy -> ByteString -- | The port number of the HTTP proxy. proxyPort :: Proxy -> Int -- | When using one of the RequestBodyStream / -- RequestBodyStreamChunked constructors, you must ensure that the -- GivesPopper can be called multiple times. Usually this is not a -- problem. -- -- The RequestBodyStreamChunked will send a chunked request body. -- Note that not all servers support this. Only use -- RequestBodyStreamChunked if you know the server you're sending -- to supports chunked request bodies. -- -- Since 0.1.0 data RequestBody RequestBodyLBS :: ByteString -> RequestBody RequestBodyBS :: ByteString -> RequestBody RequestBodyBuilder :: Int64 -> Builder -> RequestBody RequestBodyStream :: Int64 -> GivesPopper () -> RequestBody RequestBodyStreamChunked :: GivesPopper () -> RequestBody -- | Allows creation of a RequestBody inside the IO -- monad, which is useful for making easier APIs (like -- setRequestBodyFile). RequestBodyIO :: IO RequestBody -> RequestBody -- | A function which generates successive chunks of a request body, -- provider a single empty bytestring when no more data is available. -- -- Since 0.1.0 type Popper = IO ByteString -- | A function which must be provided with a Popper. -- -- Since 0.1.0 type NeedsPopper a = Popper -> IO a -- | A function which will provide a Popper to a NeedsPopper. -- This seemingly convoluted structure allows for creation of request -- bodies which allocate scarce resources in an exception safe manner. -- -- Since 0.1.0 type GivesPopper a = NeedsPopper a -> IO a -- | All information on how to connect to a host and what should be sent in -- the HTTP request. -- -- If you simply wish to download from a URL, see parseRequest. -- -- The constructor for this data type is not exposed. Instead, you should -- use either the defaultRequest value, or parseRequest -- to construct from a URL, and then use the records below to make -- modifications. This approach allows http-client to add configuration -- options without breaking backwards compatibility. -- -- For example, to construct a POST request, you could do something like: -- --
-- initReq <- parseRequest "http://www.example.com/path"
-- let req = initReq
-- { method = "POST"
-- }
--
--
-- For more information, please see
-- http://www.yesodweb.com/book/settings-types.
--
-- Since 0.1.0
data Request
-- | How to deal with timing out a response
data ResponseTimeout
-- | A simple representation of the HTTP response.
--
-- Since 0.1.0
data Response body
-- | Settings for a Manager. Please use the
-- defaultManagerSettings function and then modify individual
-- settings. For more information, see
-- http://www.yesodweb.com/book/settings-types.
--
-- Since 0.1.0
data ManagerSettings
-- | How the HTTP proxy server settings should be discovered.
--
-- Since 0.4.7
data ProxyOverride
-- | Keeps track of open connections for keep-alive.
--
-- If possible, you should share a single Manager between multiple
-- threads and requests.
--
-- Since 0.1.0
data Manager
class HasHttpManager a
getHttpManager :: HasHttpManager a => a -> Manager
-- | Status of streaming a request body from a file.
--
-- Since 0.4.9
data StreamFileStatus
StreamFileStatus :: Int64 -> Int64 -> Int -> StreamFileStatus
[fileSize] :: StreamFileStatus -> Int64
[readSoFar] :: StreamFileStatus -> Int64
[thisChunkSize] :: StreamFileStatus -> Int
fragment :: URI -> String
query :: URI -> String
path :: URI -> String
authority :: URI -> String
scheme :: URI -> String
unreserved :: Char -> Bool
reserved :: Char -> Bool
escapeString :: String -> Char -> Bool -> String
parseabsoluteURI :: String -> Maybe URI
-- | Path segment normalization; cf. RFC3986 section 6.2.2.3
normalizePathSegments :: String -> String
-- | Encoding normalization; cf. RFC3986 section 6.2.2.2
normalizeEscape :: String -> String
-- | Case normalization; cf. RFC3986 section 6.2.2.1 NOTE: authority case
-- normalization is not performed
normalizeCase :: String -> String
-- | Returns a new URI which represents the relative location of the
-- first URI with respect to the second URI. Thus, the
-- values supplied are expected to be absolute URIs, and the result
-- returned may be a relative URI.
--
-- Example:
--
-- -- "http://example.com/Root/sub1/name2#frag" -- `relativeFrom` "http://example.com/Root/sub2/name2#frag" -- == "../sub1/name2#frag" ---- -- There is no single correct implementation of this function, but any -- acceptable implementation must satisfy the following: -- --
-- (uabs `relativeFrom` ubase) `relativeTo` ubase == uabs ---- -- For any valid absolute URI. (cf. -- http://lists.w3.org/Archives/Public/uri/2003Jan/0008.html -- http://lists.w3.org/Archives/Public/uri/2003Jan/0005.html) relativeFrom :: URI -> URI -> URI -- | Returns the segments of the path component. E.g., pathSegments -- $ parseURI "http://example.org/foo/bar/baz" == ["foo", -- "bar", "baz"] pathSegments :: URI -> [String] -- | Returns a new URI which represents the value of the first -- URI interpreted as relative to the second URI. -- -- Algorithm from RFC3986 [3], section 5.2 relativeTo :: URI -> URI -> URI -- | Returns a new URI which represents the value of the first -- URI interpreted as relative to the second URI. For -- example: -- --
-- "foo" `relativeTo` "http://bar.org/" = "http://bar.org/foo" -- "http:foo" `nonStrictRelativeTo` "http://bar.org/" = "http://bar.org/foo" ---- -- Algorithm from RFC3986 [3], section 5.2.2 nonStrictRelativeTo :: URI -> URI -> URI -- | Turns all instances of escaped characters in the string back into -- literal characters. unEscapeString :: String -> String -- | Can be used to make a string valid for use in a URI. escapeURIString :: Char -> Bool -> String -> String -- | Escape character if supplied predicate is not satisfied, otherwise -- return character as singleton string. escapeURIChar :: Char -> Bool -> Char -> String -- | Returns True if the character is allowed unescaped in a URI -- component. -- --
-- >>> escapeURIString isUnescapedInURIComponent "http://haskell.org:80?some_param=true&other_param=їґ" -- "http%3A%2F%2Fhaskell.org%3A80%3Fsome_param%3Dtrue%26other_param%3D%D1%97%D2%91" --isUnescapedInURIComponent :: Char -> Bool -- | Returns True if the character is allowed unescaped in a URI. -- --
-- >>> escapeURIString isUnescapedInURI "http://haskell.org:80?some_param=true&other_param=їґ" -- "http://haskell.org:80?some_param=true&other_param=%D1%97%D2%91" --isUnescapedInURI :: Char -> Bool -- | Returns True if the character is allowed in a URI. isAllowedInURI :: Char -> Bool -- | Turn a URI into a string. -- -- Uses a supplied function to map the userinfo part of the URI. -- -- The Show instance for URI uses a mapping that hides any password that -- may be present in the URI. Use this function with argument id -- to preserve the password in the formatted output. uriToString :: String -> String -> URI -> ShowS -- | Returns True if the character is an "unreserved" character in a -- URI. These characters do not need to be escaped in a URI. The only -- characters allowed in a URI are either "reserved", "unreserved", or an -- escape sequence (% followed by two hex digits). isUnreserved :: Char -> Bool -- | Returns True if the character is a "reserved" character in a -- URI. To include a literal instance of one of these characters in a -- component of a URI, it must be escaped. isReserved :: Char -> Bool uriIsRelative :: URI -> Bool uriIsAbsolute :: URI -> Bool -- | Test if string contains a valid IPv4 address isIPv4address :: String -> Bool -- | Test if string contains a valid IPv6 address isIPv6address :: String -> Bool -- | Test if string contains a valid absolute URI (an absolute URI without -- a fragment identifier). isAbsoluteURI :: String -> Bool -- | Test if string contains a valid relative URI (a relative URI with -- optional fragment identifier). isRelativeReference :: String -> Bool -- | Test if string contains a valid URI reference (an absolute or relative -- URI with optional fragment identifier). isURIReference :: String -> Bool -- | Test if string contains a valid URI (an absolute URI with optional -- fragment identifier). isURI :: String -> Bool -- | Parse an absolute URI to a URI value. Returns Nothing if -- the string is not a valid absolute URI. (an absolute URI without a -- fragment identifier). parseAbsoluteURI :: String -> Maybe URI -- | Parse a relative URI to a URI value. Returns Nothing if -- the string is not a valid relative URI. (a relative URI with optional -- fragment identifier). parseRelativeReference :: String -> Maybe URI -- | Parse a URI reference to a URI value. Returns Nothing if -- the string is not a valid URI reference. (an absolute or relative URI -- with optional fragment identifier). parseURIReference :: String -> Maybe URI -- | Turn a string containing a URI into a URI. Returns -- Nothing if the string is not a valid URI; (an absolute URI with -- optional fragment identifier). -- -- NOTE: this is different from the previous network.URI, whose -- parseURI function works like parseURIReference in this -- module. parseURI :: String -> Maybe URI -- | Blank URI nullURI :: URI -- | Type for authority value within a URI data URIAuth URIAuth :: String -> String -> String -> URIAuth -- |
-- anonymous@ --[uriUserInfo] :: URIAuth -> String -- |
-- www.haskell.org --[uriRegName] :: URIAuth -> String -- |
-- :42 --[uriPort] :: URIAuth -> String -- | Orphan instances and utility functions for Data.Has, a typeclass for -- extracting values from a structure by type. module Magicbane.Has -- | Gets a value of any type from the context. askObj :: (Has β α, MonadReader α μ) => μ β -- | Gets a thing from a value of any type from the context. (Useful for -- configuration fields.) askOpt :: (Has β α, MonadReader α μ) => (β -> ψ) -> μ ψ instance Data.Has.Has Magicbane.HTTPClient.ModHttpClient α => Network.HTTP.Client.Types.HasHttpManager α instance Data.Has.Has Magicbane.Logging.ModLogger α => RIO.Prelude.Logger.HasLogFunc α instance (Data.Has.Has Magicbane.Metrics.ModMetrics α, GHC.Base.Monad μ, Control.Monad.Reader.Class.MonadReader α μ) => Control.Monad.Metrics.MonadMetrics μ -- | Utility functions and reexports for System.Envy, an environment -- variable config reader. module Magicbane.Config -- | Display all environment variables, for convenience showEnv :: IO () -- | Unset Environment using a value of class ToEnv unsetEnvironment' :: ToEnv a => a -> IO Either String () -- | Unset Environment from a ToEnv constrained type unsetEnvironment :: () => EnvList a -> IO Either String () -- | Set environment directly using a value of class ToEnv setEnvironment' :: ToEnv a => a -> IO Either String () -- | Set environment via a ToEnv constrained type setEnvironment :: () => EnvList a -> IO Either String () -- | Environment retrieval with failure info decodeEnv :: FromEnv a => IO Either String a -- | Smart constructor, environment creation helper. makeEnv :: () => [EnvVar] -> EnvList a -- | Meant for specifying a custom Option for environment retrieval -- --
-- instance FromEnv PGConfig where
-- fromEnv = gFromEnvCustom Option { dropPrefixCount = 8, customPrefix = "PG" }
--
gFromEnvCustom :: (DefConfig a, Generic a, GFromEnv Rep a) => Option -> Parser a
-- | Environment variable getter returning Maybe
envMaybe :: Var a => String -> Parser Maybe a
-- | Environment variable getter. Fails if the variable is not set or fails
-- to parse.
env :: Var a => String -> Parser a
-- | For use with Generics, no FromEnv typeclass necessary
--
-- -- getPgConfig :: IO (Either String ConnectInfo) -- getPgConfig = runEnv $ gFromEnvCustom defOption --runEnv :: () => Parser a -> IO Either String a -- | Parser Monad for environment variable retrieval newtype Parser a Parser :: ExceptT String IO a -> Parser a [runParser] :: Parser a -> ExceptT String IO a -- | FromEnv Typeclass w/ Generic default implementation class FromEnv a fromEnv :: FromEnv a => Parser a -- | Type class for objects which have a default configuration. class DefConfig a defConfig :: DefConfig a => a -- | For customizing environment variable generation data Option Option :: Int -> String -> Option -- | Applied first [dropPrefixCount] :: Option -> Int -- | Converted toUpper [customPrefix] :: Option -> String -- | Type class for objects which can be converted to a set of environment -- variable settings. class ToEnv a -- | Convert an object into a list of environment variable settings. toEnv :: ToEnv a => a -> EnvList a -- | List of environment variables. Captures a "phantom type" which allows -- the type checker to detect the proper implementation of toEnv to use. data EnvList a -- | Class for converting to / from an environment variable class Typeable a => Var a -- | Convert a value into an environment variable. toVar :: Var a => a -> String -- | Parse an environment variable. fromVar :: Var a => String -> Maybe a decodeEnvy :: FromEnv a => IO Maybe a -- | Reads an Envy configuration from the env variables and launches the -- given action if successful. (Does environment variable reading ever -- fail in practice? Probably not.) withEnvConfig :: FromEnv α => (α -> IO ()) -> IO () -- | Integrates the refinement types from the refined library with aeson. module Magicbane.Validation instance Data.Aeson.Types.ToJSON.ToJSON α => Data.Aeson.Types.ToJSON.ToJSON (Refined.Refined ρ α) instance (Data.Aeson.Types.FromJSON.FromJSON α, Refined.Predicate ρ α) => Data.Aeson.Types.FromJSON.FromJSON (Refined.Refined ρ α) -- | A Dropwizard-inspired web framework that integrates Servant, -- monad-metricsEKG, monad-loggerfast-logger, and other useful -- libraries to provide a smooth web service development experience. -- -- This module provides all the stuff you need for an application: - -- reexports from all the modules below, including orphan instances from -- Magicbane.Has - orphan instances for RIO - reexports from various -- utility packages - a basic example context for simple apps module Magicbane -- | If the first argument evaluates to True, then the result is the -- second argument. Otherwise an AssertionFailed exception is -- raised, containing a String with the source file and line -- number of the call to assert. -- -- Assertions can normally be turned on or off with a compiler flag (for -- GHC, assertions are normally on unless optimisation is turned on with -- -O or the -fignore-asserts option is given). When -- assertions are turned off, the first argument to assert is -- ignored, and the second argument is returned as the result. assert :: () => Bool -> a -> a -- | The class Typeable allows a concrete representation of a type -- to be calculated. class Typeable (a :: k) -- | Like decodeFileStrict' but returns an error message when -- decoding fails. eitherDecodeFileStrict' :: FromJSON a => FilePath -> IO Either String a -- | Like decodeStrict' but returns an error message when decoding -- fails. eitherDecodeStrict' :: FromJSON a => ByteString -> Either String a -- | Like decode' but returns an error message when decoding fails. eitherDecode' :: FromJSON a => ByteString -> Either String a -- | Like decodeFileStrict but returns an error message when -- decoding fails. eitherDecodeFileStrict :: FromJSON a => FilePath -> IO Either String a -- | Like decodeStrict but returns an error message when decoding -- fails. eitherDecodeStrict :: FromJSON a => ByteString -> Either String a -- | Like decode but returns an error message when decoding fails. eitherDecode :: FromJSON a => ByteString -> Either String a -- | Efficiently deserialize a JSON value from a file. If this fails due to -- incomplete or invalid input, Nothing is returned. -- -- The input file's content must consist solely of a JSON document, with -- no trailing data except for whitespace. -- -- This function parses and performs conversion immediately. See -- json' for details. decodeFileStrict' :: FromJSON a => FilePath -> IO Maybe a -- | Efficiently deserialize a JSON value from a strict ByteString. -- If this fails due to incomplete or invalid input, Nothing is -- returned. -- -- The input must consist solely of a JSON document, with no trailing -- data except for whitespace. -- -- This function parses and performs conversion immediately. See -- json' for details. decodeStrict' :: FromJSON a => ByteString -> Maybe a -- | Efficiently deserialize a JSON value from a lazy ByteString. If -- this fails due to incomplete or invalid input, Nothing is -- returned. -- -- The input must consist solely of a JSON document, with no trailing -- data except for whitespace. -- -- This function parses and performs conversion immediately. See -- json' for details. decode' :: FromJSON a => ByteString -> Maybe a -- | Efficiently deserialize a JSON value from a file. If this fails due to -- incomplete or invalid input, Nothing is returned. -- -- The input file's content must consist solely of a JSON document, with -- no trailing data except for whitespace. -- -- This function parses immediately, but defers conversion. See -- json for details. decodeFileStrict :: FromJSON a => FilePath -> IO Maybe a -- | Efficiently deserialize a JSON value from a strict ByteString. -- If this fails due to incomplete or invalid input, Nothing is -- returned. -- -- The input must consist solely of a JSON document, with no trailing -- data except for whitespace. -- -- This function parses immediately, but defers conversion. See -- json for details. decodeStrict :: FromJSON a => ByteString -> Maybe a -- | Efficiently deserialize a JSON value from a lazy ByteString. If -- this fails due to incomplete or invalid input, Nothing is -- returned. -- -- The input must consist solely of a JSON document, with no trailing -- data except for whitespace. -- -- This function parses immediately, but defers conversion. See -- json for details. decode :: FromJSON a => ByteString -> Maybe a -- | Efficiently serialize a JSON value as a lazy ByteString and -- write it to a file. encodeFile :: ToJSON a => FilePath -> a -> IO () -- | Efficiently serialize a JSON value as a lazy ByteString. -- -- This is implemented in terms of the ToJSON class's -- toEncoding method. encode :: ToJSON a => a -> ByteString -- | Encode a Foldable as a JSON array. foldable :: (Foldable t, ToJSON a) => t a -> Encoding type GToJSON = GToJSON Value type GToEncoding = GToJSON Encoding -- | Lift the standard toEncoding function through the type -- constructor. toEncoding2 :: (ToJSON2 f, ToJSON a, ToJSON b) => f a b -> Encoding -- | Lift the standard toJSON function through the type constructor. toJSON2 :: (ToJSON2 f, ToJSON a, ToJSON b) => f a b -> Value -- | Lift the standard toEncoding function through the type -- constructor. toEncoding1 :: (ToJSON1 f, ToJSON a) => f a -> Encoding -- | Lift the standard toJSON function through the type constructor. toJSON1 :: (ToJSON1 f, ToJSON a) => f a -> Value -- | A configurable generic JSON encoder. This function applied to -- defaultOptions is used as the default for liftToEncoding -- when the type is an instance of Generic1. genericLiftToEncoding :: (Generic1 f, GToJSON Encoding One Rep1 f) => Options -> a -> Encoding -> [a] -> Encoding -> f a -> Encoding -- | A configurable generic JSON encoder. This function applied to -- defaultOptions is used as the default for toEncoding -- when the type is an instance of Generic. genericToEncoding :: (Generic a, GToJSON Encoding Zero Rep a) => Options -> a -> Encoding -- | A configurable generic JSON creator. This function applied to -- defaultOptions is used as the default for liftToJSON -- when the type is an instance of Generic1. genericLiftToJSON :: (Generic1 f, GToJSON Value One Rep1 f) => Options -> a -> Value -> [a] -> Value -> f a -> Value -- | A configurable generic JSON creator. This function applied to -- defaultOptions is used as the default for toJSON when -- the type is an instance of Generic. genericToJSON :: (Generic a, GToJSON Value Zero Rep a) => Options -> a -> Value -- | A ToArgs value either stores nothing (for ToJSON) or it -- stores the two function arguments that encode occurrences of the type -- parameter (for ToJSON1). data ToArgs res arity a [NoToArgs] :: ToArgs res Zero a [To1Args] :: ToArgs res One a -- | A type that can be converted to JSON. -- -- Instances in general must specify toJSON and -- should (but don't need to) specify toEncoding. -- -- An example type and instance: -- --
-- -- Allow ourselves to write Text literals.
-- {-# LANGUAGE OverloadedStrings #-}
--
-- data Coord = Coord { x :: Double, y :: Double }
--
-- instance ToJSON Coord where
-- toJSON (Coord x y) = object ["x" .= x, "y" .= y]
--
-- toEncoding (Coord x y) = pairs ("x" .= x <> "y" .= y)
--
--
-- Instead of manually writing your ToJSON instance, there are two
-- options to do it automatically:
--
--
-- {-# LANGUAGE DeriveGeneric #-}
--
-- import GHC.Generics
--
-- data Coord = Coord { x :: Double, y :: Double } deriving Generic
--
-- instance ToJSON Coord where
-- toEncoding = genericToEncoding defaultOptions
--
--
-- If on the other hand you wish to customize the generic decoding, you
-- have to implement both methods:
--
--
-- customOptions = defaultOptions
-- { fieldLabelModifier = map toUpper
-- }
--
-- instance ToJSON Coord where
-- toJSON = genericToJSON customOptions
-- toEncoding = genericToEncoding customOptions
--
--
-- Previous versions of this library only had the toJSON method.
-- Adding toEncoding had to reasons:
--
-- -- instance ToJSON Coord where -- toEncoding = genericToEncoding defaultOptions --toEncoding :: ToJSON a => a -> Encoding toJSONList :: ToJSON a => [a] -> Value toEncodingList :: ToJSON a => [a] -> Encoding -- | A key-value pair for encoding a JSON object. class KeyValue kv (.=) :: (KeyValue kv, ToJSON v) => Text -> v -> kv -- | Typeclass for types that can be used as the key of a map-like -- container (like Map or HashMap). For example, since -- Text has a ToJSONKey instance and Char has a -- ToJSON instance, we can encode a value of type Map -- Text Char: -- --
-- >>> LBC8.putStrLn $ encode $ Map.fromList [("foo" :: Text, 'a')]
-- {"foo":"a"}
--
--
-- Since Int also has a ToJSONKey instance, we can
-- similarly write:
--
--
-- >>> LBC8.putStrLn $ encode $ Map.fromList [(5 :: Int, 'a')]
-- {"5":"a"}
--
--
-- JSON documents only accept strings as object keys. For any type from
-- base that has a natural textual representation, it can be
-- expected that its ToJSONKey instance will choose that
-- representation.
--
-- For data types that lack a natural textual representation, an
-- alternative is provided. The map-like container is represented as a
-- JSON array instead of a JSON object. Each value in the array is an
-- array with exactly two values. The first is the key and the second is
-- the value.
--
-- For example, values of type '[Text]' cannot be encoded to a string, so
-- a Map with keys of type '[Text]' is encoded as follows:
--
-- -- >>> LBC8.putStrLn $ encode $ Map.fromList [(["foo","bar","baz" :: Text], 'a')] -- [[["foo","bar","baz"],"a"]] ---- -- The default implementation of ToJSONKey chooses this method of -- encoding a key, using the ToJSON instance of the type. -- -- To use your own data type as the key in a map, all that is needed is -- to write a ToJSONKey (and possibly a FromJSONKey) -- instance for it. If the type cannot be trivially converted to and from -- Text, it is recommended that ToJSONKeyValue is used. -- Since the default implementations of the typeclass methods can build -- this from a ToJSON instance, there is nothing that needs to be -- written: -- --
-- data Foo = Foo { fooAge :: Int, fooName :: Text }
-- deriving (Eq,Ord,Generic)
-- instance ToJSON Foo
-- instance ToJSONKey Foo
--
--
-- That's it. We can now write:
--
--
-- >>> let m = Map.fromList [(Foo 4 "bar",'a'),(Foo 6 "arg",'b')]
--
-- >>> LBC8.putStrLn $ encode m
-- [[{"fooName":"bar","fooAge":4},"a"],[{"fooName":"arg","fooAge":6},"b"]]
--
--
-- The next case to consider is if we have a type that is a newtype
-- wrapper around Text. The recommended approach is to use
-- generalized newtype deriving:
--
--
-- newtype RecordId = RecordId { getRecordId :: Text}
-- deriving (Eq,Ord,ToJSONKey)
--
--
-- Then we may write:
--
--
-- >>> LBC8.putStrLn $ encode $ Map.fromList [(RecordId "abc",'a')]
-- {"abc":"a"}
--
--
-- Simple sum types are a final case worth considering. Suppose we have:
--
-- -- data Color = Red | Green | Blue -- deriving (Show,Read,Eq,Ord) ---- -- It is possible to get the ToJSONKey instance for free as we did -- with Foo. However, in this case, we have a natural way to go -- to and from Text that does not require any escape sequences. -- So, in this example, ToJSONKeyText will be used instead of -- ToJSONKeyValue. The Show instance can be used to help -- write ToJSONKey: -- --
-- instance ToJSONKey Color where -- toJSONKey = ToJSONKeyText f g -- where f = Text.pack . show -- g = text . Text.pack . show -- -- text function is from Data.Aeson.Encoding ---- -- The situation of needing to turning function a -> Text -- into a ToJSONKeyFunction is common enough that a special -- combinator is provided for it. The above instance can be rewritten as: -- --
-- instance ToJSONKey Color where -- toJSONKey = toJSONKeyText (Text.pack . show) ---- -- The performance of the above instance can be improved by not using -- String as an intermediate step when converting to Text. -- One option for improving performance would be to use template haskell -- machinery from the text-show package. However, even with the -- approach, the Encoding (a wrapper around a bytestring builder) -- is generated by encoding the Text to a ByteString, an -- intermediate step that could be avoided. The fastest possible -- implementation would be: -- --
-- -- Assuming that OverloadedStrings is enabled
-- instance ToJSONKey Color where
-- toJSONKey = ToJSONKeyText f g
-- where f x = case x of {Red -> "Red";Green ->"Green";Blue -> "Blue"}
-- g x = case x of {Red -> text "Red";Green -> text "Green";Blue -> text "Blue"}
-- -- text function is from Data.Aeson.Encoding
--
--
-- This works because GHC can lift the encoded values out of the case
-- statements, which means that they are only evaluated once. This
-- approach should only be used when there is a serious need to maximize
-- performance.
class ToJSONKey a
-- | Strategy for rendering the key for a map-like container.
toJSONKey :: ToJSONKey a => ToJSONKeyFunction a
-- | This is similar in spirit to the showsList method of
-- Show. It makes it possible to give String keys special
-- treatment without using OverlappingInstances. End users
-- should always be able to use the default implementation of this
-- method.
toJSONKeyList :: ToJSONKey a => ToJSONKeyFunction [a]
data ToJSONKeyFunction a
-- | key is encoded to string, produces object
ToJSONKeyText :: !a -> Text -> !a -> Encoding' Text -> ToJSONKeyFunction a
-- | key is encoded to value, produces array
ToJSONKeyValue :: !a -> Value -> !a -> Encoding -> ToJSONKeyFunction a
-- | Lifting of the ToJSON class to unary type constructors.
--
-- Instead of manually writing your ToJSON1 instance, there are
-- two options to do it automatically:
--
--
-- {-# LANGUAGE DeriveGeneric #-}
--
-- import GHC.Generics
--
-- data Pair = Pair { pairFst :: a, pairSnd :: b } deriving Generic1
--
-- instance ToJSON a => ToJSON1 (Pair a)
--
--
-- If the default implementation doesn't give exactly the results you
-- want, you can customize the generic encoding with only a tiny amount
-- of effort, using genericLiftToJSON and
-- genericLiftToEncoding with your preferred Options:
--
--
-- customOptions = defaultOptions
-- { fieldLabelModifier = map toUpper
-- }
--
-- instance ToJSON a => ToJSON1 (Pair a) where
-- liftToJSON = genericLiftToJSON customOptions
-- liftToEncoding = genericLiftToEncoding customOptions
--
--
-- See also ToJSON.
class ToJSON1 (f :: * -> *)
liftToJSON :: ToJSON1 f => a -> Value -> [a] -> Value -> f a -> Value
liftToJSONList :: ToJSON1 f => a -> Value -> [a] -> Value -> [f a] -> Value
liftToEncoding :: ToJSON1 f => a -> Encoding -> [a] -> Encoding -> f a -> Encoding
liftToEncodingList :: ToJSON1 f => a -> Encoding -> [a] -> Encoding -> [f a] -> Encoding
-- | Lifting of the ToJSON class to binary type constructors.
--
-- Instead of manually writing your ToJSON2 instance,
-- Data.Aeson.TH provides Template Haskell functions which will
-- derive an instance at compile time.
--
-- The compiler cannot provide a default generic implementation for
-- liftToJSON2, unlike toJSON and liftToJSON.
class ToJSON2 (f :: * -> * -> *)
liftToJSON2 :: ToJSON2 f => a -> Value -> [a] -> Value -> b -> Value -> [b] -> Value -> f a b -> Value
liftToJSONList2 :: ToJSON2 f => a -> Value -> [a] -> Value -> b -> Value -> [b] -> Value -> [f a b] -> Value
liftToEncoding2 :: ToJSON2 f => a -> Encoding -> [a] -> Encoding -> b -> Encoding -> [b] -> Encoding -> f a b -> Encoding
liftToEncodingList2 :: ToJSON2 f => a -> Encoding -> [a] -> Encoding -> b -> Encoding -> [b] -> Encoding -> [f a b] -> Encoding
-- | Encode a series of key/value pairs, separated by commas.
pairs :: Series -> Encoding
-- | Acquire the underlying bytestring builder.
fromEncoding :: Encoding' tag -> Builder
-- | Often used synonym for Encoding'.
type Encoding = Encoding' Value
-- | A series of values that, when encoded, should be separated by commas.
-- Since 0.11.0.0, the .= operator is overloaded to create
-- either (Text, Value) or Series. You can use Series
-- when encoding directly to a bytestring builder as in the following
-- example:
--
--
-- toEncoding (Person name age) = pairs ("name" .= name <> "age" .= age)
--
data Series
-- | Helper for use in combination with .:? to provide default
-- values for optional JSON object fields.
--
-- This combinator is most useful if the key and value can be absent from
-- an object without affecting its validity and we know a default value
-- to assign in that case. If the key and value are mandatory, use
-- .: instead.
--
-- Example usage:
--
-- -- v1 <- o .:? "opt_field_with_dfl" .!= "default_val" -- v2 <- o .: "mandatory_field" -- v3 <- o .:? "opt_field2" --(.!=) :: () => Parser Maybe a -> a -> Parser a -- | Retrieve the value associated with the given key of an Object. -- The result is Nothing if the key is not present or -- empty if the value cannot be converted to the desired type. -- -- This differs from .:? by attempting to parse Null the -- same as any other JSON value, instead of interpreting it as -- Nothing. (.:!) :: FromJSON a => Object -> Text -> Parser Maybe a -- | Retrieve the value associated with the given key of an Object. -- The result is Nothing if the key is not present or if its value -- is Null, or empty if the value cannot be converted to -- the desired type. -- -- This accessor is most useful if the key and value can be absent from -- an object without affecting its validity. If the key and value are -- mandatory, use .: instead. (.:?) :: FromJSON a => Object -> Text -> Parser Maybe a -- | Retrieve the value associated with the given key of an Object. -- The result is empty if the key is not present or the value -- cannot be converted to the desired type. -- -- This accessor is appropriate if the key and value must be -- present in an object for it to be valid. If the key and value are -- optional, use .:? instead. (.:) :: FromJSON a => Object -> Text -> Parser a -- | Convert a value from JSON, failing if the types do not match. fromJSON :: FromJSON a => Value -> Result a -- | Decode a nested JSON-encoded string. withEmbeddedJSON :: () => String -> Value -> Parser a -> Value -> Parser a -- | withBool expected f value applies f to the -- Bool when value is a Bool and fails using -- typeMismatch expected otherwise. withBool :: () => String -> Bool -> Parser a -> Value -> Parser a -- | withScientific expected f value applies f to -- the Scientific number when value is a Number -- and fails using typeMismatch expected otherwise. . -- Warning: If you are converting from a scientific to an -- unbounded type such as Integer you may want to add a -- restriction on the size of the exponent (see -- withBoundedScientific) to prevent malicious input from filling -- up the memory of the target system. withScientific :: () => String -> Scientific -> Parser a -> Value -> Parser a -- | withArray expected f value applies f to the -- Array when value is an Array and fails using -- typeMismatch expected otherwise. withArray :: () => String -> Array -> Parser a -> Value -> Parser a -- | withText expected f value applies f to the -- Text when value is a String and fails using -- typeMismatch expected otherwise. withText :: () => String -> Text -> Parser a -> Value -> Parser a -- | withObject expected f value applies f to the -- Object when value is an Object and fails using -- typeMismatch expected otherwise. withObject :: () => String -> Object -> Parser a -> Value -> Parser a -- | Lift the standard parseJSON function through the type -- constructor. parseJSON2 :: (FromJSON2 f, FromJSON a, FromJSON b) => Value -> Parser f a b -- | Lift the standard parseJSON function through the type -- constructor. parseJSON1 :: (FromJSON1 f, FromJSON a) => Value -> Parser f a -- | A configurable generic JSON decoder. This function applied to -- defaultOptions is used as the default for liftParseJSON -- when the type is an instance of Generic1. genericLiftParseJSON :: (Generic1 f, GFromJSON One Rep1 f) => Options -> Value -> Parser a -> Value -> Parser [a] -> Value -> Parser f a -- | A configurable generic JSON decoder. This function applied to -- defaultOptions is used as the default for parseJSON when -- the type is an instance of Generic. genericParseJSON :: (Generic a, GFromJSON Zero Rep a) => Options -> Value -> Parser a -- | Class of generic representation types that can be converted from JSON. class GFromJSON arity (f :: * -> *) -- | This method (applied to defaultOptions) is used as the default -- generic implementation of parseJSON (if the arity is -- Zero) or liftParseJSON (if the arity is -- One). gParseJSON :: GFromJSON arity f => Options -> FromArgs arity a -> Value -> Parser f a -- | A FromArgs value either stores nothing (for FromJSON) or -- it stores the two function arguments that decode occurrences of the -- type parameter (for FromJSON1). data FromArgs arity a [NoFromArgs] :: FromArgs Zero a [From1Args] :: FromArgs One a -- | A type that can be converted from JSON, with the possibility of -- failure. -- -- In many cases, you can get the compiler to generate parsing code for -- you (see below). To begin, let's cover writing an instance by hand. -- -- There are various reasons a conversion could fail. For example, an -- Object could be missing a required key, an Array could -- be of the wrong size, or a value could be of an incompatible type. -- -- The basic ways to signal a failed conversion are as follows: -- --
-- -- Allow ourselves to write Text literals.
-- {-# LANGUAGE OverloadedStrings #-}
--
-- data Coord = Coord { x :: Double, y :: Double }
--
-- instance FromJSON Coord where
-- parseJSON (Object v) = Coord
-- <$> v .: "x"
-- <*> v .: "y"
--
-- -- We do not expect a non-Object value here.
-- -- We could use mzero to fail, but typeMismatch
-- -- gives a much more informative error message.
-- parseJSON invalid = typeMismatch "Coord" invalid
--
--
-- For this common case of only being concerned with a single type of
-- JSON value, the functions withObject, withNumber, etc.
-- are provided. Their use is to be preferred when possible, since they
-- are more terse. Using withObject, we can rewrite the above
-- instance (assuming the same language extension and data type) as:
--
-- -- instance FromJSON Coord where -- parseJSON = withObject "Coord" $ \v -> Coord -- <$> v .: "x" -- <*> v .: "y" ---- -- Instead of manually writing your FromJSON instance, there are -- two options to do it automatically: -- --
-- {-# LANGUAGE DeriveGeneric #-}
--
-- import GHC.Generics
--
-- data Coord = Coord { x :: Double, y :: Double } deriving Generic
--
-- instance FromJSON Coord
--
--
-- The default implementation will be equivalent to parseJSON =
-- genericParseJSON defaultOptions; If you need
-- different options, you can customize the generic decoding by defining:
--
--
-- customOptions = defaultOptions
-- { fieldLabelModifier = map toUpper
-- }
--
-- instance FromJSON Coord where
-- parseJSON = genericParseJSON customOptions
--
class FromJSON a
parseJSON :: FromJSON a => Value -> Parser a
parseJSONList :: FromJSON a => Value -> Parser [a]
-- | Read the docs for ToJSONKey first. This class is a conversion
-- in the opposite direction. If you have a newtype wrapper around
-- Text, the recommended way to define instances is with
-- generalized newtype deriving:
--
--
-- newtype SomeId = SomeId { getSomeId :: Text }
-- deriving (Eq,Ord,Hashable,FromJSONKey)
--
class FromJSONKey a
-- | Strategy for parsing the key of a map-like container.
fromJSONKey :: FromJSONKey a => FromJSONKeyFunction a
-- | This is similar in spirit to the readList method of
-- Read. It makes it possible to give String keys special
-- treatment without using OverlappingInstances. End users
-- should always be able to use the default implementation of this
-- method.
fromJSONKeyList :: FromJSONKey a => FromJSONKeyFunction [a]
-- | This type is related to ToJSONKeyFunction. If
-- FromJSONKeyValue is used in the FromJSONKey instance,
-- then ToJSONKeyValue should be used in the ToJSONKey
-- instance. The other three data constructors for this type all
-- correspond to ToJSONKeyText. Strictly speaking,
-- FromJSONKeyTextParser is more powerful than
-- FromJSONKeyText, which is in turn more powerful than
-- FromJSONKeyCoerce. For performance reasons, these exist as
-- three options instead of one.
data FromJSONKeyFunction a
-- | uses coerce (unsafeCoerce in older GHCs)
FromJSONKeyCoerce :: !CoerceText a -> FromJSONKeyFunction a
-- | conversion from Text that always succeeds
FromJSONKeyText :: !Text -> a -> FromJSONKeyFunction a
-- | conversion from Text that may fail
FromJSONKeyTextParser :: !Text -> Parser a -> FromJSONKeyFunction a
-- | conversion for non-textual keys
FromJSONKeyValue :: !Value -> Parser a -> FromJSONKeyFunction a
-- | Lifting of the FromJSON class to unary type constructors.
--
-- Instead of manually writing your FromJSON1 instance, there are
-- two options to do it automatically:
--
--
-- {-# LANGUAGE DeriveGeneric #-}
--
-- import GHC.Generics
--
-- data Pair a b = Pair { pairFst :: a, pairSnd :: b } deriving Generic1
--
-- instance FromJSON a => FromJSON1 (Pair a)
--
--
-- If the default implementation doesn't give exactly the results you
-- want, you can customize the generic decoding with only a tiny amount
-- of effort, using genericLiftParseJSON with your preferred
-- Options:
--
--
-- customOptions = defaultOptions
-- { fieldLabelModifier = map toUpper
-- }
--
-- instance FromJSON a => FromJSON1 (Pair a) where
-- liftParseJSON = genericLiftParseJSON customOptions
--
class FromJSON1 (f :: * -> *)
liftParseJSON :: FromJSON1 f => Value -> Parser a -> Value -> Parser [a] -> Value -> Parser f a
liftParseJSONList :: FromJSON1 f => Value -> Parser a -> Value -> Parser [a] -> Value -> Parser [f a]
-- | Lifting of the FromJSON class to binary type constructors.
--
-- Instead of manually writing your FromJSON2 instance,
-- Data.Aeson.TH provides Template Haskell functions which will
-- derive an instance at compile time.
class FromJSON2 (f :: * -> * -> *)
liftParseJSON2 :: FromJSON2 f => Value -> Parser a -> Value -> Parser [a] -> Value -> Parser b -> Value -> Parser [b] -> Value -> Parser f a b
liftParseJSONList2 :: FromJSON2 f => Value -> Parser a -> Value -> Parser [a] -> Value -> Parser b -> Value -> Parser [b] -> Value -> Parser [f a b]
-- | Parse a top-level JSON value.
--
-- This is a strict version of json which avoids building up
-- thunks during parsing; it performs all conversions immediately. Prefer
-- this version if most of the JSON data needs to be accessed.
--
-- This function is an alias for value'. In aeson 0.8 and earlier,
-- it parsed only object or array types, in conformance with the
-- now-obsolete RFC 4627.
json' :: Parser Value
-- | Parse a top-level JSON value.
--
-- The conversion of a parsed value to a Haskell value is deferred until
-- the Haskell value is needed. This may improve performance if only a
-- subset of the results of conversions are needed, but at a cost in
-- thunk allocation.
--
-- This function is an alias for value. In aeson 0.8 and earlier,
-- it parsed only object or array types, in conformance with the
-- now-obsolete RFC 4627.
json :: Parser Value
-- | Better version of camelTo. Example where it works better:
--
-- -- camelTo '_' 'CamelAPICase' == "camel_apicase" -- camelTo2 '_' 'CamelAPICase' == "camel_api_case" --camelTo2 :: Char -> String -> String -- | Default TaggedObject SumEncoding options: -- --
-- defaultTaggedObject = TaggedObject
-- { tagFieldName = "tag"
-- , contentsFieldName = "contents"
-- }
--
defaultTaggedObject :: SumEncoding
-- | Default encoding Options:
--
--
-- Options
-- { fieldLabelModifier = id
-- , constructorTagModifier = id
-- , allNullaryToStringTag = True
-- , omitNothingFields = False
-- , sumEncoding = defaultTaggedObject
-- , unwrapUnaryRecords = False
-- , tagSingleConstructors = False
-- }
--
defaultOptions :: Options
-- | Create a Value from a list of name/value Pairs. If
-- duplicate keys arise, earlier keys and their associated values win.
object :: [Pair] -> Value
-- | The result of running a Parser.
data Result a
Error :: String -> Result a
Success :: a -> Result a
-- | A JSON "object" (key/value map).
type Object = HashMap Text Value
-- | A JSON "array" (sequence).
type Array = Vector Value
-- | A JSON value represented as a Haskell value.
data Value
Object :: !Object -> Value
Array :: !Array -> Value
String :: !Text -> Value
Number :: !Scientific -> Value
Bool :: !Bool -> Value
Null :: Value
-- | A newtype wrapper for UTCTime that uses the same non-standard
-- serialization format as Microsoft .NET, whose System.DateTime
-- type is by default serialized to JSON as in the following example:
--
-- -- /Date(1302547608878)/ ---- -- The number represents milliseconds since the Unix epoch. newtype DotNetTime DotNetTime :: UTCTime -> DotNetTime -- | Acquire the underlying value. [fromDotNetTime] :: DotNetTime -> UTCTime -- | Options that specify how to encode/decode your datatype to/from JSON. -- -- Options can be set using record syntax on defaultOptions with -- the fields below. data Options -- | Specifies how to encode constructors of a sum datatype. data SumEncoding -- | A constructor will be encoded to an object with a field -- tagFieldName which specifies the constructor tag (modified by -- the constructorTagModifier). If the constructor is a record the -- encoded record fields will be unpacked into this object. So make sure -- that your record doesn't have a field with the same label as the -- tagFieldName. Otherwise the tag gets overwritten by the encoded -- value of that field! If the constructor is not a record the encoded -- constructor contents will be stored under the contentsFieldName -- field. TaggedObject :: String -> String -> SumEncoding [tagFieldName] :: SumEncoding -> String [contentsFieldName] :: SumEncoding -> String -- | Constructor names won't be encoded. Instead only the contents of the -- constructor will be encoded as if the type had a single constructor. -- JSON encodings have to be disjoint for decoding to work properly. -- -- When decoding, constructors are tried in the order of definition. If -- some encodings overlap, the first one defined will succeed. -- -- Note: Nullary constructors are encoded as strings (using -- constructorTagModifier). Having a nullary constructor alongside -- a single field constructor that encodes to a string leads to -- ambiguity. -- -- Note: Only the last error is kept when decoding, so in the case -- of malformed JSON, only an error for the last constructor will be -- reported. UntaggedValue :: SumEncoding -- | A constructor will be encoded to an object with a single field named -- after the constructor tag (modified by the -- constructorTagModifier) which maps to the encoded contents of -- the constructor. ObjectWithSingleField :: SumEncoding -- | A constructor will be encoded to a 2-element array where the first -- element is the tag of the constructor (modified by the -- constructorTagModifier) and the second element the encoded -- contents of the constructor. TwoElemArray :: SumEncoding -- | A type-level indicator that ToJSON or FromJSON is -- being derived generically. data Zero -- | A type-level indicator that ToJSON1 or FromJSON1 is -- being derived generically. data One aesonQQ :: QuasiQuoter -- | A ThreadId is an abstract type representing a handle to a -- thread. ThreadId is an instance of Eq, Ord and -- Show, where the Ord instance implements an arbitrary -- total ordering over ThreadIds. The Show instance lets -- you convert an arbitrary-valued ThreadId to string form; -- showing a ThreadId value is occasionally useful when debugging -- or diagnosing the behaviour of a concurrent program. -- -- Note: in GHC, if you have a ThreadId, you essentially -- have a pointer to the thread itself. This means the thread itself -- can't be garbage collected until you drop the ThreadId. This -- misfeature will hopefully be corrected at a later date. data ThreadId -- | True if bound threads are supported. If -- rtsSupportsBoundThreads is False, -- isCurrentThreadBound will always return False and both -- forkOS and runInBoundThread will fail. rtsSupportsBoundThreads :: Bool -- | Chan is an abstract type representing an unbounded FIFO -- channel. data Chan a -- | Superclass for asynchronous exceptions. data SomeAsyncException [SomeAsyncException] :: SomeAsyncException -- | Exceptions that occur in the IO monad. An -- IOException records a more specific error type, a descriptive -- string and maybe the handle that was used when the error was flagged. data IOException -- | Any type that you wish to throw or catch as an exception must be an -- instance of the Exception class. The simplest case is a new -- exception type directly below the root: -- --
-- data MyException = ThisException | ThatException -- deriving Show -- -- instance Exception MyException ---- -- The default method definitions in the Exception class do what -- we need in this case. You can now throw and catch -- ThisException and ThatException as exceptions: -- --
-- *Main> throw ThisException `catch` \e -> putStrLn ("Caught " ++ show (e :: MyException))
-- Caught ThisException
--
--
-- In more complicated examples, you may wish to define a whole hierarchy
-- of exceptions:
--
-- -- --------------------------------------------------------------------- -- -- Make the root exception type for all the exceptions in a compiler -- -- data SomeCompilerException = forall e . Exception e => SomeCompilerException e -- -- instance Show SomeCompilerException where -- show (SomeCompilerException e) = show e -- -- instance Exception SomeCompilerException -- -- compilerExceptionToException :: Exception e => e -> SomeException -- compilerExceptionToException = toException . SomeCompilerException -- -- compilerExceptionFromException :: Exception e => SomeException -> Maybe e -- compilerExceptionFromException x = do -- SomeCompilerException a <- fromException x -- cast a -- -- --------------------------------------------------------------------- -- -- Make a subhierarchy for exceptions in the frontend of the compiler -- -- data SomeFrontendException = forall e . Exception e => SomeFrontendException e -- -- instance Show SomeFrontendException where -- show (SomeFrontendException e) = show e -- -- instance Exception SomeFrontendException where -- toException = compilerExceptionToException -- fromException = compilerExceptionFromException -- -- frontendExceptionToException :: Exception e => e -> SomeException -- frontendExceptionToException = toException . SomeFrontendException -- -- frontendExceptionFromException :: Exception e => SomeException -> Maybe e -- frontendExceptionFromException x = do -- SomeFrontendException a <- fromException x -- cast a -- -- --------------------------------------------------------------------- -- -- Make an exception type for a particular frontend compiler exception -- -- data MismatchedParentheses = MismatchedParentheses -- deriving Show -- -- instance Exception MismatchedParentheses where -- toException = frontendExceptionToException -- fromException = frontendExceptionFromException ---- -- We can now catch a MismatchedParentheses exception as -- MismatchedParentheses, SomeFrontendException or -- SomeCompilerException, but not other types, e.g. -- IOException: -- --
-- *Main> throw MismatchedParentheses `catch` \e -> putStrLn ("Caught " ++ show (e :: MismatchedParentheses))
-- Caught MismatchedParentheses
-- *Main> throw MismatchedParentheses `catch` \e -> putStrLn ("Caught " ++ show (e :: SomeFrontendException))
-- Caught MismatchedParentheses
-- *Main> throw MismatchedParentheses `catch` \e -> putStrLn ("Caught " ++ show (e :: SomeCompilerException))
-- Caught MismatchedParentheses
-- *Main> throw MismatchedParentheses `catch` \e -> putStrLn ("Caught " ++ show (e :: IOException))
-- *** Exception: MismatchedParentheses
--
class (Typeable e, Show e) => Exception e
toException :: Exception e => e -> SomeException
fromException :: Exception e => SomeException -> Maybe e
-- | Render this exception value in a human-friendly manner.
--
-- Default implementation: show.
displayException :: Exception e => e -> String
-- | asProxyTypeOf is a type-restricted version of const. It
-- is usually used as an infix operator, and its typing forces its first
-- argument (which is usually overloaded) to have the same type as the
-- tag of the second.
--
-- -- >>> import Data.Word -- -- >>> :type asProxyTypeOf 123 (Proxy :: Proxy Word8) -- asProxyTypeOf 123 (Proxy :: Proxy Word8) :: Word8 ---- -- Note the lower-case proxy in the definition. This allows any -- type constructor with just one argument to be passed to the function, -- for example we could also write -- --
-- >>> import Data.Word -- -- >>> :type asProxyTypeOf 123 (Just (undefined :: Word8)) -- asProxyTypeOf 123 (Just (undefined :: Word8)) :: Word8 --asProxyTypeOf :: () => a -> proxy a -> a -- | Proxy is a type that holds no data, but has a phantom parameter -- of arbitrary type (or even kind). Its use is to provide type -- information, even though there is no value available of that type (or -- it may be too costly to create one). -- -- Historically, Proxy :: Proxy a is a safer -- alternative to the 'undefined :: a' idiom. -- --
-- >>> Proxy :: Proxy (Void, Int -> Int) -- Proxy ---- -- Proxy can even hold types of higher kinds, -- --
-- >>> Proxy :: Proxy Either -- Proxy ---- --
-- >>> Proxy :: Proxy Functor -- Proxy ---- --
-- >>> Proxy :: Proxy complicatedStructure -- Proxy --data Proxy (t :: k) :: forall k. () => k -> * Proxy :: Proxy -- | A concrete, promotable proxy type, for use at the kind level There are -- no instances for this because it is intended at the kind level only data KProxy t KProxy :: KProxy t -- | Type-level If. If True a b ==> a; If -- False a b ==> b -- | An MVar (pronounced "em-var") is a synchronising variable, used -- for communication between concurrent threads. It can be thought of as -- a a box, which may be empty or full. data MVar a -- | The SomeException type is the root of the exception type -- hierarchy. When an exception of type e is thrown, behind the -- scenes it is encapsulated in a SomeException. data SomeException [SomeException] :: SomeException -- | The parameterizable maybe monad, obtained by composing an arbitrary -- monad with the Maybe monad. -- -- Computations are actions that may produce a value or exit. -- -- The return function yields a computation that produces that -- value, while >>= sequences two subcomputations, exiting -- if either computation does. newtype MaybeT (m :: * -> *) a MaybeT :: m Maybe a -> MaybeT a [runMaybeT] :: MaybeT a -> m Maybe a -- | A monad transformer that adds exceptions to other monads. -- -- ExceptT constructs a monad parameterized over two things: -- --
unliftIO u . return = return
unliftIO u (m >>= f) = unliftIO u m >>= unliftIO -- u . f
askUnliftIO >>= (u -> liftIO (unliftIO u m)) = -- m
-- +RTS -T ---- -- or compile it with -- --
-- -with-rtsopts=-T ---- -- The runtime overhead of -T is very small so it's safe to -- always leave it enabled. -- -- Registered counters: -- --
-- instance FromEnv PGConfig where
-- fromEnv = gFromEnvCustom Option { dropPrefixCount = 8, customPrefix = "PG" }
--
gFromEnvCustom :: (DefConfig a, Generic a, GFromEnv Rep a) => Option -> Parser a
-- | Environment variable getter returning Maybe
envMaybe :: Var a => String -> Parser Maybe a
-- | Environment variable getter. Fails if the variable is not set or fails
-- to parse.
env :: Var a => String -> Parser a
-- | For use with Generics, no FromEnv typeclass necessary
--
-- -- getPgConfig :: IO (Either String ConnectInfo) -- getPgConfig = runEnv $ gFromEnvCustom defOption --runEnv :: () => Parser a -> IO Either String a -- | Parser Monad for environment variable retrieval newtype Parser a Parser :: ExceptT String IO a -> Parser a [runParser] :: Parser a -> ExceptT String IO a -- | FromEnv Typeclass w/ Generic default implementation class FromEnv a fromEnv :: FromEnv a => Parser a -- | Type class for objects which have a default configuration. class DefConfig a defConfig :: DefConfig a => a -- | For customizing environment variable generation data Option Option :: Int -> String -> Option -- | Applied first [dropPrefixCount] :: Option -> Int -- | Converted toUpper [customPrefix] :: Option -> String -- | Type class for objects which can be converted to a set of environment -- variable settings. class ToEnv a -- | Convert an object into a list of environment variable settings. toEnv :: ToEnv a => a -> EnvList a -- | List of environment variables. Captures a "phantom type" which allows -- the type checker to detect the proper implementation of toEnv to use. data EnvList a -- | Class for converting to / from an environment variable class Typeable a => Var a -- | Convert a value into an environment variable. toVar :: Var a => a -> String -- | Parse an environment variable. fromVar :: Var a => String -> Maybe a -- | fmap specialized to ExceptT, given a name symmetric to -- fmapLT fmapRT :: Monad m => a -> b -> ExceptT l m a -> ExceptT l m b -- | Analogous to isRight, but for ExceptT isRightT :: Monad m => ExceptT a m b -> m Bool -- | Analogous to isLeft, but for ExceptT isLeftT :: Monad m => ExceptT a m b -> m Bool -- | fmap specialized to Either, given a name symmetric to -- fmapL fmapR :: () => a -> b -> Either l a -> Either l b -- | Returns whether argument is a Right isRight :: () => Either a b -> Bool -- | Returns whether argument is a Left isLeft :: () => Either a b -> Bool -- | Analogous to isNothing, but for MaybeT isNothingT :: Monad m => MaybeT m a -> m Bool -- | Analogous to isJust, but for MaybeT isJustT :: Monad m => MaybeT m a -> m Bool -- | Analogous to Nothing and equivalent to mzero nothing :: Monad m => MaybeT m a -- | Analogous to Just and equivalent to return just :: Monad m => a -> MaybeT m a -- | Case analysis for MaybeT -- -- Use the first argument if the MaybeT computation fails, -- otherwise apply the function to the successful result. maybeT :: Monad m => m b -> a -> m b -> MaybeT m a -> m b -- | Convert an applicative Maybe value into the ExceptT -- monad -- -- Named version of (!?) with arguments flipped failWithM :: Applicative m => e -> m Maybe a -> ExceptT e m a -- | Convert a Maybe value into the ExceptT monad -- -- Named version of (??) with arguments flipped failWith :: Applicative m => e -> Maybe a -> ExceptT e m a -- | An infix form of fromMaybe with arguments flipped. (?:) :: () => Maybe a -> a -> a infixr 0 ?: -- | Convert an applicative Maybe value into the ExceptT -- monad (!?) :: Applicative m => m Maybe a -> e -> ExceptT e m a -- | Lift a Maybe to the MaybeT monad hoistMaybe :: Monad m => Maybe b -> MaybeT m b -- | Tag the Nothing value of a MaybeT noteT :: Monad m => a -> MaybeT m b -> ExceptT a m b -- | Tag the Nothing value of a Maybe note :: () => a -> Maybe b -> Either a b -- | Suppress the Left value of an ExceptT hushT :: Monad m => ExceptT a m b -> MaybeT m b -- | Suppress the Left value of an Either hush :: () => Either a b -> Maybe b -- | Upgrade an Either to an ExceptT hoistEither :: Monad m => Either e a -> ExceptT e m a -- | Transform the left and right value bimapExceptT :: Functor m => e -> f -> a -> b -> ExceptT e m a -> ExceptT f m b -- | Fold an ExceptT by providing one continuation for each -- constructor exceptT :: Monad m => a -> m c -> b -> m c -> ExceptT a m b -> m c -- | Run multiple Either computations and succeed if all of them -- succeed -- -- mappends all successes or failures newtype AllE e r AllE :: Either e r -> AllE e r [runAllE] :: AllE e r -> Either e r -- | Run multiple Either computations and succeed if any of them -- succeed -- -- mappends all successes or failures newtype AnyE e r AnyE :: Either e r -> AnyE e r [runAnyE] :: AnyE e r -> Either e r -- | Transform the computation inside a MaybeT. -- -- mapMaybeT :: () => m Maybe a -> n Maybe b -> MaybeT m a -> MaybeT n b -- | Lift a catchE operation to the new monad. liftCatch :: () => Catch e m Maybe a -> Catch e MaybeT m a -- | The inverse of ExceptT. runExceptT :: () => ExceptT e m a -> m Either e a -- | A class for monads which allow exceptions to be caught, in particular -- exceptions which were thrown by throwM. -- -- Instances should obey the following law: -- --
-- catch (throwM e) f = f e ---- -- Note that the ability to catch an exception does not guarantee -- that we can deal with all possible exit points from a computation. -- Some monads, such as continuation-based stacks, allow for more than -- just a success/failure strategy, and therefore catch -- cannot be used by those monads to properly implement a function -- such as finally. For more information, see MonadMask. class MonadThrow m => MonadCatch (m :: * -> *) -- | Logger Type. data LogType -- | No logging. LogNone :: LogType -- | Logging to stdout. BufSize is a buffer size for each -- capability. LogStdout :: BufSize -> LogType -- | Logging to stderr. BufSize is a buffer size for each -- capability. LogStderr :: BufSize -> LogType -- | Logging to a file. BufSize is a buffer size for each -- capability. LogFileNoRotate :: FilePath -> BufSize -> LogType -- | Logging to a file. BufSize is a buffer size for each -- capability. File rotation is done on-demand. LogFile :: FileLogSpec -> BufSize -> LogType -- | Logging with a log and flush action. run flush after log each message. LogCallback :: LogStr -> IO () -> IO () -> LogType -- | The default buffer size (4,096 bytes). defaultBufSize :: BufSize -- | Like encodePathSegments, but without the initial slash. encodePathSegmentsRelative :: [Text] -> Builder -- | Convert value to HTTP API data. -- -- WARNING: Do not derive this using DeriveAnyClass as -- the generated instance will loop indefinitely. class ToHttpApiData a -- | Convert to URL path piece. toUrlPiece :: ToHttpApiData a => a -> Text -- | Convert to a URL path piece, making sure to encode any special chars. -- The default definition uses encodePathSegmentsRelative, but -- this may be overriden with a more efficient version. toEncodedUrlPiece :: ToHttpApiData a => a -> Builder -- | Convert to HTTP header value. toHeader :: ToHttpApiData a => a -> ByteString -- | Convert to query param value. toQueryParam :: ToHttpApiData a => a -> Text -- | Parse value from HTTP API data. -- -- WARNING: Do not derive this using DeriveAnyClass as -- the generated instance will loop indefinitely. class FromHttpApiData a -- | Parse URL path piece. parseUrlPiece :: FromHttpApiData a => Text -> Either Text a -- | Parse HTTP header value. parseHeader :: FromHttpApiData a => ByteString -> Either Text a -- | Parse query param value. parseQueryParam :: FromHttpApiData a => Text -> Either Text a -- | Represents a general universal resource identifier using its component -- parts. -- -- For example, for the URI -- --
-- foo://anonymous@www.haskell.org:42/ghc?query#frag ---- -- the components are: data URI URI :: String -> Maybe URIAuth -> String -> String -> String -> URI -- |
-- foo: --[uriScheme] :: URI -> String -- |
-- //anonymous@www.haskell.org:42 --[uriAuthority] :: URI -> Maybe URIAuth -- |
-- /ghc --[uriPath] :: URI -> String -- |
-- ?query --[uriQuery] :: URI -> String -- |
-- #frag --[uriFragment] :: URI -> String -- | Use the default response timeout -- -- When used on a Request, means: use the manager's timeout value -- -- When used on a ManagerSettings, means: default to 30 seconds responseTimeoutDefault :: ResponseTimeout -- | Do not have a response timeout responseTimeoutNone :: ResponseTimeout -- | Specify a response timeout in microseconds responseTimeoutMicro :: Int -> ResponseTimeout -- | Set the proxy override value, for both HTTP (insecure) and HTTPS -- (insecure) connections. -- -- Since 0.4.7 managerSetProxy :: ProxyOverride -> ManagerSettings -> ManagerSettings -- | Set the proxy override value, only for HTTPS (secure) connections. -- -- Since 0.4.7 managerSetSecureProxy :: ProxyOverride -> ManagerSettings -> ManagerSettings -- | Set the proxy override value, only for HTTP (insecure) connections. -- -- Since 0.4.7 managerSetInsecureProxy :: ProxyOverride -> ManagerSettings -> ManagerSettings -- | A variant of withResponse which keeps a history of all -- redirects performed in the interim, together with the first 1024 bytes -- of their response bodies. -- -- Since 0.4.1 withResponseHistory :: () => Request -> Manager -> HistoriedResponse BodyReader -> IO a -> IO a -- | A variant of responseOpen which keeps a history of all -- redirects performed in the interim, together with the first 1024 bytes -- of their response bodies. -- -- Since 0.4.1 responseOpenHistory :: Request -> Manager -> IO HistoriedResponse BodyReader -- | A datatype holding information on redirected requests and the final -- response. -- -- Since 0.4.1 data HistoriedResponse body -- | Perform an action using a Connection acquired from the given -- Manager. -- -- You should use this only when you have to read and write interactively -- through the connection (e.g. connection by the WebSocket protocol). withConnection :: () => Request -> Manager -> Connection -> IO a -> IO a -- | Close any open resources associated with the given Response. -- In general, this will either close an active Connection or -- return it to the Manager to be reused. -- -- Since 0.1.0 responseClose :: () => Response a -> IO () -- | The most low-level function for initiating an HTTP request. -- -- The first argument to this function gives a full specification on the -- request: the host to connect to, whether to use SSL, headers, etc. -- Please see Request for full details. The second argument -- specifies which Manager should be used. -- -- This function then returns a Response with a BodyReader. -- The Response contains the status code and headers that were -- sent back to us, and the BodyReader contains the body of the -- request. Note that this BodyReader allows you to have fully -- interleaved IO actions during your HTTP download, making it possible -- to download very large responses in constant memory. -- -- An important note: the response body returned by this function -- represents a live HTTP connection. As such, if you do not use the -- response body, an open socket will be retained indefinitely. You must -- be certain to call responseClose on this response to free up -- resources. -- -- This function automatically performs any necessary redirects, as -- specified by the redirectCount setting. -- -- When implementing a (reverse) proxy using this function or relating -- functions, it's wise to remove Transfer-Encoding:, Content-Length:, -- Content-Encoding: and Accept-Encoding: from request and response -- headers to be relayed. -- -- Since 0.1.0 responseOpen :: Request -> Manager -> IO Response BodyReader -- | A convenient wrapper around withResponse which ignores the -- response body. This is useful, for example, when performing a HEAD -- request. -- -- Since 0.3.2 httpNoBody :: Request -> Manager -> IO Response () -- | A convenience wrapper around withResponse which reads in the -- entire response body and immediately closes the connection. Note that -- this function performs fully strict I/O, and only uses a lazy -- ByteString in its response for memory efficiency. If you are -- anticipating a large response body, you are encouraged to use -- withResponse and brRead instead. -- -- Since 0.1.0 httpLbs :: Request -> Manager -> IO Response ByteString -- | Perform a Request using a connection acquired from the given -- Manager, and then provide the Response to the given -- function. This function is fully exception safe, guaranteeing that the -- response will be closed when the inner function exits. It is defined -- as: -- --
-- withResponse req man f = bracket (responseOpen req man) responseClose f ---- -- It is recommended that you use this function in place of explicit -- calls to responseOpen and responseClose. -- -- You will need to use functions such as brRead to consume the -- response body. -- -- Since 0.1.0 withResponse :: () => Request -> Manager -> Response BodyReader -> IO a -> IO a -- | Turn a SetCookie into a Cookie, if it is valid generateCookie :: SetCookie -> Request -> UTCTime -> Bool -> Maybe Cookie -- | Insert a cookie created by generateCookie into the cookie jar (or not -- if it shouldn't be allowed in) insertCheckedCookie :: Cookie -> CookieJar -> Bool -> CookieJar -- | This corresponds to the algorithm described in Section 5.3 "Storage -- Model" This function consists of calling generateCookie -- followed by insertCheckedCookie. Use this function if you plan -- to do both in a row. generateCookie and -- insertCheckedCookie are only provided for more fine-grained -- control. receiveSetCookie :: SetCookie -> Request -> UTCTime -> Bool -> CookieJar -> CookieJar -- | This applies receiveSetCookie to a given Response updateCookieJar :: () => Response a -> Request -> UTCTime -> CookieJar -> (CookieJar, Response a) -- | This corresponds to the algorithm described in Section 5.4 "The Cookie -- Header" computeCookieString :: Request -> CookieJar -> UTCTime -> Bool -> (ByteString, CookieJar) -- | This applies the computeCookieString to a given Request insertCookiesIntoRequest :: Request -> CookieJar -> UTCTime -> (Request, CookieJar) -- | This corresponds to the eviction algorithm described in Section 5.3 -- "Storage Model" evictExpiredCookies :: CookieJar -> UTCTime -> CookieJar removeExistingCookieFromCookieJar :: Cookie -> CookieJar -> (Maybe Cookie, CookieJar) destroyCookieJar :: CookieJar -> [Cookie] createCookieJar :: [Cookie] -> CookieJar -- | This corresponds to the subcomponent algorithm entitled "Path-Match" -- detailed in section 5.1.4 pathMatches :: ByteString -> ByteString -> Bool -- | This corresponds to the subcomponent algorithm entitled "Paths" -- detailed in section 5.1.4 defaultPath :: Request -> ByteString -- | This corresponds to the subcomponent algorithm entitled "Domain -- Matching" detailed in section 5.1.3 domainMatches :: ByteString -> ByteString -> Bool isIpAddress :: ByteString -> Bool -- | The default proxy settings for a manager. In particular: if the -- http_proxy (or https_proxy) environment variable is -- set, use it. Otherwise, use the values in the Request. -- -- Since 0.4.7 defaultProxy :: ProxyOverride -- | Same as proxyEnvironment, but instead of default environment -- variable names, allows you to set your own name. -- -- Since 0.4.7 proxyEnvironmentNamed :: Text -> Maybe Proxy -> ProxyOverride -- | Get the proxy settings from the default environment variable -- (http_proxy for insecure, https_proxy for secure). -- If no variable is set, then fall back to the given value. -- Nothing is equivalent to noProxy, Just is -- equivalent to useProxy. -- -- Since 0.4.7 proxyEnvironment :: Maybe Proxy -> ProxyOverride -- | Use the given proxy settings, regardless of the proxy value in the -- Request. -- -- Since 0.4.7 useProxy :: Proxy -> ProxyOverride -- | Never connect using a proxy, regardless of the proxy value in the -- Request. -- -- Since 0.4.7 noProxy :: ProxyOverride -- | Get the proxy settings from the Request itself. -- -- Since 0.4.7 proxyFromRequest :: ProxyOverride -- | Create, use and close a Manager. -- -- Since 0.2.1 withManager :: () => ManagerSettings -> Manager -> IO a -> IO a -- | Close all connections in a Manager. -- -- Note that this doesn't affect currently in-flight connections, meaning -- you can safely use it without hurting any queries you may have -- concurrently running. -- -- Since 0.1.0 closeManager :: Manager -> IO () -- | Create a Manager. The Manager will be shut down -- automatically via garbage collection. -- -- Creating a new Manager is a relatively expensive operation, you -- are advised to share a single Manager between requests instead. -- -- The first argument to this function is often -- defaultManagerSettings, though add-on libraries may provide a -- recommended replacement. -- -- Since 0.1.0 newManager :: ManagerSettings -> IO Manager -- | Default value for ManagerSettings. -- -- Note that this value does not have support for SSL/TLS. If you -- need to make any https connections, please use the http-client-tls -- package, which provides a tlsManagerSettings value. -- -- Since 0.1.0 defaultManagerSettings :: ManagerSettings -- | Same as rawConnectionModifySocket, but also takes in a chunk -- size. rawConnectionModifySocketSize :: Socket -> IO () -> IO Int -> Maybe HostAddress -> String -> Int -> IO Connection -- | A value for the managerRawConnection setting, but also allows -- you to modify the underlying Socket to set additional -- settings. For a motivating use case, see: -- https://github.com/snoyberg/http-client/issues/71. -- -- Since 0.3.8 rawConnectionModifySocket :: Socket -> IO () -> IO Maybe HostAddress -> String -> Int -> IO Connection -- | Send a file as the request body, while observing streaming progress -- via a PopObserver. Observations are made between reading and -- sending a chunk. -- -- It is expected that the file size does not change between calling -- observedStreamFile and making any requests using this request -- body. -- -- Since 0.4.9 observedStreamFile :: StreamFileStatus -> IO () -> FilePath -> IO RequestBody -- | Send a file as the request body. -- -- It is expected that the file size does not change between calling -- streamFile and making any requests using this request body. -- -- Since 0.4.9 streamFile :: FilePath -> IO RequestBody -- | Set the query string to the given key/value pairs. setQueryStringPartialEscape :: [(ByteString, [EscapeItem])] -> Request -> Request -- | Set the query string to the given key/value pairs. -- -- Since 0.3.6 setQueryString :: [(ByteString, Maybe ByteString)] -> Request -> Request -- | Modify the request so that non-2XX status codes generate a runtime -- StatusCodeException, by using throwErrorStatusCodes setRequestCheckStatus :: Request -> Request -- | Modify the request so that non-2XX status codes do not generate a -- runtime StatusCodeException. setRequestIgnoreStatus :: Request -> Request -- | Add url-encoded parameters to the Request. -- -- This sets a new requestBody, adds a content-type request header -- and changes the method to POST. -- -- Since 0.1.0 urlEncodedBody :: [(ByteString, ByteString)] -> Request -> Request -- | Add a Proxy-Authorization header (with the specified username and -- password) to the given Request. Ignore error handling: -- --
-- applyBasicProxyAuth "user" "pass" <$> parseRequest "http://example.org" ---- -- Since 0.3.4 applyBasicProxyAuth :: ByteString -> ByteString -> Request -> Request -- | Add a Basic Auth header (with the specified user name and password) to -- the given Request. Ignore error handling: -- --
-- applyBasicAuth "user" "pass" $ parseRequest_ url ---- -- NOTE: The function applyDigestAuth is provided by the -- http-client-tls package instead of this package due to extra -- dependencies. Please use that package if you need to use digest -- authentication. -- -- Since 0.1.0 applyBasicAuth :: ByteString -> ByteString -> Request -> Request -- | A default request value, a GET request of localhost/:80, with an empty -- request body. -- -- Note that the default checkResponse does nothing. defaultRequest :: Request -- | Extract a URI from the request. -- -- Since 0.1.0 getUri :: Request -> URI -- | Same as requestFromURI, but if the conversion would fail, -- throws an impure exception. requestFromURI_ :: URI -> Request -- | Convert a URI into a Request. -- -- This can fail if the given URI is not absolute, or if the -- URI scheme is not "http" or "https". In these -- cases the function will throw an error via MonadThrow. -- -- This function defaults some of the values in Request, such as -- setting method to GET and requestHeaders -- to []. -- -- A Request created by this function won't cause exceptions on -- non-2XX response status codes. requestFromURI :: MonadThrow m => URI -> m Request -- | Same as parseRequest, but parse errors cause an impure -- exception. Mostly useful for static strings which are known to be -- correctly formatted. parseRequest_ :: String -> Request -- | Convert a URL into a Request. -- -- This function defaults some of the values in Request, such as -- setting method to GET and requestHeaders -- to []. -- -- Since this function uses MonadThrow, the return monad can be -- anything that is an instance of MonadThrow, such as IO -- or Maybe. -- -- You can place the request method at the beginning of the URL separated -- by a space, e.g.: -- -- @@ parseRequest "POST http://httpbin.org/post" @@ -- -- Note that the request method must be provided as all capital letters. -- -- A Request created by this function won't cause exceptions on -- non-2XX response status codes. -- -- To create a request which throws on non-2XX status codes, see -- parseUrlThrow parseRequest :: MonadThrow m => String -> m Request -- | Throws a StatusCodeException wrapped in -- HttpExceptionRequest, if the response's status code indicates -- an error (if it isn't 2xx). This can be used to implement -- checkResponse. throwErrorStatusCodes :: MonadIO m => Request -> Response BodyReader -> m () -- | Same as parseRequest, except will throw an HttpException -- in the event of a non-2XX response. This uses -- throwErrorStatusCodes to implement checkResponse. parseUrlThrow :: MonadThrow m => String -> m Request -- | Deprecated synonym for parseUrlThrow. You probably want -- parseRequest or parseRequest_ instead. parseUrl :: MonadThrow m => String -> m Request -- | Strictly consume all remaining chunks of data from the stream. -- -- Since 0.1.0 brConsume :: BodyReader -> IO [ByteString] -- | Continuously call brRead, building up a lazy ByteString until a -- chunk is constructed that is at least as many bytes as requested. -- -- Since 0.4.20 brReadSome :: BodyReader -> Int -> IO ByteString -- | Get a single chunk of data from the response body, or an empty -- bytestring if no more data is available. -- -- Note that in order to consume the entire request body, you will need -- to repeatedly call this function until you receive an empty -- ByteString as a result. -- -- Since 0.1.0 brRead :: BodyReader -> IO ByteString -- | Create a new Connection from a Socket. socketConnection :: Socket -> Int -> IO Connection -- | Create a new Connection from a read, write, and close function. makeConnection :: IO ByteString -> ByteString -> IO () -> IO () -> IO Connection -- | An IO action that represents an incoming response body coming -- from the server. Data provided by this action has already been -- gunzipped and de-chunked, and respects any content-length headers -- present. -- -- The action gets a single chunk of data from the response body, or an -- empty bytestring if no more data is available. -- -- Since 0.4.0 type BodyReader = IO ByteString -- | An exception which may be generated by this library data HttpException -- | Most exceptions are specific to a Request. Inspect the -- HttpExceptionContent value for details on what occurred. HttpExceptionRequest :: Request -> HttpExceptionContent -> HttpException -- | A URL (first field) is invalid for a given reason (second argument). InvalidUrlException :: String -> String -> HttpException data HttpExceptionContent -- | Generated by the parseUrlThrow function when the server -- returns a non-2XX response status code. -- -- May include the beginning of the response body. StatusCodeException :: Response () -> ByteString -> HttpExceptionContent -- | The server responded with too many redirects for a request. -- -- Contains the list of encountered responses containing redirects in -- reverse chronological order; including last redirect, which triggered -- the exception and was not followed. TooManyRedirects :: [Response ByteString] -> HttpExceptionContent -- | Either too many headers, or too many total bytes in a single header, -- were returned by the server, and the memory exhaustion protection in -- this library has kicked in. OverlongHeaders :: HttpExceptionContent -- | The server took too long to return a response. This can be altered via -- responseTimeout or managerResponseTimeout. ResponseTimeout :: HttpExceptionContent -- | Attempting to connect to the server timed out. ConnectionTimeout :: HttpExceptionContent -- | An exception occurred when trying to connect to the server. ConnectionFailure :: SomeException -> HttpExceptionContent -- | The status line returned by the server could not be parsed. InvalidStatusLine :: ByteString -> HttpExceptionContent -- | The given response header line could not be parsed InvalidHeader :: ByteString -> HttpExceptionContent -- | An exception was raised by an underlying library when performing the -- request. Most often, this is caused by a failing socket action or a -- TLS exception. InternalException :: SomeException -> HttpExceptionContent -- | A non-200 status code was returned when trying to connect to the proxy -- server on the given host and port. ProxyConnectException :: ByteString -> Int -> Status -> HttpExceptionContent -- | No response data was received from the server at all. This exception -- may deserve special handling within the library, since it may indicate -- that a pipelining has been used, and a connection thought to be open -- was in fact closed. NoResponseDataReceived :: HttpExceptionContent -- | Exception thrown when using a Manager which does not have -- support for secure connections. Typically, you will want to use -- tlsManagerSettings from http-client-tls to overcome -- this. TlsNotSupported :: HttpExceptionContent -- | The request body provided did not match the expected size. -- -- Provides the expected and actual size. WrongRequestBodyStreamSize :: Word64 -> Word64 -> HttpExceptionContent -- | The returned response body is too short. Provides the expected size -- and actual size. ResponseBodyTooShort :: Word64 -> Word64 -> HttpExceptionContent -- | A chunked response body had invalid headers. InvalidChunkHeaders :: HttpExceptionContent -- | An incomplete set of response headers were returned. IncompleteHeaders :: HttpExceptionContent -- | The host we tried to connect to is invalid (e.g., an empty string). InvalidDestinationHost :: ByteString -> HttpExceptionContent -- | An exception was thrown when inflating a response body. HttpZlibException :: ZlibException -> HttpExceptionContent -- | Values in the proxy environment variable were invalid. Provides the -- environment variable name and its value. InvalidProxyEnvironmentVariable :: Text -> Text -> HttpExceptionContent -- | Attempted to use a Connection which was already closed ConnectionClosed :: HttpExceptionContent -- | Proxy settings are not valid (Windows specific currently) @since 0.5.7 InvalidProxySettings :: Text -> HttpExceptionContent data Cookie Cookie :: ByteString -> ByteString -> UTCTime -> ByteString -> ByteString -> UTCTime -> UTCTime -> Bool -> Bool -> Bool -> Bool -> Cookie [cookie_name] :: Cookie -> ByteString [cookie_value] :: Cookie -> ByteString [cookie_expiry_time] :: Cookie -> UTCTime [cookie_domain] :: Cookie -> ByteString [cookie_path] :: Cookie -> ByteString [cookie_creation_time] :: Cookie -> UTCTime [cookie_last_access_time] :: Cookie -> UTCTime [cookie_persistent] :: Cookie -> Bool [cookie_host_only] :: Cookie -> Bool [cookie_secure_only] :: Cookie -> Bool [cookie_http_only] :: Cookie -> Bool data CookieJar -- | The host name of the HTTP proxy. proxyHost :: Proxy -> ByteString -- | The port number of the HTTP proxy. proxyPort :: Proxy -> Int -- | When using one of the RequestBodyStream / -- RequestBodyStreamChunked constructors, you must ensure that the -- GivesPopper can be called multiple times. Usually this is not a -- problem. -- -- The RequestBodyStreamChunked will send a chunked request body. -- Note that not all servers support this. Only use -- RequestBodyStreamChunked if you know the server you're sending -- to supports chunked request bodies. -- -- Since 0.1.0 data RequestBody RequestBodyLBS :: ByteString -> RequestBody RequestBodyBS :: ByteString -> RequestBody RequestBodyBuilder :: Int64 -> Builder -> RequestBody RequestBodyStream :: Int64 -> GivesPopper () -> RequestBody RequestBodyStreamChunked :: GivesPopper () -> RequestBody -- | Allows creation of a RequestBody inside the IO -- monad, which is useful for making easier APIs (like -- setRequestBodyFile). RequestBodyIO :: IO RequestBody -> RequestBody -- | A function which generates successive chunks of a request body, -- provider a single empty bytestring when no more data is available. -- -- Since 0.1.0 type Popper = IO ByteString -- | A function which must be provided with a Popper. -- -- Since 0.1.0 type NeedsPopper a = Popper -> IO a -- | A function which will provide a Popper to a NeedsPopper. -- This seemingly convoluted structure allows for creation of request -- bodies which allocate scarce resources in an exception safe manner. -- -- Since 0.1.0 type GivesPopper a = NeedsPopper a -> IO a -- | All information on how to connect to a host and what should be sent in -- the HTTP request. -- -- If you simply wish to download from a URL, see parseRequest. -- -- The constructor for this data type is not exposed. Instead, you should -- use either the defaultRequest value, or parseRequest -- to construct from a URL, and then use the records below to make -- modifications. This approach allows http-client to add configuration -- options without breaking backwards compatibility. -- -- For example, to construct a POST request, you could do something like: -- --
-- initReq <- parseRequest "http://www.example.com/path"
-- let req = initReq
-- { method = "POST"
-- }
--
--
-- For more information, please see
-- http://www.yesodweb.com/book/settings-types.
--
-- Since 0.1.0
data Request
-- | How to deal with timing out a response
data ResponseTimeout
-- | A simple representation of the HTTP response.
--
-- Since 0.1.0
data Response body
-- | Settings for a Manager. Please use the
-- defaultManagerSettings function and then modify individual
-- settings. For more information, see
-- http://www.yesodweb.com/book/settings-types.
--
-- Since 0.1.0
data ManagerSettings
-- | How the HTTP proxy server settings should be discovered.
--
-- Since 0.4.7
data ProxyOverride
-- | Keeps track of open connections for keep-alive.
--
-- If possible, you should share a single Manager between multiple
-- threads and requests.
--
-- Since 0.1.0
data Manager
class HasHttpManager a
getHttpManager :: HasHttpManager a => a -> Manager
-- | Status of streaming a request body from a file.
--
-- Since 0.4.9
data StreamFileStatus
StreamFileStatus :: Int64 -> Int64 -> Int -> StreamFileStatus
[fileSize] :: StreamFileStatus -> Int64
[readSoFar] :: StreamFileStatus -> Int64
[thisChunkSize] :: StreamFileStatus -> Int
-- | Query.
--
-- General form: a=b&c=d, but if the value is Nothing, it becomes
-- a&c=d.
type Query = [QueryItem]
writeLinkHeader :: [Link] -> Text
writeLink :: Link -> Text
-- | Parses a Link header, returns a Maybe.
parseLinkHeaderBS :: ByteString -> Maybe [Link]
-- | Parses a Link header, returns an Either, where Left is the Attoparsec
-- error string (probably not a useful one).
parseLinkHeaderBS' :: ByteString -> Either String [Link]
-- | Parses a Link header, returns a Maybe.
parseLinkHeader :: Text -> Maybe [Link]
-- | Parses a Link header, returns an Either, where Left is the Attoparsec
-- error string (probably not a useful one).
parseLinkHeader' :: Text -> Either String [Link]
-- | The Attoparsec parser for the Link header.
linkHeader :: Parser [Link]
lnk :: String -> [(LinkParam, Text)] -> Maybe Link
-- | Extracts the parameters from the link.
linkParams :: Link -> [(LinkParam, Text)]
-- | Extracts the URI from the link.
href :: Link -> URI
-- | The link attribute key.
data LinkParam
Rel :: LinkParam
Anchor :: LinkParam
Rev :: LinkParam
Hreflang :: LinkParam
Media :: LinkParam
Title :: LinkParam
Title' :: LinkParam
ContentType :: LinkParam
Other :: Text -> LinkParam
-- | HTTP 2.0
http20 :: HttpVersion
-- | HTTP 1.1
http11 :: HttpVersion
-- | HTTP 1.0
http10 :: HttpVersion
-- | HTTP 0.9
http09 :: HttpVersion
-- | HTTP Version.
--
-- Note that the Show instance is intended merely for debugging.
data HttpVersion
HttpVersion :: !Int -> !Int -> HttpVersion
[httpMajor] :: HttpVersion -> !Int
[httpMinor] :: HttpVersion -> !Int
-- | Types which can, and commonly are, converted to Query are in
-- this class.
--
-- You can use lists of simple key value pairs, with ByteString
-- (strict, or lazy: ByteString), Text, or String as
-- the key/value types. You can also have the value type lifted into a
-- Maybe to support keys without values; and finally it is possible to
-- put each pair into a Maybe for key-value pairs that aren't always
-- present.
class QueryLike a
-- | Convert to Query.
toQuery :: QueryLike a => a -> Query
-- | Convert PartialEscapeQuery to a Builder.
renderQueryBuilderPartialEscape :: Bool -> PartialEscapeQuery -> Builder
-- | Convert PartialEscapeQuery to ByteString.
renderQueryPartialEscape :: Bool -> PartialEscapeQuery -> ByteString
-- | Decode a whole path (path segments + query).
decodePath :: ByteString -> ([Text], Query)
-- | Encode a whole path (path segments + query).
encodePath :: [Text] -> Query -> Builder
-- | Extract whole path (path segments + query) from a RFC 2616
-- Request-URI.
--
-- -- >>> extractPath "/path" -- "/path" ---- --
-- >>> extractPath "http://example.com:8080/path" -- "/path" ---- --
-- >>> extractPath "http://example.com" -- "/" ---- --
-- >>> extractPath "" -- "/" --extractPath :: ByteString -> ByteString -- | Parse a list of path segments from a valid URL fragment. decodePathSegments :: ByteString -> [Text] -- | Encodes a list of path segments into a valid URL fragment. -- -- This function takes the following three steps: -- --
-- encodePathSegments [\"foo\", \"bar\", \"baz\"] ---- -- "/foo/bar/baz" -- --
-- encodePathSegments [\"foo bar\", \"baz\/bin\"] ---- -- "/foo%20bar/baz%2Fbin" -- --
-- encodePathSegments [\"שלום\"] ---- -- "/%D7%A9%D7%9C%D7%95%D7%9D" -- -- Huge thanks to Jeremy Shaw who created the original implementation of -- this function in web-routes and did such thorough research to -- determine all correct escaping procedures. encodePathSegments :: [Text] -> Builder -- | Percent-decoding. urlDecode :: Bool -> ByteString -> ByteString -- | Percent-encoding for URLs. urlEncode :: Bool -> ByteString -> ByteString -- | Percent-encoding for URLs (using Builder). urlEncodeBuilder :: Bool -> ByteString -> Builder -- | Parse SimpleQuery from a ByteString. parseSimpleQuery :: ByteString -> SimpleQuery -- | Split out the query string into a list of keys and values. A few -- importants points: -- --
-- >>> parseByteRanges "error" -- Nothing -- -- >>> parseByteRanges "bytes=0-499" -- Just [ByteRangeFromTo 0 499] -- -- >>> parseByteRanges "bytes=500-999" -- Just [ByteRangeFromTo 500 999] -- -- >>> parseByteRanges "bytes=-500" -- Just [ByteRangeSuffix 500] -- -- >>> parseByteRanges "bytes=9500-" -- Just [ByteRangeFrom 9500] -- -- >>> parseByteRanges "bytes=0-0,-1" -- Just [ByteRangeFromTo 0 0,ByteRangeSuffix 1] -- -- >>> parseByteRanges "bytes=500-600,601-999" -- Just [ByteRangeFromTo 500 600,ByteRangeFromTo 601 999] -- -- >>> parseByteRanges "bytes=500-700,601-999" -- Just [ByteRangeFromTo 500 700,ByteRangeFromTo 601 999] --parseByteRanges :: ByteString -> Maybe ByteRanges renderByteRanges :: ByteRanges -> ByteString renderByteRangesBuilder :: ByteRanges -> Builder renderByteRange :: ByteRange -> ByteString renderByteRangeBuilder :: ByteRange -> Builder -- | HTTP Header names according to -- https://tools.ietf.org/html/rfc6265#section-4 hCookie :: HeaderName -- | HTTP Header names according to -- http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html hUserAgent :: HeaderName -- | HTTP Header names according to -- http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html hServer :: HeaderName -- | HTTP Header names according to -- http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html hReferer :: HeaderName -- | HTTP Header names according to -- http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html hRange :: HeaderName -- | HTTP Header names according to -- http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html hLocation :: HeaderName -- | HTTP Header names according to -- http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html hLastModified :: HeaderName -- | HTTP Header names according to -- http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html hIfRange :: HeaderName -- | HTTP Header names according to -- http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html hIfModifiedSince :: HeaderName -- | HTTP Header names according to -- http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html hDate :: HeaderName -- | HTTP Header names according to -- http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html hContentType :: HeaderName -- | HTTP Header names according to -- http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html hContentMD5 :: HeaderName -- | HTTP Header names according to -- http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html hContentLength :: HeaderName -- | HTTP Header names according to -- http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html hContentEncoding :: HeaderName -- | HTTP Header names according to -- http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html hConnection :: HeaderName -- | HTTP Header names according to -- http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html hCacheControl :: HeaderName -- | HTTP Header names according to -- http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html hAuthorization :: HeaderName -- | HTTP Header names according to -- http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html hAcceptLanguage :: HeaderName -- | HTTP Header names according to -- http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html hAccept :: HeaderName -- | Header name type HeaderName = CI ByteString -- | Request Headers type RequestHeaders = [Header] -- | Response Headers type ResponseHeaders = [Header] -- | RFC 2616 Byte range (individual). -- -- Negative indices are not allowed! data ByteRange ByteRangeFrom :: !Integer -> ByteRange ByteRangeFromTo :: !Integer -> !Integer -> ByteRange ByteRangeSuffix :: !Integer -> ByteRange -- | RFC 2616 Byte ranges (set). type ByteRanges = [ByteRange] -- | Set the Label to the Shown value of whatever you pass -- in. -- --
-- timedList Seconds ["request.byUser." <> userName, "request.byType." <> requestType] $ do -- ... ---- -- So you will have "request.byUser.someuser" storing duration -- distribution for requests of user "someuser" of any type; and -- "request.byType.sometype" storing duration distribution for -- requests of type "sometype" from any user. timedList :: (MonadIO m, MonadMetrics m, MonadMask m) => Resolution -> [Text] -> m a -> m a -- | Record the time taken to perform the named action. The number is -- stored in a Distribution and is converted to the specified -- Resolution. -- --
-- "http://example.com/Root/sub1/name2#frag" -- `relativeFrom` "http://example.com/Root/sub2/name2#frag" -- == "../sub1/name2#frag" ---- -- There is no single correct implementation of this function, but any -- acceptable implementation must satisfy the following: -- --
-- (uabs `relativeFrom` ubase) `relativeTo` ubase == uabs ---- -- For any valid absolute URI. (cf. -- http://lists.w3.org/Archives/Public/uri/2003Jan/0008.html -- http://lists.w3.org/Archives/Public/uri/2003Jan/0005.html) relativeFrom :: URI -> URI -> URI -- | Returns the segments of the path component. E.g., pathSegments -- $ parseURI "http://example.org/foo/bar/baz" == ["foo", -- "bar", "baz"] pathSegments :: URI -> [String] -- | Returns a new URI which represents the value of the first -- URI interpreted as relative to the second URI. -- -- Algorithm from RFC3986 [3], section 5.2 relativeTo :: URI -> URI -> URI -- | Returns a new URI which represents the value of the first -- URI interpreted as relative to the second URI. For -- example: -- --
-- "foo" `relativeTo` "http://bar.org/" = "http://bar.org/foo" -- "http:foo" `nonStrictRelativeTo` "http://bar.org/" = "http://bar.org/foo" ---- -- Algorithm from RFC3986 [3], section 5.2.2 nonStrictRelativeTo :: URI -> URI -> URI -- | Turns all instances of escaped characters in the string back into -- literal characters. unEscapeString :: String -> String -- | Can be used to make a string valid for use in a URI. escapeURIString :: Char -> Bool -> String -> String -- | Escape character if supplied predicate is not satisfied, otherwise -- return character as singleton string. escapeURIChar :: Char -> Bool -> Char -> String -- | Returns True if the character is allowed unescaped in a URI -- component. -- --
-- >>> escapeURIString isUnescapedInURIComponent "http://haskell.org:80?some_param=true&other_param=їґ" -- "http%3A%2F%2Fhaskell.org%3A80%3Fsome_param%3Dtrue%26other_param%3D%D1%97%D2%91" --isUnescapedInURIComponent :: Char -> Bool -- | Returns True if the character is allowed unescaped in a URI. -- --
-- >>> escapeURIString isUnescapedInURI "http://haskell.org:80?some_param=true&other_param=їґ" -- "http://haskell.org:80?some_param=true&other_param=%D1%97%D2%91" --isUnescapedInURI :: Char -> Bool -- | Returns True if the character is allowed in a URI. isAllowedInURI :: Char -> Bool -- | Turn a URI into a string. -- -- Uses a supplied function to map the userinfo part of the URI. -- -- The Show instance for URI uses a mapping that hides any password that -- may be present in the URI. Use this function with argument id -- to preserve the password in the formatted output. uriToString :: String -> String -> URI -> ShowS -- | Returns True if the character is an "unreserved" character in a -- URI. These characters do not need to be escaped in a URI. The only -- characters allowed in a URI are either "reserved", "unreserved", or an -- escape sequence (% followed by two hex digits). isUnreserved :: Char -> Bool -- | Returns True if the character is a "reserved" character in a -- URI. To include a literal instance of one of these characters in a -- component of a URI, it must be escaped. isReserved :: Char -> Bool uriIsRelative :: URI -> Bool uriIsAbsolute :: URI -> Bool -- | Test if string contains a valid IPv4 address isIPv4address :: String -> Bool -- | Test if string contains a valid IPv6 address isIPv6address :: String -> Bool -- | Test if string contains a valid absolute URI (an absolute URI without -- a fragment identifier). isAbsoluteURI :: String -> Bool -- | Test if string contains a valid relative URI (a relative URI with -- optional fragment identifier). isRelativeReference :: String -> Bool -- | Test if string contains a valid URI reference (an absolute or relative -- URI with optional fragment identifier). isURIReference :: String -> Bool -- | Test if string contains a valid URI (an absolute URI with optional -- fragment identifier). isURI :: String -> Bool -- | Parse an absolute URI to a URI value. Returns Nothing if -- the string is not a valid absolute URI. (an absolute URI without a -- fragment identifier). parseAbsoluteURI :: String -> Maybe URI -- | Parse a relative URI to a URI value. Returns Nothing if -- the string is not a valid relative URI. (a relative URI with optional -- fragment identifier). parseRelativeReference :: String -> Maybe URI -- | Parse a URI reference to a URI value. Returns Nothing if -- the string is not a valid URI reference. (an absolute or relative URI -- with optional fragment identifier). parseURIReference :: String -> Maybe URI -- | Turn a string containing a URI into a URI. Returns -- Nothing if the string is not a valid URI; (an absolute URI with -- optional fragment identifier). -- -- NOTE: this is different from the previous network.URI, whose -- parseURI function works like parseURIReference in this -- module. parseURI :: String -> Maybe URI -- | Blank URI nullURI :: URI -- | Type for authority value within a URI data URIAuth URIAuth :: String -> String -> String -> URIAuth -- |
-- anonymous@ --[uriUserInfo] :: URIAuth -> String -- |
-- www.haskell.org --[uriRegName] :: URIAuth -> String -- |
-- :42 --[uriPort] :: URIAuth -> String -- | A variant of r that interprets the "|~]" sequence as -- "|]", "|~~]" as "|~]" and, in general, -- "|~^n]" as "|~^(n-1)]" for n >= 1. -- -- Usage: -- --
-- ghci> [rQ||~]|~]|] -- "|]|]" -- ghci> [rQ||~~]|] -- "|~]" -- ghci> [rQ||~~~~]|] -- "|~~~]" --rQ :: QuasiQuoter -- | A quasiquoter for raw string literals - that is, string literals that -- don't recognise the standard escape sequences (such as '\n'). -- Basically, they make your code more readable by freeing you from the -- responsibility to escape backslashes. They are useful when working -- with regular expressions, DOS/Windows paths and markup languages (such -- as XML). -- -- Don't forget the LANGUAGE QuasiQuotes pragma if you're using -- this module in your code. -- -- Usage: -- --
-- ghci> :set -XQuasiQuotes
-- ghci> import Text.RawString.QQ
-- ghci> let s = [r|\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,3}|]
-- ghci> s
-- "\\w+@[a-zA-Z_]+?\\.[a-zA-Z]{2,3}"
-- ghci> [r|C:\Windows\SYSTEM|] ++ [r|\user32.dll|]
-- "C:\\Windows\\SYSTEM\\user32.dll"
--
--
-- Multiline raw string literals are also supported:
--
-- -- multiline :: String -- multiline = [r|<HTML> -- <HEAD> -- <TITLE>Auto-generated html formated source</TITLE> -- <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252"> -- </HEAD> -- <BODY LINK="800080" BGCOLOR="#ffffff"> -- <P> </P> -- <PRE>|] ---- -- Caveat: since the "|]" character sequence is used to -- terminate the quasiquotation, you can't use it inside the raw string -- literal. Use rQ if you want to embed that character sequence -- inside the raw string. -- -- For more on raw strings, see e.g. -- http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2053.html -- -- For more on quasiquotation, see -- http://www.haskell.org/haskellwiki/Quasiquotation r :: QuasiQuoter -- | A handler for a RefineException. -- -- throwRefineOtherException is useful for defining what behaviour -- validate should have in the event of a predicate failure. throwRefineOtherException :: Monad m => TypeRep -> Doc Void -> RefineT m a -- | A handler function to handle previous RefineExceptions -- and return to normal execution. A common idiom is: -- --
-- do { action1; action2; action3 } `catchRefine' handler
--
--
-- where the action functions can call throwRefine. Note
-- that handler and the do-block must have the same return type.
catchRefine :: Monad m => RefineT m a -> RefineException -> RefineT m a -> RefineT m a
-- | One can use throwRefine inside of a monadic context to
-- begin processing a RefineException.
throwRefine :: Monad m => RefineException -> RefineT m a
-- | Run a monadic action of type RefineM a, yielding an
-- Either RefineException a.
--
-- This is just defined as runIdentity .
-- runRefineT.
runRefineM :: () => RefineM a -> Either RefineException a
-- | Constructs a computation in the RefineM monad. (The inverse of
-- runRefineM).
refineM :: () => Either RefineException a -> RefineM a
-- | Map the unwrapped computation using the given function.
--
-- -- runRefineT (mapRefineT f m) = f (runRefineT m) --mapRefineT :: () => m Either RefineException a -> n Either RefineException b -> RefineT m a -> RefineT n b -- | The inverse of RefineT. runRefineT :: () => RefineT m a -> m Either RefineException a -- | Display a RefineException as a Doc ann displayRefineException :: () => RefineException -> Doc ann -- | This function helps type inference. It is equivalent to the following: -- --
-- instance Weaken r (Or l r) --rightOr :: () => Refined r x -> Refined Or l r x -- | This function helps type inference. It is equivalent to the following: -- --
-- instance Weaken l (Or l r) --leftOr :: () => Refined l x -> Refined Or l r x -- | This function helps type inference. It is equivalent to the following: -- --
-- instance Weaken (And l r) r --andRight :: () => Refined And l r x -> Refined r x -- | This function helps type inference. It is equivalent to the following: -- --
-- instance Weaken (And l r) l --andLeft :: () => Refined And l r x -> Refined l x -- | Extracts the refined value. unrefine :: () => Refined p x -> x -- | Constructs a Refined value at compile-time using -- -XTemplateHaskell. -- -- For example: -- --
-- >>> $$(refineTH 23) :: Refined Positive Int -- Refined 23 ---- -- Here's an example of an invalid value: -- --
-- >>> $$(refineTH 0) :: Refined Positive Int -- <interactive>:6:4: -- Value is not greater than 0 -- In the Template Haskell splice $$(refineTH 0) -- In the expression: $$(refineTH 0) :: Refined Positive Int -- In an equation for ‘it’: -- it = $$(refineTH 0) :: Refined Positive Int ---- -- If it's not evident, the example above indicates a compile-time -- failure, which means that the checking was done at compile-time, thus -- introducing a zero runtime overhead compared to a plain value -- construction. refineTH :: (Predicate p x, Lift x) => x -> Q TExp Refined p x -- | Constructs a Refined value at run-time, calling error if -- the value does not satisfy the predicate. -- -- WARNING: this function is not total! unsafeRefine :: Predicate p x => x -> Refined p x -- | Constructs a Refined value at run-time, calling -- throwError if the value does not satisfy the predicate. refineError :: (Predicate p x, MonadError RefineException m) => x -> m Refined p x -- | Constructs a Refined value at run-time, calling fail if -- the value does not satisfy the predicate. refineFail :: (Predicate p x, MonadFail m) => x -> m Refined p x -- | Constructs a Refined value at run-time, calling throwM -- if the value does not satisfy the predicate. refineThrow :: (Predicate p x, MonadThrow m) => x -> m Refined p x -- | A smart constructor of a Refined value. Checks the input value -- at runtime. refine :: Predicate p x => x -> Either RefineException Refined p x -- | A refinement type, which wraps a value of type x, ensuring -- that it satisfies a type-level predicate p. -- -- The only ways that this library provides to construct a value of type -- Refined are with the 'refine-' family of functions, because the -- use of the newtype constructor gets around the checking of the -- predicate. This restriction on the user makes unrefine safe. -- -- If you would really like to construct a Refined value -- without checking the predicate, use unsafeCoerce. data Refined p x -- | A typeclass which defines a runtime interpretation of a type-level -- predicate p for type x. class Typeable p => Predicate p x -- | Check the value x according to the predicate p, -- producing an error string if the value does not satisfy. validate :: (Predicate p x, Monad m) => p -> x -> RefineT m () -- | The negation of a predicate. data Not p -- | The conjunction of two predicates. data And l r -- | The conjunction of two predicates. type && = And -- | The disjunction of two predicates. data Or l r -- | The disjunction of two predicates. type || = Or -- | A Predicate ensuring that the Foldable has a length -- which is less than the specified type-level number. data SizeLessThan (n :: Nat) -- | A Predicate ensuring that the Foldable has a length -- which is greater than the specified type-level number. data SizeGreaterThan (n :: Nat) -- | A Predicate ensuring that the Foldable has a length -- which is equal to the specified type-level number. data SizeEqualTo (n :: Nat) -- | A Predicate ensuring that the IsList contains elements -- in a strictly ascending order. data Ascending -- | A Predicate ensuring that the IsList contains elements -- in a strictly descending order. data Descending -- | A Predicate ensuring that the value is less than the specified -- type-level number. data LessThan (n :: Nat) -- | A Predicate ensuring that the value is greater than the -- specified type-level number. data GreaterThan (n :: Nat) -- | A Predicate ensuring that the value is greater than or equal to -- the specified type-level number. data From (n :: Nat) -- | A Predicate ensuring that the value is less than or equal to -- the specified type-level number. data To (n :: Nat) -- | A Predicate ensuring that the value is within an inclusive -- range. data FromTo (mn :: Nat) (mx :: Nat) -- | A Predicate ensuring that the value is equal to the specified -- type-level number n. data EqualTo (n :: Nat) -- | A Predicate ensuring that the value is not equal to the -- specified type-level number n. data NotEqualTo (n :: Nat) -- | A Predicate ensuring that the value is greater than zero. type Positive = GreaterThan 0 -- | A Predicate ensuring that the value is less than or equal to -- zero. type NonPositive = To 0 -- | A Predicate ensuring that the value is less than zero. type Negative = LessThan 0 -- | A Predicate ensuring that the value is greater than or equal to -- zero. type NonNegative = From 0 -- | An inclusive range of values from zero to one. type ZeroToOne = FromTo 0 1 -- | A Predicate ensuring that the value is not equal to zero. type NonZero = NotEqualTo 0 -- | A Predicate ensuring that the Foldable is non-empty. type NonEmpty = SizeGreaterThan 0 -- | A typeclass containing "safe" conversions between refined predicates -- where the target is weaker than the source: that is, all values -- that satisfy the first predicate will be guarunteed to satisy the -- second. -- -- Take care: writing an instance declaration for your custom predicates -- is the same as an assertion that weaken is safe to use: -- --
-- instance Weaken Pred1 Pred2 ---- -- For most of the instances, explicit type annotations for the result -- value's type might be required. class Weaken from to weaken :: Weaken from to => Refined from x -> Refined to x -- | An exception encoding the way in which a Predicate failed. data RefineException -- | A RefineException for failures involving the Not -- predicate. RefineNotException :: !TypeRep -> RefineException -- | A RefineException for failures involving the And -- predicate. RefineAndException :: !TypeRep -> !These RefineException RefineException -> RefineException -- | A RefineException for failures involving the Or -- predicate. RefineOrException :: !TypeRep -> !RefineException -> !RefineException -> RefineException -- | A RefineException for failures involving all other predicates. RefineOtherException :: !TypeRep -> !Doc Void -> RefineException -- | A monad transformer that adds RefineExceptions to -- other monads. -- -- The pure and return functions yield -- computations that produce the given value, while -- >>= sequences two subcomputations, exiting on -- the first RefineException. data RefineT (m :: * -> *) a -- | RefineM a is equivalent to RefineT -- Identity a for any type a. type RefineM a = RefineT Identity a -- | Lifted newChan. newChan :: MonadIO m => m Chan a -- | Lifted writeChan. writeChan :: MonadIO m => Chan a -> a -> m () -- | Lifted readChan. readChan :: MonadIO m => Chan a -> m a -- | Lifted dupChan. dupChan :: MonadIO m => Chan a -> m Chan a -- | Lifted getChanContents. getChanContents :: MonadIO m => Chan a -> m [a] -- | Lifted writeList2Chan. writeList2Chan :: MonadIO m => Chan a -> [a] -> m () -- | Exception type thrown by throwString. -- -- Note that the second field of the data constructor depends on GHC/base -- version. For base 4.9 and GHC 8.0 and later, the second field is a -- call stack. Previous versions of GHC and base do not support call -- stacks, and the field is simply unit (provided to make pattern -- matching across GHC versions easier). data StringException StringException :: String -> CallStack -> StringException -- | Wrap up a synchronous exception to be treated as an asynchronous -- exception. -- -- This is intended to be created via toAsyncException. data AsyncExceptionWrapper [AsyncExceptionWrapper] :: AsyncExceptionWrapper -- | Wrap up an asynchronous exception to be treated as a synchronous -- exception. -- -- This is intended to be created via toSyncException. data SyncExceptionWrapper [SyncExceptionWrapper] :: SyncExceptionWrapper -- | Unlifted catch, but will not catch asynchronous exceptions. catch :: (MonadUnliftIO m, Exception e) => m a -> e -> m a -> m a -- | catch specialized to only catching IOExceptions. catchIO :: MonadUnliftIO m => m a -> IOException -> m a -> m a -- | catch specialized to catch all synchronous exception. catchAny :: MonadUnliftIO m => m a -> SomeException -> m a -> m a -- | Same as catch, but fully force evaluation of the result value -- to find all impure exceptions. catchDeep :: (MonadUnliftIO m, Exception e, NFData a) => m a -> e -> m a -> m a -- | catchDeep specialized to catch all synchronous exception. catchAnyDeep :: (NFData a, MonadUnliftIO m) => m a -> SomeException -> m a -> m a -- | catchJust is like catch but it takes an extra argument -- which is an exception predicate, a function which selects which type -- of exceptions we're interested in. catchJust :: (MonadUnliftIO m, Exception e) => e -> Maybe b -> m a -> b -> m a -> m a -- | Flipped version of catch. handle :: (MonadUnliftIO m, Exception e) => e -> m a -> m a -> m a -- | handle specialized to only catching IOExceptions. handleIO :: MonadUnliftIO m => IOException -> m a -> m a -> m a -- | Flipped version of catchAny. handleAny :: MonadUnliftIO m => SomeException -> m a -> m a -> m a -- | Flipped version of catchDeep. handleDeep :: (MonadUnliftIO m, Exception e, NFData a) => e -> m a -> m a -> m a -- | Flipped version of catchAnyDeep. handleAnyDeep :: (MonadUnliftIO m, NFData a) => SomeException -> m a -> m a -> m a -- | Flipped catchJust. handleJust :: (MonadUnliftIO m, Exception e) => e -> Maybe b -> b -> m a -> m a -> m a -- | Unlifted try, but will not catch asynchronous exceptions. try :: (MonadUnliftIO m, Exception e) => m a -> m Either e a -- | try specialized to only catching IOExceptions. tryIO :: MonadUnliftIO m => m a -> m Either IOException a -- | try specialized to catch all synchronous exceptions. tryAny :: MonadUnliftIO m => m a -> m Either SomeException a -- | Same as try, but fully force evaluation of the result value to -- find all impure exceptions. tryDeep :: (MonadUnliftIO m, Exception e, NFData a) => m a -> m Either e a -- | tryDeep specialized to catch all synchronous exceptions. tryAnyDeep :: (MonadUnliftIO m, NFData a) => m a -> m Either SomeException a -- | A variant of try that takes an exception predicate to select -- which exceptions are caught. tryJust :: (MonadUnliftIO m, Exception e) => e -> Maybe b -> m a -> m Either b a -- | Evaluate the value to WHNF and catch any synchronous exceptions. -- -- The expression may still have bottom values within it; you may instead -- want to use pureTryDeep. pureTry :: () => a -> Either SomeException a -- | Evaluate the value to NF and catch any synchronous exceptions. pureTryDeep :: NFData a => a -> Either SomeException a -- | Same as upstream catches, but will not catch asynchronous -- exceptions. catches :: MonadUnliftIO m => m a -> [Handler m a] -> m a -- | Same as catches, but fully force evaluation of the result value -- to find all impure exceptions. catchesDeep :: (MonadUnliftIO m, NFData a) => m a -> [Handler m a] -> m a -- | Lifted version of evaluate. evaluate :: MonadIO m => a -> m a -- | Deeply evaluate a value using evaluate and NFData. evaluateDeep :: (MonadIO m, NFData a) => a -> m a -- | Async safe version of bracket. bracket :: MonadUnliftIO m => m a -> a -> m b -> a -> m c -> m c -- | Async safe version of bracket_. bracket_ :: MonadUnliftIO m => m a -> m b -> m c -> m c -- | Async safe version of bracketOnError. bracketOnError :: MonadUnliftIO m => m a -> a -> m b -> a -> m c -> m c -- | A variant of bracketOnError where the return value from the -- first computation is not required. bracketOnError_ :: MonadUnliftIO m => m a -> m b -> m c -> m c -- | Async safe version of finally. finally :: MonadUnliftIO m => m a -> m b -> m a -- | Like onException, but provides the handler the thrown -- exception. withException :: (MonadUnliftIO m, Exception e) => m a -> e -> m b -> m a -- | Async safe version of onException. onException :: MonadUnliftIO m => m a -> m b -> m a -- | Synchronously throw the given exception. throwIO :: (MonadIO m, Exception e) => e -> m a -- | Convert an exception into a synchronous exception. -- -- For synchronous exceptions, this is the same as toException. -- For asynchronous exceptions, this will wrap up the exception with -- SyncExceptionWrapper. toSyncException :: Exception e => e -> SomeException -- | Convert an exception into an asynchronous exception. -- -- For asynchronous exceptions, this is the same as toException. -- For synchronous exceptions, this will wrap up the exception with -- AsyncExceptionWrapper. toAsyncException :: Exception e => e -> SomeException -- | Check if the given exception is synchronous. isSyncException :: Exception e => e -> Bool -- | Check if the given exception is asynchronous. isAsyncException :: Exception e => e -> Bool -- | Unlifted version of mask. mask :: MonadUnliftIO m => forall a. () => m a -> m a -> m b -> m b -- | Unlifted version of uninterruptibleMask. uninterruptibleMask :: MonadUnliftIO m => forall a. () => m a -> m a -> m b -> m b -- | Unlifted version of mask_. mask_ :: MonadUnliftIO m => m a -> m a -- | Unlifted version of uninterruptibleMask_. uninterruptibleMask_ :: MonadUnliftIO m => m a -> m a -- | A convenience function for throwing a user error. This is useful for -- cases where it would be too high a burden to define your own exception -- type. -- -- This throws an exception of type StringException. When GHC -- supports it (base 4.9 and GHC 8.0 and onward), it includes a call -- stack. throwString :: (MonadIO m, HasCallStack) => String -> m a -- | Smart constructor for a StringException that deals with the -- call stack. stringException :: HasCallStack -> String -> StringException -- | Throw an asynchronous exception to another thread. -- -- Synchronously typed exceptions will be wrapped into an -- AsyncExceptionWrapper, see -- https://github.com/fpco/safe-exceptions#determining-sync-vs-async. -- -- It's usually a better idea to use the UnliftIO.Async module, -- see https://github.com/fpco/safe-exceptions#quickstart. throwTo :: (Exception e, MonadIO m) => ThreadId -> e -> m () -- | Generate a pure value which, when forced, will synchronously throw the -- given exception. -- -- Generally it's better to avoid using this function and instead use -- throwIO, see -- https://github.com/fpco/safe-exceptions#quickstart. impureThrow :: Exception e => e -> a -- | Unwrap an Either value, throwing its Left value as a -- runtime exception via throwIO if present. fromEither :: (Exception e, MonadIO m) => Either e a -> m a -- | Same as fromEither, but works on an IO-wrapped -- Either. fromEitherIO :: (Exception e, MonadIO m) => IO Either e a -> m a -- | Same as fromEither, but works on an m-wrapped -- Either. fromEitherM :: (Exception e, MonadIO m) => m Either e a -> m a -- | Lifted newEmptyMVar. newEmptyMVar :: MonadIO m => m MVar a -- | Lifted newMVar. newMVar :: MonadIO m => a -> m MVar a -- | Lifted takeMVar. takeMVar :: MonadIO m => MVar a -> m a -- | Lifted putMVar. putMVar :: MonadIO m => MVar a -> a -> m () -- | Lifted readMVar. readMVar :: MonadIO m => MVar a -> m a -- | Lifted swapMVar. swapMVar :: MonadIO m => MVar a -> a -> m a -- | Lifted tryTakeMVar. tryTakeMVar :: MonadIO m => MVar a -> m Maybe a -- | Lifted tryPutMVar. tryPutMVar :: MonadIO m => MVar a -> a -> m Bool -- | Lifted isEmptyMVar. isEmptyMVar :: MonadIO m => MVar a -> m Bool -- | Lifted tryReadMVar. tryReadMVar :: MonadIO m => MVar a -> m Maybe a -- | Unlifted withMVar. withMVar :: MonadUnliftIO m => MVar a -> a -> m b -> m b -- | Unlifted withMVarMasked. withMVarMasked :: MonadUnliftIO m => MVar a -> a -> m b -> m b -- | Unlifted modifyMVar_. modifyMVar_ :: MonadUnliftIO m => MVar a -> a -> m a -> m () -- | Unlifted modifyMVar. modifyMVar :: MonadUnliftIO m => MVar a -> a -> m (a, b) -> m b -- | Unlifted modifyMVarMasked_. modifyMVarMasked_ :: MonadUnliftIO m => MVar a -> a -> m a -> m () -- | Unlifted modifyMVarMasked. modifyMVarMasked :: MonadUnliftIO m => MVar a -> a -> m (a, b) -> m b -- | Unlifted mkWeakMVar. mkWeakMVar :: MonadUnliftIO m => MVar a -> m () -> m Weak MVar a -- | The Reader+IO monad. This is different from a ReaderT because: -- --
-- data Record route = Record
-- { _get :: route :- Capture "id" Int :> Get '[JSON] String
-- , _put :: route :- ReqBody '[JSON] Int :> Put '[JSON] Bool
-- }
-- deriving (Generic)
--
-- getLink :: Int -> Link
-- getLink = fieldLink _get
--
fieldLink :: (IsElem endpoint ToServantApi routes, HasLink endpoint, GenericServant routes AsApi) => routes AsApi -> endpoint -> MkLink endpoint Link
-- | More general allLinks. See safeLink'.
allLinks' :: HasLink api => Link -> a -> Proxy api -> MkLink api a
-- | Create all links in an API.
--
-- Note that the api type must be restricted to the endpoints
-- that have valid links to them.
--
-- -- >>> type API = "foo" :> Capture "name" Text :> Get '[JSON] Text :<|> "bar" :> Capture "name" Int :> Get '[JSON] Double -- -- >>> let fooLink :<|> barLink = allLinks (Proxy :: Proxy API) -- -- >>> :t fooLink -- fooLink :: Text -> Link -- -- >>> :t barLink -- barLink :: Int -> Link ---- -- Note: nested APIs don't work well with this approach -- --
-- >>> :kind! MkLink (Capture "nest" Char :> (Capture "x" Int :> Get '[JSON] Int :<|> Capture "y" Double :> Get '[JSON] Double)) Link -- MkLink (Capture "nest" Char :> (Capture "x" Int :> Get '[JSON] Int :<|> Capture "y" Double :> Get '[JSON] Double)) Link :: * -- = Char -> (Int -> Link) :<|> (Double -> Link) --allLinks :: HasLink api => Proxy api -> MkLink api Link -- | More general safeLink. safeLink' :: (IsElem endpoint api, HasLink endpoint) => Link -> a -> Proxy api -> Proxy endpoint -> MkLink endpoint a -- | Create a valid (by construction) relative URI with query params. -- -- This function will only typecheck if endpoint is part of the -- API api safeLink :: (IsElem endpoint api, HasLink endpoint) => Proxy api -> Proxy endpoint -> MkLink endpoint Link -- | Configurable linkURI. -- --
-- >>> type API = "sum" :> QueryParams "x" Int :> Get '[JSON] Int -- -- >>> linkURI' LinkArrayElementBracket $ safeLink (Proxy :: Proxy API) (Proxy :: Proxy API) [1, 2, 3] -- sum?x[]=1&x[]=2&x[]=3 ---- --
-- >>> linkURI' LinkArrayElementPlain $ safeLink (Proxy :: Proxy API) (Proxy :: Proxy API) [1, 2, 3] -- sum?x=1&x=2&x=3 --linkURI' :: LinkArrayElementStyle -> Link -> URI -- | Transform Link into URI. -- --
-- >>> type API = "something" :> Get '[JSON] Int -- -- >>> linkURI $ safeLink (Proxy :: Proxy API) (Proxy :: Proxy API) -- something ---- --
-- >>> type API = "sum" :> QueryParams "x" Int :> Get '[JSON] Int -- -- >>> linkURI $ safeLink (Proxy :: Proxy API) (Proxy :: Proxy API) [1, 2, 3] -- sum?x[]=1&x[]=2&x[]=3 ---- --
-- >>> type API = "foo/bar" :> Get '[JSON] Int -- -- >>> linkURI $ safeLink (Proxy :: Proxy API) (Proxy :: Proxy API) -- foo%2Fbar ---- --
-- >>> type SomeRoute = "abc" :> Capture "email" String :> Put '[JSON] ()
--
-- >>> let someRoute = Proxy :: Proxy SomeRoute
--
-- >>> safeLink someRoute someRoute "test@example.com"
-- Link {_segments = ["abc","test%40example.com"], _queryParams = []}
--
--
-- -- >>> linkURI $ safeLink someRoute someRoute "test@example.com" -- abc/test%40example.com --linkURI :: Link -> URI linkQueryParams :: Link -> [Param] linkSegments :: Link -> [String] -- | A safe link datatype. The only way of constructing a Link is -- using safeLink, which means any Link is guaranteed to be -- part of the mentioned API. data Link -- | Query parameter. data Param SingleParam :: String -> Text -> Param ArrayElemParam :: String -> Text -> Param FlagParam :: String -> Param -- | How to encode array query elements. data LinkArrayElementStyle -- |
-- foo[]=1&foo[]=2 --LinkArrayElementBracket :: LinkArrayElementStyle -- |
-- foo=1&foo=2 --LinkArrayElementPlain :: LinkArrayElementStyle -- | A type that specifies that an API record contains a set of links. data AsLink a -- | Construct a toLink for an endpoint. class HasLink (endpoint :: k) where { type family MkLink (endpoint :: k) a :: *; } toLink :: HasLink endpoint => Link -> a -> Proxy endpoint -> Link -> MkLink endpoint a -- | WithNamedContext names a specific tagged context to use for the -- combinators in the API. (See also in servant-server, -- Servant.Server.Context.) For example: -- --
-- type UseNamedContextAPI = WithNamedContext "myContext" '[String] ( -- ReqBody '[JSON] Int :> Get '[JSON] Int) ---- -- Both the ReqBody and Get combinators will use the -- WithNamedContext with type tag "myContext" as their context. -- -- Contexts are only relevant for servant-server. -- -- For more information, see the tutorial. data WithNamedContext (name :: Symbol) (subContext :: [*]) subApi -- | Flatten API into a list of endpoints. -- --
-- >>> Refl :: Endpoints SampleAPI :~: '["hello" :> Verb 'GET 200 '[JSON] Int, "bye" :> (Capture "name" String :> Verb 'POST 200 '[JSON, PlainText] Bool)] -- Refl ---- | You may use this type family to tell the type checker that your custom -- type may be skipped as part of a link. This is useful for things like -- QueryParam that are optional in a URI and do not -- affect them if they are omitted. -- --
-- >>> data CustomThing -- -- >>> type instance IsElem' e (CustomThing :> s) = IsElem e s ---- -- Note that IsElem is called, which will mutually -- recurse back to IsElem' if it exhausts all other -- options again. -- -- Once you have written a HasLink instance for -- CustomThing you are ready to go. -- | Closed type family, check if endpoint is within api. -- Uses IsElem' if it exhausts all other options. -- --
-- >>> ok (Proxy :: Proxy (IsElem ("hello" :> Get '[JSON] Int) SampleAPI))
-- OK
--
--
--
-- >>> ok (Proxy :: Proxy (IsElem ("bye" :> Get '[JSON] Int) SampleAPI))
-- ...
-- ... Could not deduce...
-- ...
--
--
-- An endpoint is considered within an api even if it is missing
-- combinators that don't affect the URL:
--
-- -- >>> ok (Proxy :: Proxy (IsElem (Get '[JSON] Int) (Header "h" Bool :> Get '[JSON] Int))) -- OK ---- --
-- >>> ok (Proxy :: Proxy (IsElem (Get '[JSON] Int) (ReqBody '[JSON] Bool :> Get '[JSON] Int))) -- OK ---- --
-- >>> ok (Proxy :: Proxy (IsSubAPI SampleAPI (SampleAPI :<|> Get '[JSON] Int))) -- OK ---- --
-- >>> ok (Proxy :: Proxy (IsSubAPI (SampleAPI :<|> Get '[JSON] Int) SampleAPI)) -- ... -- ... Could not deduce... -- ... ---- -- This uses IsElem for checking; thus the note there applies -- here. -- | Check that every element of xs is an endpoint of api -- (using IsElem). -- | Closed type family, check if endpoint is exactly within -- api. -- --
-- >>> ok (Proxy :: Proxy (IsIn ("hello" :> Get '[JSON] Int) SampleAPI))
-- OK
--
--
-- Unlike IsElem, this requires an *exact* match.
--
-- -- >>> ok (Proxy :: Proxy (IsIn (Get '[JSON] Int) (Header "h" Bool :> Get '[JSON] Int))) -- ... -- ... Could not deduce... -- ... ---- | Check whether sub is a sub API of api. -- -- Like IsSubAPI, but uses IsIn rather than IsElem. -- | Check that every element of xs is an endpoint of api -- (using IsIn). -- -- ok (Proxy :: Proxy (AllIsIn (Endpoints SampleAPI) SampleAPI)) OK -- | Apply (e :>) to every API in xs. -- | Append two type-level lists. -- | Check that a value is an element of a list: -- --
-- >>> ok (Proxy :: Proxy (Elem Bool '[Int, Bool])) -- OK ---- --
-- >>> ok (Proxy :: Proxy (Elem String '[Int, Bool])) -- ... -- ... [Char]...'[Int, Bool... -- ... --type Elem (e :: t) (es :: [t]) = ElemGo e es es -- | Verb is a general type for representing HTTP verbs (a.k.a. -- methods). For convenience, type synonyms for each verb with a 200 -- response code are provided, but you are free to define your own: -- --
-- >>> type Post204 contentTypes a = Verb 'POST 204 contentTypes a --data Verb (method :: k1) (statusCode :: Nat) (contentTypes :: [*]) a :: forall k1. () => k1 -> Nat -> [*] -> * -> * -- | GET with 200 status code. type Get = Verb GET 200 -- | POST with 200 status code. type Post = Verb POST 200 -- | PUT with 200 status code. type Put = Verb PUT 200 -- | DELETE with 200 status code. type Delete = Verb DELETE 200 -- | PATCH with 200 status code. type Patch = Verb PATCH 200 -- | POST with 201 status code. type PostCreated = Verb POST 201 -- | GET with 202 status code. type GetAccepted = Verb GET 202 -- | POST with 202 status code. type PostAccepted = Verb POST 202 -- | DELETE with 202 status code. type DeleteAccepted = Verb DELETE 202 -- | PATCH with 202 status code. type PatchAccepted = Verb PATCH 202 -- | PUT with 202 status code. type PutAccepted = Verb PUT 202 -- | GET with 203 status code. type GetNonAuthoritative = Verb GET 203 -- | POST with 203 status code. type PostNonAuthoritative = Verb POST 203 -- | DELETE with 203 status code. type DeleteNonAuthoritative = Verb DELETE 203 -- | PATCH with 203 status code. type PatchNonAuthoritative = Verb PATCH 203 -- | PUT with 203 status code. type PutNonAuthoritative = Verb PUT 203 -- | GET with 204 status code. type GetNoContent = Verb GET 204 -- | POST with 204 status code. type PostNoContent = Verb POST 204 -- | DELETE with 204 status code. type DeleteNoContent = Verb DELETE 204 -- | PATCH with 204 status code. type PatchNoContent = Verb PATCH 204 -- | PUT with 204 status code. type PutNoContent = Verb PUT 204 -- | GET with 205 status code. type GetResetContent = Verb GET 205 -- | POST with 205 status code. type PostResetContent = Verb POST 205 -- | GET with 206 status code. type GetPartialContent = Verb GET 206 class ReflectMethod (a :: k) reflectMethod :: ReflectMethod a => Proxy a -> Method -- | The contained API (second argument) can be found under ("/" ++ -- path) (path being the first argument). -- -- Example: -- --
-- >>> -- GET /hello/world -- -- >>> -- returning a JSON encoded World value -- -- >>> type MyApi = "hello" :> "world" :> Get '[JSON] World --data (:>) (path :: k) a :: forall k. () => k -> * -> * -- | A Stream endpoint for a given method emits a stream of encoded values -- at a given Content-Type, delimited by a framing strategy. Stream -- endpoints always return response code 200 on success. Type synonyms -- are provided for standard methods. data Stream (method :: k1) (status :: Nat) framing contentType a :: forall k1. () => k1 -> Nat -> * -> * -> * -> * type StreamGet = Stream GET 200 type StreamPost = Stream POST 200 -- | Stream endpoints may be implemented as producing a -- StreamGenerator -- a function that itself takes two emit -- functions -- the first to be used on the first value the stream emits, -- and the second to be used on all subsequent values (to allow -- interspersed framing strategies such as comma separation). newtype StreamGenerator a StreamGenerator :: a -> IO () -> a -> IO () -> IO () -> StreamGenerator a [getStreamGenerator] :: StreamGenerator a -> a -> IO () -> a -> IO () -> IO () -- | ToStreamGenerator is intended to be implemented for types such as -- Conduit, Pipe, etc. By implementing this class, all such streaming -- abstractions can be used directly as endpoints. class ToStreamGenerator a b | a -> b toStreamGenerator :: ToStreamGenerator a b => a -> StreamGenerator b -- | Clients reading from streaming endpoints can be implemented as -- producing a ResultStream that captures the setup, takedown, -- and incremental logic for a read, being an IO continuation that takes -- a producer of Just either values or errors that terminates with a -- Nothing. newtype ResultStream a ResultStream :: forall b. () => IO Maybe Either String a -> IO b -> IO b -> ResultStream a -- | BuildFromStream is intended to be implemented for types such as -- Conduit, Pipe, etc. By implementing this class, all such streaming -- abstractions can be used directly on the client side for talking to -- streaming endpoints. class BuildFromStream a b buildFromStream :: BuildFromStream a b => ResultStream a -> b -- | The FramingRender class provides the logic for emitting a framing -- strategy. The strategy emits a header, followed by boundary-delimited -- data, and finally a termination character. For many strategies, some -- of these will just be empty bytestrings. class FramingRender (strategy :: k) (a :: k1) header :: FramingRender strategy a => Proxy strategy -> Proxy a -> ByteString boundary :: FramingRender strategy a => Proxy strategy -> Proxy a -> BoundaryStrategy trailer :: FramingRender strategy a => Proxy strategy -> Proxy a -> ByteString -- | The bracketing strategy generates things to precede and follow the -- content, as with netstrings. The intersperse strategy inserts -- seperators between things, as with newline framing. Finally, the -- general strategy performs an arbitrary rewrite on the content, to -- allow escaping rules and such. data BoundaryStrategy BoundaryStrategyBracket :: ByteString -> (ByteString, ByteString) -> BoundaryStrategy BoundaryStrategyIntersperse :: ByteString -> BoundaryStrategy BoundaryStrategyGeneral :: ByteString -> ByteString -> BoundaryStrategy -- | A type of parser that can never fail, and has different parsing -- strategies (incremental, or EOF) depending if more input can be sent. -- The incremental parser should return Nothing if it would like -- to be sent a longer ByteString. If it returns a value, it also returns -- the remainder following that value. data ByteStringParser a ByteStringParser :: ByteString -> Maybe (a, ByteString) -> ByteString -> (a, ByteString) -> ByteStringParser a [parseIncremental] :: ByteStringParser a -> ByteString -> Maybe (a, ByteString) [parseEOF] :: ByteStringParser a -> ByteString -> (a, ByteString) -- | The FramingUnrender class provides the logic for parsing a framing -- strategy. The outer ByteStringParser strips the header from a -- stream of bytes, and yields a parser that can handle the remainder, -- stepwise. Each frame may be a ByteString, or a String indicating the -- error state for that frame. Such states are per-frame, so that -- protocols that can resume after errors are able to do so. Eventually -- this returns an empty ByteString to indicate termination. class FramingUnrender (strategy :: k) (a :: k1) unrenderFrames :: FramingUnrender strategy a => Proxy strategy -> Proxy a -> ByteStringParser ByteStringParser Either String ByteString -- | A framing strategy that does not do any framing at all, it just passes -- the input data This will be used most of the time with binary data, -- such as files data NoFraming -- | A simple framing strategy that has no header or termination, and -- inserts a newline character between each frame. This assumes that it -- is used with a Content-Type that encodes without newlines (e.g. JSON). data NewlineFraming -- | The netstring framing strategy as defined by djb: -- http://cr.yp.to/proto/netstrings.txt data NetstringFraming -- | Deliberately do not add a header to a value. -- --
-- >>> let example1 = noHeader "hi" :: Headers '[Header "someheader" Int] String -- -- >>> getHeaders example1 -- [] --noHeader :: AddHeader h v orig new => orig -> new -- | addHeader adds a header to a response. Note that it changes -- the type of the value in the following ways: -- --
-- >>> let example1 = addHeader 5 "hi" :: Headers '[Header "someheader" Int] String;
--
-- >>> getHeaders example1
-- [("someheader","5")]
--
--
--
-- >>> let example1 = addHeader 5 "hi" :: Headers '[Header "someheader" Int] String;
--
-- >>> let example2 = addHeader True example1 :: Headers '[Header "1st" Bool, Header "someheader" Int] String
--
-- >>> getHeaders example2
-- [("1st","true"),("someheader","5")]
--
--
-- Note that while in your handlers type annotations are not required,
-- since the type can be inferred from the API type, in other cases you
-- may find yourself needing to add annotations.
addHeader :: AddHeader h v orig new => v -> orig -> new
-- | Response Header objects. You should never need to construct one
-- directly. Instead, use addOptionalHeader.
data Headers (ls :: [*]) a
Headers :: a -> HList ls -> Headers a
-- | The underlying value of a Headers
[getResponse] :: Headers a -> a
-- | HList of headers.
[getHeadersHList] :: Headers a -> HList ls
data ResponseHeader (sym :: Symbol) a
Header :: a -> ResponseHeader a
MissingHeader :: ResponseHeader a
UndecodableHeader :: ByteString -> ResponseHeader a
data HList (a :: [*])
[HNil] :: HList ([] :: [*])
[HCons] :: HList Header h x : xs
class BuildHeadersTo (hs :: [*])
-- | Note: if there are multiple occurences of a header in the argument,
-- the values are interspersed with commas before deserialization (see
-- RFC2616 Sec 4.2)
buildHeadersTo :: BuildHeadersTo hs => [Header] -> HList hs
class GetHeaders ls
getHeaders :: GetHeaders ls => ls -> [Header]
class AddHeader (h :: Symbol) v orig new | h v orig -> new, new -> h, new -> v, new -> orig
-- | Extract the request body as a value of type a.
--
-- Example:
--
-- -- >>> -- POST /books -- -- >>> type MyApi = "books" :> ReqBody '[JSON] Book :> Post '[JSON] Book --type ReqBody = ReqBody' Required : Strict : ([] :: [*]) -- | Note: ReqBody' is always Required. data ReqBody' (mods :: [*]) (contentTypes :: [*]) a -- | Provides access to the host or IP address from which the HTTP request -- was sent. data RemoteHost -- | Endpoint for plugging in your own Wai Applications. -- -- The given Application will get the request as received by the -- server, potentially with a modified (stripped) pathInfo if -- the Application is being routed with :>. -- -- In addition to just letting you plug in your existing WAI -- Applications, this can also be used with -- serveDirectory to serve static files stored in a particular -- directory on your filesystem data Raw -- | Lookup the value associated to the sym query string parameter -- and try to extract it as a value of type a. -- -- Example: -- --
-- >>> -- /books?author=<author name> -- -- >>> type MyApi = "books" :> QueryParam "author" Text :> Get '[JSON] [Book] --type QueryParam = QueryParam' Optional : Strict : ([] :: [*]) -- | QueryParam which can be Required, Lenient, or -- modified otherwise. data QueryParam' (mods :: [*]) (sym :: Symbol) a -- | Lookup the values associated to the sym query string -- parameter and try to extract it as a value of type [a]. This -- is typically meant to support query string parameters of the form -- param[]=val1¶m[]=val2 and so on. Note that servant -- doesn't actually require the []s and will fetch the values -- just fine with param=val1¶m=val2, too. -- -- Example: -- --
-- >>> -- /books?authors[]=<author1>&authors[]=<author2>&... -- -- >>> type MyApi = "books" :> QueryParams "authors" Text :> Get '[JSON] [Book] --data QueryParams (sym :: Symbol) a -- | Lookup a potentially value-less query string parameter with boolean -- semantics. If the param sym is there without any value, or if -- it's there with value "true" or "1", it's interpreted as True. -- Otherwise, it's interpreted as False. -- -- Example: -- --
-- >>> -- /books?published -- -- >>> type MyApi = "books" :> QueryFlag "published" :> Get '[JSON] [Book] --data QueryFlag (sym :: Symbol) -- | Extract the given header's value as a value of type a. I.e. -- header sent by client, parsed by server. -- -- Example: -- --
-- >>> newtype Referer = Referer Text deriving (Eq, Show) -- -- >>> -- -- >>> -- GET /view-my-referer -- -- >>> type MyApi = "view-my-referer" :> Header "from" Referer :> Get '[JSON] Referer --type Header = (Header' Optional : Strict : ([] :: [*]) :: Symbol -> k -> *) data Header' (mods :: [*]) (sym :: Symbol) (a :: k) :: forall k. () => [*] -> Symbol -> k -> * -- | Required argument. Not wrapped. data Required -- | Optional argument. Wrapped in Maybe. data Optional -- | Leniently parsed argument, i.e. parsing never fail. Wrapped in -- Either Text. data Lenient -- | Strictly parsed argument. Not wrapped. data Strict -- | Was this request made over an SSL connection? -- -- Note that this value will not tell you if the client originally made -- this request over SSL, but rather whether the current connection is -- SSL. The distinction lies with reverse proxies. In many cases, the -- client will connect to a load balancer over SSL, but connect to the -- WAI handler without SSL. In such a case, the handlers would get -- NotSecure, but from a user perspective, there is a secure -- connection. data IsSecure -- | the connection to the server is secure (HTTPS) Secure :: IsSecure -- | the connection to the server is not secure (HTTP) NotSecure :: IsSecure -- | A generalized Authentication combinator. Use this if you have a -- non-standard authentication technique. -- -- NOTE: THIS API IS EXPERIMENTAL AND SUBJECT TO CHANGE. data AuthProtect (tag :: k) :: forall k. () => k -> * -- | An empty API: one which serves nothing. Morally speaking, this should -- be the unit of :<|>. Implementors of interpretations of -- API types should treat EmptyAPI as close to the unit as -- possible. data EmptyAPI EmptyAPI :: EmptyAPI -- | Add a short summary for (part of) API. -- -- Example: -- --
-- >>> type MyApi = Summary "Get book by ISBN." :> "books" :> Capture "isbn" Text :> Get '[JSON] Book --data Summary (sym :: Symbol) -- | Add more verbose description for (part of) API. -- -- Example: -- --
-- >>> :{
-- type MyApi = Description
-- "This comment is visible in multiple Servant interpretations \
-- \and can be really long if necessary. \
-- \Haskell multiline support is not perfect \
-- \but it's still very readable."
-- :> Get '[JSON] Book
-- :}
--
data Description (sym :: Symbol)
data JSON
data PlainText
data FormUrlEncoded
data OctetStream
-- | Instances of Accept represent mimetypes. They are used for
-- matching against the Accept HTTP header of the request, and
-- for setting the Content-Type header of the response
--
-- Example:
--
--
-- >>> import Network.HTTP.Media ((//), (/:))
--
-- >>> data HTML
--
-- >>> :{
-- instance Accept HTML where
-- contentType _ = "text" // "html" /: ("charset", "utf-8")
-- :}
--
class Accept (ctype :: k)
contentType :: Accept ctype => Proxy ctype -> MediaType
contentTypes :: Accept ctype => Proxy ctype -> NonEmpty MediaType
-- | Instantiate this class to register a way of serializing a type based
-- on the Accept header.
--
-- Example:
--
--
-- data MyContentType
--
-- instance Accept MyContentType where
-- contentType _ = "example" // "prs.me.mine" /: ("charset", "utf-8")
--
-- instance Show a => MimeRender MyContentType a where
-- mimeRender _ val = pack ("This is MINE! " ++ show val)
--
-- type MyAPI = "path" :> Get '[MyContentType] Int
--
class Accept ctype => MimeRender (ctype :: k) a
mimeRender :: MimeRender ctype a => Proxy ctype -> a -> ByteString
-- | Instantiate this class to register a way of deserializing a type based
-- on the request's Content-Type header.
--
-- -- >>> import Network.HTTP.Media hiding (Accept) -- -- >>> import qualified Data.ByteString.Lazy.Char8 as BSC -- -- >>> data MyContentType = MyContentType String ---- --
-- >>> :{
-- instance Accept MyContentType where
-- contentType _ = "example" // "prs.me.mine" /: ("charset", "utf-8")
-- :}
--
--
--
-- >>> :{
-- instance Read a => MimeUnrender MyContentType a where
-- mimeUnrender _ bs = case BSC.take 12 bs of
-- "MyContentType" -> return . read . BSC.unpack $ BSC.drop 12 bs
-- _ -> Left "didn't start with the magic incantation"
-- :}
--
--
-- -- >>> type MyAPI = "path" :> ReqBody '[MyContentType] Int :> Get '[JSON] Int --class Accept ctype => MimeUnrender (ctype :: k) a mimeUnrender :: MimeUnrender ctype a => Proxy ctype -> ByteString -> Either String a -- | Variant which is given the actual MediaType provided by the -- other party. -- -- In the most cases you don't want to branch based on the -- MediaType. See pr552 for a motivating example. mimeUnrenderWithType :: MimeUnrender ctype a => Proxy ctype -> MediaType -> ByteString -> Either String a -- | A type for responses without content-body. data NoContent NoContent :: NoContent -- | Capture a value from the request path under a certain type a. -- -- Example: -- --
-- >>> -- GET /books/:isbn -- -- >>> type MyApi = "books" :> Capture "isbn" Text :> Get '[JSON] Book --type Capture = Capture' ([] :: [*]) -- | Capture which can be modified. For example with -- Description. data Capture' (mods :: [*]) (sym :: Symbol) a -- | Capture all remaining values from the request path under a certain -- type a. -- -- Example: -- --
-- >>> -- GET /src/* -- -- >>> type MyAPI = "src" :> CaptureAll "segments" Text :> Get '[JSON] SourceFile --data CaptureAll (sym :: Symbol) a -- | Combinator for Basic Access Authentication. -- --
-- >>> :{
-- type MyApi = "books" :> Get '[JSON] [Book] -- GET /books
-- :<|> "books" :> ReqBody '[JSON] Book :> Post '[JSON] () -- POST /books
-- :}
--
data (:<|>) a b
(:<|>) :: a -> b -> (:<|>) a b
-- | A persistent store for values of arbitrary types.
--
-- This variant is the simplest and creates keys in the IO monad.
-- See the module Data.Vault.ST if you want to use it with the
-- ST monad instead.
type Vault = Vault RealWorld
class SBoolI (b :: Bool)
sbool :: SBoolI b => SBool b
data SBool (b :: Bool)
[STrue] :: SBool True
[SFalse] :: SBool False
-- | Same as serveDirectoryFileServer. It used to be the only file
-- serving function in servant pre-0.10 and will be kept around for a few
-- versions, but is deprecated.
serveDirectory :: () => FilePath -> ServerT Raw m
-- | Alias for staticApp. Lets you serve a directory with arbitrary
-- StaticSettings. Useful when you want particular settings not
-- covered by the four other variants. This is the most flexible method.
serveDirectoryWith :: () => StaticSettings -> ServerT Raw m
-- | Uses embeddedSettings.
serveDirectoryEmbedded :: () => [(FilePath, ByteString)] -> ServerT Raw m
-- | Same as serveDirectoryWebApp, but uses
-- webAppSettingsWithLookup.
serveDirectoryWebAppLookup :: () => ETagLookup -> FilePath -> ServerT Raw m
-- | Same as serveDirectoryWebApp, but uses
-- defaultFileServerSettings.
serveDirectoryFileServer :: () => FilePath -> ServerT Raw m
-- | Serve anything under the specified directory as a Raw endpoint.
--
-- -- type MyApi = "static" :> Raw -- -- server :: Server MyApi -- server = serveDirectoryWebApp "/var/www" ---- -- would capture any request to /static/<something> and -- look for <something> under /var/www. -- -- It will do its best to guess the MIME type for that file, based on the -- extension, and send an appropriate Content-Type header if -- possible. -- -- If your goal is to serve HTML, CSS and Javascript files that use the -- rest of the API as a webapp backend, you will most likely not want the -- static files to be hidden behind a /static/ prefix. In that -- case, remember to put the serveDirectoryWebApp handler in the -- last position, because servant will try to match the handlers -- in order. -- -- Corresponds to the defaultWebAppSettings StaticSettings -- value. serveDirectoryWebApp :: () => FilePath -> ServerT Raw m -- | Variant of layout that takes an additional Context. layoutWithContext :: HasServer api context => Proxy api -> Context context -> Text -- | The function layout produces a textual description of the -- internal router layout for debugging purposes. Note that the router -- layout is determined just by the API, not by the handlers. -- -- Example: -- -- For the following API -- --
-- type API = -- "a" :> "d" :> Get '[JSON] NoContent -- :<|> "b" :> Capture "x" Int :> Get '[JSON] Bool -- :<|> "c" :> Put '[JSON] Bool -- :<|> "a" :> "e" :> Get '[JSON] Int -- :<|> "b" :> Capture "x" Int :> Put '[JSON] Bool -- :<|> Raw ---- -- we get the following output: -- --
-- / -- ├─ a/ -- │ ├─ d/ -- │ │ └─• -- │ └─ e/ -- │ └─• -- ├─ b/ -- │ └─ <capture>/ -- │ ├─• -- │ ┆ -- │ └─• -- ├─ c/ -- │ └─• -- ┆ -- └─ <raw> ---- -- Explanation of symbols: -- --
-- >>> import Control.Monad.Reader -- -- >>> type ReaderAPI = "ep1" :> Get '[JSON] Int :<|> "ep2" :> Get '[JSON] String :<|> Raw :<|> EmptyAPI -- -- >>> let readerApi = Proxy :: Proxy ReaderAPI -- -- >>> let readerServer = return 1797 :<|> ask :<|> Tagged (error "raw server") :<|> emptyServer :: ServerT ReaderAPI (Reader String) -- -- >>> let nt x = return (runReader x "hi") -- -- >>> let mainServer = hoistServer readerApi nt readerServer :: Server ReaderAPI --hoistServer :: HasServer api ([] :: [*]) => Proxy api -> forall x. () => m x -> n x -> ServerT api m -> ServerT api n serveWithContext :: HasServer api context => Proxy api -> Context context -> Server api -> Application -- | serve allows you to implement an API and produce a wai -- Application. -- -- Example: -- --
-- type MyApi = "books" :> Get '[JSON] [Book] -- GET /books -- :<|> "books" :> ReqBody Book :> Post '[JSON] Book -- POST /books -- -- server :: Server MyApi -- server = listAllBooks :<|> postBook -- where listAllBooks = ... -- postBook book = ... -- -- myApi :: Proxy MyApi -- myApi = Proxy -- -- app :: Application -- app = serve myApi server -- -- main :: IO () -- main = Network.Wai.Handler.Warp.run 8080 app --serve :: HasServer api ([] :: [*]) => Proxy api -> Server api -> Application -- | Server for EmptyAPI emptyServer :: () => ServerT EmptyAPI m class HasServer (api :: k) (context :: [*]) where { type family ServerT (api :: k) (m :: * -> *) :: *; } route :: HasServer api context => Proxy api -> Context context -> Delayed env Server api -> Router env hoistServerWithContext :: HasServer api context => Proxy api -> Proxy context -> forall x. () => m x -> n x -> ServerT api m -> ServerT api n type Server (api :: k) = ServerT api Handler -- | Singleton type representing a server that serves an empty API. data EmptyServer -- | servant-server's current implementation of basic authentication is not -- immune to certian kinds of timing attacks. Decoding payloads does not -- take a fixed amount of time. -- -- The result of authentication/authorization data BasicAuthResult usr Unauthorized :: BasicAuthResult usr BadPassword :: BasicAuthResult usr NoSuchUser :: BasicAuthResult usr Authorized :: usr -> BasicAuthResult usr -- | Datatype wrapping a function used to check authentication. newtype BasicAuthCheck usr BasicAuthCheck :: BasicAuthData -> IO BasicAuthResult usr -> BasicAuthCheck usr [unBasicAuthCheck] :: BasicAuthCheck usr -> BasicAuthData -> IO BasicAuthResult usr -- | Apply a transformation to the response of a Router. tweakResponse :: () => RouteResult Response -> RouteResult Response -> Router env -> Router env toApplication :: RoutingApplication -> Application runHandler :: () => Handler a -> IO Either ServantErr a runHandler' :: Handler a -> ExceptT ServantErr IO a -- | err505 HTTP Version not supported -- -- Example usage: -- --
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err505 { errBody = "I support HTTP/4.0 only." }
--
err505 :: ServantErr
-- | err504 Gateway Time-out
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err504 { errBody = "Backend foobar did not respond in 5 seconds." }
--
err504 :: ServantErr
-- | err503 Service Unavailable
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err503 { errBody = "We're rewriting in PHP." }
--
err503 :: ServantErr
-- | err502 Bad Gateway
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err502 { errBody = "Tried gateway foo, bar, and baz. None responded." }
--
err502 :: ServantErr
-- | err501 Not Implemented
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err501 { errBody = "/v1/foo is not supported with quux in the request." }
--
err501 :: ServantErr
-- | err500 Internal Server Error
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err500 { errBody = "Exception in module A.B.C:55. Have a great day!" }
--
err500 :: ServantErr
-- | err422 Unprocessable Entity
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err422 { errBody = "I understood your request, but can't process it." }
--
err422 :: ServantErr
-- | err418 Expectation Failed
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err418 { errBody = "Apologies, this is not a webserver but a teapot." }
--
err418 :: ServantErr
-- | err417 Expectation Failed
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err417 { errBody = "I found a quux in the request. This isn't going to work." }
--
err417 :: ServantErr
-- | err416 Request range not satisfiable
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err416 { errBody = "Valid range is [0, 424242]." }
--
err416 :: ServantErr
-- | err415 Unsupported Media Type
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err415 { errBody = "Supported media types: gif, png" }
--
err415 :: ServantErr
-- | err414 Request-URI Too Large
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err414 { errBody = "Maximum length is 64." }
--
err414 :: ServantErr
-- | err413 Request Entity Too Large
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err413 { errBody = "Request exceeded 64k." }
--
err413 :: ServantErr
-- | err412 Precondition Failed
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err412 { errBody = "Precondition fail: x < 42 && y > 57" }
--
err412 :: ServantErr
-- | err411 Length Required
--
-- Example:
--
-- -- failingHandler :: Handler () -- failingHandler = throwError err411 --err411 :: ServantErr -- | err410 Gone -- -- Example: -- --
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err410 { errBody = "I know it was here at some point, but.. I blame bad luck." }
--
err410 :: ServantErr
-- | err409 Conflict
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err409 { errBody = "Transaction conflicts with 59879cb56c7c159231eeacdd503d755f7e835f74" }
--
err409 :: ServantErr
-- | err407 Proxy Authentication Required
--
-- Example:
--
-- -- failingHandler :: Handler () -- failingHandler = throwError err407 --err407 :: ServantErr -- | err406 Not Acceptable -- -- Example: -- --
-- failingHandler :: Handler () -- failingHandler = throwError err406 --err406 :: ServantErr -- | err405 Method Not Allowed -- -- Example: -- --
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err405 { errBody = "Your account privileges does not allow for this. Please pay $$$." }
--
err405 :: ServantErr
-- | err404 Not Found
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err404 { errBody = "(╯°□°)╯︵ ┻━┻)." }
--
err404 :: ServantErr
-- | err403 Forbidden
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err403 { errBody = "Please login first." }
--
err403 :: ServantErr
-- | err402 Payment Required
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err402 { errBody = "You have 0 credits. Please give me $$$." }
--
err402 :: ServantErr
-- | err401 Unauthorized
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err401 { errBody = "Your credentials are invalid." }
--
err401 :: ServantErr
-- | err400 Bad Request
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err400 { errBody = "Your request makes no sense to me." }
--
err400 :: ServantErr
-- | err307 Temporary Redirect
--
-- Example:
--
-- -- failingHandler :: Handler () -- failingHandler = throwError err307 --err307 :: ServantErr -- | err305 Use Proxy -- -- Example: -- --
-- failingHandler :: Handler () -- failingHandler = throwError err305 --err305 :: ServantErr -- | err304 Not Modified -- -- Example: -- --
-- failingHandler :: Handler () -- failingHandler = throwError err304 --err304 :: ServantErr -- | err303 See Other -- -- Example: -- --
-- failingHandler :: Handler () -- failingHandler = throwError err303 --err303 :: ServantErr -- | err302 Found -- -- Example: -- --
-- failingHandler :: Handler () -- failingHandler = throwError err302 --err302 :: ServantErr -- | err301 Moved Permanently -- -- Example: -- --
-- failingHandler :: Handler () -- failingHandler = throwError err301 --err301 :: ServantErr -- | err300 Multiple Choices -- -- Example: -- --
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err300 { errBody = "I can't choose." }
--
err300 :: ServantErr
data ServantErr
ServantErr :: Int -> String -> ByteString -> [Header] -> ServantErr
[errHTTPCode] :: ServantErr -> Int
[errReasonPhrase] :: ServantErr -> String
[errBody] :: ServantErr -> ByteString
[errHeaders] :: ServantErr -> [Header]
-- | descendIntoNamedContext allows you to access
-- NamedContexts. Usually you won't have to use it yourself but
-- instead use a combinator like WithNamedContext.
--
-- This is how descendIntoNamedContext works:
--
-- -- >>> :set -XFlexibleContexts -- -- >>> let subContext = True :. EmptyContext -- -- >>> :type subContext -- subContext :: Context '[Bool] -- -- >>> let parentContext = False :. (NamedContext subContext :: NamedContext "subContext" '[Bool]) :. EmptyContext -- -- >>> :type parentContext -- parentContext :: Context '[Bool, NamedContext "subContext" '[Bool]] -- -- >>> descendIntoNamedContext (Proxy :: Proxy "subContext") parentContext :: Context '[Bool] -- True :. EmptyContext --descendIntoNamedContext :: HasContextEntry context NamedContext name subContext => Proxy name -> Context context -> Context subContext -- | Contexts are used to pass values to combinators. (They are -- not meant to be used to pass parameters to your handlers, i.e. -- they should not replace any custom ReaderT-monad-stack that -- you're using with hoistServer.) If you don't use combinators -- that require any context entries, you can just use serve as -- always. -- -- If you are using combinators that require a non-empty Context -- you have to use serveWithContext and pass it a Context -- that contains all the values your combinators need. A Context -- is essentially a heterogenous list and accessing the elements is being -- done by type (see getContextEntry). The parameter of the type -- Context is a type-level list reflecting the types of the -- contained context entries. To create a Context with entries, -- use the operator (:.): -- --
-- >>> :type True :. () :. EmptyContext -- True :. () :. EmptyContext :: Context '[Bool, ()] --data Context (contextTypes :: [*]) [EmptyContext] :: Context ([] :: [*]) [:.] :: Context x : xs -- | This class is used to access context entries in Contexts. -- getContextEntry returns the first value where the type matches: -- --
-- >>> getContextEntry (True :. False :. EmptyContext) :: Bool -- True ---- -- If the Context does not contain an entry of the requested type, -- you'll get an error: -- --
-- >>> getContextEntry (True :. False :. EmptyContext) :: String -- ... -- ...No instance for (HasContextEntry '[] [Char]) -- ... --class HasContextEntry (context :: [*]) val getContextEntry :: HasContextEntry context val => Context context -> val -- | Normally context entries are accessed by their types. In case you need -- to have multiple values of the same type in your Context and -- need to access them, we provide NamedContext. You can think of -- it as sub-namespaces for Contexts. data NamedContext (name :: Symbol) (subContext :: [*]) NamedContext :: Context subContext -> NamedContext -- | The WAI application. -- -- Note that, since WAI 3.0, this type is structured in continuation -- passing style to allow for proper safe resource handling. This was -- handled in the past via other means (e.g., ResourceT). As a -- demonstration: -- --
-- app :: Application -- app req respond = bracket_ -- (putStrLn "Allocating scarce resource") -- (putStrLn "Cleaning up") -- (respond $ responseLBS status200 [] "Hello World") --type Application = Request -> Response -> IO ResponseReceived -> IO ResponseReceived -- | A Tagged s b value is a value b with an -- attached phantom type s. This can be used in place of the -- more traditional but less safe idiom of passing in an undefined value -- with the type, because unlike an (s -> b), a -- Tagged s b can't try to use the argument s as -- a real value. -- -- Moreover, you don't have to rely on the compiler to inline away the -- extra argument, because the newtype is "free" -- -- Tagged has kind k -> * -> * if the compiler -- supports PolyKinds, therefore there is an extra k -- showing in the instance haddocks that may cause confusion. newtype Tagged (s :: k) b :: forall k. () => k -> * -> * Tagged :: b -> Tagged b [unTagged] :: Tagged b -> b -- | Split on the given sublist. Equivalent to split . -- dropDelims . onSublist. For example: -- --
-- splitOn ".." "a..b...c....d.." == ["a","b",".c","","d",""] ---- -- In some parsing combinator frameworks this is also known as -- sepBy. -- -- Note that this is the right inverse of the intercalate function -- from Data.List, that is, -- --
-- intercalate x . splitOn x === id ---- -- splitOn x . intercalate x is the identity on -- certain lists, but it is tricky to state the precise conditions under -- which this holds. (For example, it is not enough to say that -- x does not occur in any elements of the input list. Working -- out why is left as an exercise for the reader.) splitOn :: Eq a => [a] -> [a] -> [[a]] fromLT :: ConvertibleStrings LT a => LT -> a fromLazyText :: ConvertibleStrings LazyText a => LazyText -> a fromST :: ConvertibleStrings ST a => ST -> a fromStrictText :: ConvertibleStrings StrictText a => StrictText -> a fromLBS :: ConvertibleStrings LBS a => LBS -> a fromLazyByteString :: ConvertibleStrings LazyByteString a => LazyByteString -> a fromSBS :: ConvertibleStrings SBS a => SBS -> a fromStrictByteString :: ConvertibleStrings StrictByteString a => StrictByteString -> a toLT :: ConvertibleStrings a LT => a -> LT toLazyText :: ConvertibleStrings a LazyText => a -> LazyText toST :: ConvertibleStrings a ST => a -> ST toStrictText :: ConvertibleStrings a StrictText => a -> StrictText toLBS :: ConvertibleStrings a LBS => a -> LBS toLazyByteString :: ConvertibleStrings a LazyByteString => a -> LazyByteString toSBS :: ConvertibleStrings a SBS => a -> SBS toStrictByteString :: ConvertibleStrings a StrictByteString => a -> StrictByteString toString :: ConvertibleStrings a String => a -> String cs :: ConvertibleStrings a b => a -> b class ConvertibleStrings a b convertString :: ConvertibleStrings a b => a -> b type StrictByteString = ByteString type SBS = ByteString type LazyByteString = ByteString type LBS = ByteString type StrictText = Text type ST = Text type LazyText = Text type LT = Text -- | Convert a ExceptT computation to MaybeT, discarding the -- value of any exception. exceptToMaybeT :: Functor m => ExceptT e m a -> MaybeT m a -- | Convert a MaybeT computation to ExceptT, with a default -- exception value. maybeToExceptT :: Functor m => e -> MaybeT m a -> ExceptT e m a -- | Lifted version of mkWeakThreadId. mkWeakThreadId :: MonadIO m => ThreadId -> m Weak ThreadId -- | Unlifted version of runInUnboundThread. runInUnboundThread :: MonadUnliftIO m => m a -> m a -- | Unlifted version of runInBoundThread. runInBoundThread :: MonadUnliftIO m => m a -> m a -- | Unflifted version of forkOS. forkOS :: MonadUnliftIO m => m () -> m ThreadId -- | Lifted version of yield. yield :: MonadIO m => m () -- | Lifted version of threadCapability. threadCapability :: MonadIO m => ThreadId -> m (Int, Bool) -- | Lifted version of setNumCapabilities. setNumCapabilities :: MonadIO m => Int -> m () -- | Lifted version of getNumCapabilities. getNumCapabilities :: MonadIO m => m Int -- | Unlifted version of forkOnWithUnmask. forkOnWithUnmask :: MonadUnliftIO m => Int -> forall a. () => m a -> m a -> m () -> m ThreadId -- | Unlifted version of forkOn. forkOn :: MonadUnliftIO m => Int -> m () -> m ThreadId -- | Lifted version of killThread. killThread :: MonadIO m => ThreadId -> m () -- | Unlifted version of forkFinally. forkFinally :: MonadUnliftIO m => m a -> Either SomeException a -> m () -> m ThreadId -- | Unlifted version of forkIOWithUnmask. forkWithUnmask :: MonadUnliftIO m => forall a. () => m a -> m a -> m () -> m ThreadId -- | Unlifted version of forkIO. forkIO :: MonadUnliftIO m => m () -> m ThreadId -- | Middleware is a component that sits between the server and -- application. It can do such tasks as GZIP encoding or response -- caching. What follows is the general definition of middleware, though -- a middleware author should feel free to modify this. -- -- As an example of an alternate type for middleware, suppose you write a -- function to load up session information. The session information is -- simply a string map <math>. A logical type signature for this -- middleware might be: -- --
-- loadSession :: ([(String, String)] -> Application) -> Application ---- -- Here, instead of taking a standard Application as its first -- argument, the middleware takes a function which consumes the session -- information as well. type Middleware = Application -> Application defWaiMain :: Application -> IO () defPutListening :: WaiOptions -> IO () waiMain :: WaiOptions -> IO () -> WaiOptions -> IO () -> Application -> IO () runGraceful :: GracefulMode -> Settings -> Application -> IO () -> Settings -> Application -> IO () runActivated :: Settings -> Socket -> Application -> IO () -> Settings -> Application -> IO () data GracefulMode ServeNormally :: GracefulMode Serve503 :: GracefulMode data WaiOptions WaiOptions :: Int -> String -> String -> String -> String -> String -> Maybe Bool -> WaiOptions -- | Create a middleware to be added to a WAI-based webserver. metrics :: WaiMetrics -> Middleware -- | Register in EKG a number of metrics related to web server activity -- with a namespace. -- --
namespace.wai.request_count
namespace.wai.response_status_1xx
namespace.wai.response_status_2xx
namespace.wai.response_status_3xx
namespace.wai.response_status_4xx
namespace.wai.response_status_5xx
namespace.wai.latency_distribution
wai.request_count
wai.response_status_1xx
wai.response_status_2xx
wai.response_status_3xx
wai.response_status_4xx
wai.response_status_5xx
wai.latency_distribution
-- >>> :set -XOverloadedStrings -- -- >>> slugify "Hello & World!" -- "hello-and-world" --slugify :: Text -> Text -- | Creates a simple text/plain ServantErr. errText :: ServantErr -> ByteString -> ServantErr -- | Creates and throws a simple text/plain ServantErr. throwErrText :: MonadThrow μ => ServantErr -> ByteString -> μ α type MonadHTTP ψ μ = (HasHttpManager ψ, MonadReader ψ μ, MonadUnliftIO μ) newtype ModHttpClient ModHttpClient :: Manager -> ModHttpClient newHttpClient :: IO ModHttpClient runHTTP :: ExceptT ε μ α -> μ (Either ε α) -- | Creates a request from a URI. reqU :: (MonadHTTP ψ μ) => URI -> ExceptT Text μ Request -- | Creates a request from a string of any type, parsing it into a URI. reqS :: (MonadHTTP ψ μ, ConvertibleStrings σ String) => σ -> ExceptT Text μ Request -- | Configures the request to not throw errors on error status codes. anyStatus :: (MonadHTTP ψ μ) => Request -> ExceptT Text μ Request -- | Sets a x-www-form-urlencoded form as the request body (also sets the -- content-type). postForm :: (MonadHTTP ψ μ) => [(Text, Text)] -> Request -> ExceptT Text μ Request -- | Sets a JSON value as the request body (via ToJSON; also sets the -- content-type). postJson :: (MonadHTTP ψ μ, ToJSON α) => α -> Request -> ExceptT Text μ Request -- | Performs the request, using a given function to read the body. This is -- what all other performWith functions are based on. performWithFn :: (MonadHTTP ψ μ, MonadCatch μ) => (ConduitM ι ByteString μ () -> ConduitT () Void μ ρ) -> Request -> ExceptT Text μ (Response ρ) -- | Performs the request, ignoring the body. performWithVoid :: (MonadHTTP ψ μ, MonadCatch μ) => Request -> ExceptT Text μ (Response ()) -- | Performs the request, reading the body into a lazy ByteString. performWithBytes :: (MonadHTTP ψ μ, MonadCatch μ) => Request -> ExceptT Text μ (Response ByteString) -- | Add headers to the request, preserving any existing headers not -- specified in the new set. applyHeaders :: RequestHeaders -> Request -> Request -- | Remove listed headers from the request. removeHeaders :: [HeaderName] -> Request -> Request -- | Gets a value of any type from the context. askObj :: (Has β α, MonadReader α μ) => μ β -- | Gets a thing from a value of any type from the context. (Useful for -- configuration fields.) askOpt :: (Has β α, MonadReader α μ) => (β -> ψ) -> μ ψ decodeEnvy :: FromEnv a => IO Maybe a -- | Reads an Envy configuration from the env variables and launches the -- given action if successful. (Does environment variable reading ever -- fail in practice? Probably not.) withEnvConfig :: FromEnv α => (α -> IO ()) -> IO () type BasicApp α = RIO BasicContext α type BasicContext = (ModHttpClient, ModLogger) newBasicContext :: IO BasicContext