@@ -0,0 +1,613 @@
1+-- Hoogle documentation, generated by Haddock
2+-- See Hoogle, http://www.haskell.org/hoogle/
5+-- | A family of combinators for defining webservices APIs and serving them
10+module Servant.Common.Text
12+-- | For getting values from url captures and query string parameters
14+fromText :: FromText a => Text -> Maybe a
16+-- | For putting values in paths and query string parameters
18+toText :: ToText a => a -> Text
20+instance FromText Float
21+instance ToText Double
22+instance FromText Double
23+instance ToText Integer
24+instance FromText Integer
25+instance ToText Word64
26+instance FromText Word64
27+instance ToText Word32
28+instance FromText Word32
29+instance ToText Word16
30+instance FromText Word16
32+instance FromText Word8
34+instance FromText Word
36+instance FromText Int64
38+instance FromText Int32
40+instance FromText Int16
42+instance FromText Int8
46+instance FromText Bool
47+instance ToText String
48+instance FromText String
50+instance FromText Text
53+-- | This module lets you implement <a>Server</a>s for defined APIs. You'll
54+-- most likely just need <a>serve</a>.
57+-- | <a>serve</a> allows you to implement an API and produce a wai
58+-- <a>Application</a>.
63+-- type MyApi = "books" :> Get [Book] -- GET /books
64+-- :<|> "books" :> ReqBody Book :> Post Book -- POST /books
66+-- server :: Server MyApi
67+-- server = listAllBooks :<|> postBook
68+-- where listAllBooks = ...
69+-- postBook book = ...
72+-- app = serve myApi server
75+-- main = Network.Wai.Handler.Warp.run 8080 app
77+serve :: HasServer layout => Proxy layout -> Server layout -> Application
78+toApplication :: RoutingApplication -> Application
81+-- | the usual "not found" error
82+NotFound :: RouteMismatch
84+-- | a more informative "you just got the HTTP method wrong" error
85+WrongMethod :: RouteMismatch
87+-- | an even more informative "your json request body wasn't valid" error
88+InvalidBody :: RouteMismatch
91+-- > mempty = NotFound
93+-- > NotFound <a>mappend</a> x = x
94+-- > WrongMethod <a>mappend</a> InvalidBody = InvalidBody
95+-- > WrongMethod <a>mappend</a> _ = WrongMethod
96+-- > InvalidBody <a>mappend</a> _ = InvalidBody
99+-- | A wrapper around <tt><a>Either</a> <a>RouteMismatch</a> a</tt>.
100+newtype RouteResult a
101+RR :: Either RouteMismatch a -> RouteResult a
102+routeResult :: RouteResult a -> Either RouteMismatch a
103+failWith :: RouteMismatch -> RouteResult a
104+succeedWith :: a -> RouteResult a
105+isMismatch :: RouteResult a -> Bool
107+-- | If we get a <a>Right</a>, it has precedence over everything else.
109+-- This in particular means that if we could get several <a>Right</a>s,
110+-- only the first we encounter would be taken into account.
111+type RoutingApplication = Request -> (RouteResult Response -> IO ResponseReceived) -> IO ResponseReceived
112+class HasServer layout where type family Server layout :: *
113+route :: HasServer layout => Proxy layout -> Server layout -> RoutingApplication
114+instance Eq RouteMismatch
115+instance Show RouteMismatch
116+instance Eq a => Eq (RouteResult a)
117+instance Show a => Show (RouteResult a)
118+instance Monoid (RouteResult a)
119+instance Monoid RouteMismatch
121+module Servant.API.Sub
123+-- | The contained API (second argument) can be found under <tt>("/" ++
124+-- path)</tt> (path being the first argument).
129+-- -- GET /hello/world
130+-- -- returning a JSON encoded World value
131+-- type MyApi = "hello" :> "world" :> Get World
133+data (:>) (path :: k) a
134+(:>) :: Proxy path -> a -> (:>) a
136+-- | Make sure the incoming request starts with <tt>"/path"</tt>, strip it
137+-- and pass the rest of the request path to <tt>sublayout</tt>.
138+instance (KnownSymbol path, HasServer sublayout) => HasServer (path :> sublayout)
140+module Servant.API.Alternative
142+-- | Union of two APIs, first takes precedence in case of overlap.
147+-- type MyApi = "books" :> Get [Book] -- GET /books
148+-- :<|> "books" :> ReqBody Book :> Post Book -- POST /books
151+(:<|>) :: a -> b -> (:<|>) a b
153+-- | A server for <tt>a <a>:<|></a> b</tt> first tries to match the
154+-- request again the route represented by <tt>a</tt> and if it fails
155+-- tries <tt>b</tt>. You must provide a request handler for each route.
158+-- type MyApi = "books" :> Get [Book] -- GET /books
159+-- :<|> "books" :> ReqBody Book :> Post Book -- POST /books
161+-- server :: Server MyApi
162+-- server = listAllBooks :<|> postBook
163+-- where listAllBooks = ...
164+-- postBook book = ...
166+instance (HasServer a, HasServer b) => HasServer (a :<|> b)
168+module Servant.API.Capture
170+-- | Capture a value from the request path under a certain type <tt>a</tt>.
175+-- -- GET /books/:isbn
176+-- type MyApi = "books" :> Capture "isbn" Text :> Get Book
179+instance (KnownSymbol capture, FromText a, HasServer sublayout) => HasServer (Capture capture a :> sublayout)
181+module Servant.API.QueryParam
183+-- | Lookup the value associated to the <tt>sym</tt> query string parameter
184+-- and try to extract it as a value of type <tt>a</tt>.
189+-- -- /books?author=<author name>
190+-- type MyApi = "books" :> QueryParam "author" Text :> Get [Book]
192+data QueryParam sym a
194+-- | If you use <tt><a>QueryParam</a> "author" Text</tt> in one of the
195+-- endpoints for your API, this automatically requires your server-side
196+-- handler to be a function that takes an argument of type
197+-- <tt><a>Maybe</a> <tt>Text</tt></tt>.
199+-- This lets servant worry about looking it up in the query string and
200+-- turning it into a value of the type you specify, enclosed in
201+-- <a>Maybe</a>, because it may not be there and servant would then hand
202+-- you <a>Nothing</a>.
204+-- You can control how it'll be converted from <tt>Text</tt> to your type
205+-- by simply providing an instance of <a>FromText</a> for your type.
210+-- type MyApi = "books" :> QueryParam "author" Text :> Get [Book]
212+-- server :: Server MyApi
213+-- server = getBooksBy
214+-- where getBooksBy :: Maybe Text -> EitherT (Int, String) IO [Book]
215+-- getBooksBy Nothing = ...return all books...
216+-- getBooksBy (Just author) = ...return books by the given author...
219+-- | Lookup the values associated to the <tt>sym</tt> query string
220+-- parameter and try to extract it as a value of type <tt>[a]</tt>. This
221+-- is typically meant to support query string parameters of the form
222+-- <tt>param[]=val1&param[]=val2</tt> and so on. Note that servant
223+-- doesn't actually require the <tt>[]</tt>s and will fetch the values
224+-- just fine with <tt>param=val1&param=val2</tt>, too.
229+-- -- /books?authors[]=<author1>&authors[]=<author2>&...
230+-- type MyApi = "books" :> QueryParams "authors" Text :> Get [Book]
232+data QueryParams sym a
234+-- | If you use <tt><a>QueryParams</a> "authors" Text</tt> in one of the
235+-- endpoints for your API, this automatically requires your server-side
236+-- handler to be a function that takes an argument of type
237+-- <tt>[<tt>Text</tt>]</tt>.
239+-- This lets servant worry about looking up 0 or more values in the query
240+-- string associated to <tt>authors</tt> and turning each of them into a
241+-- value of the type you specify.
243+-- You can control how the individual values are converted from
244+-- <tt>Text</tt> to your type by simply providing an instance of
245+-- <a>FromText</a> for your type.
250+-- type MyApi = "books" :> QueryParams "authors" Text :> Get [Book]
252+-- server :: Server MyApi
253+-- server = getBooksBy
254+-- where getBooksBy :: [Text] -> EitherT (Int, String) IO [Book]
255+-- getBooksBy authors = ...return all books by these authors...
258+-- | Lookup a potentially value-less query string parameter with boolean
259+-- semantics. If the param <tt>sym</tt> is there without any value, or if
260+-- it's there with value "true" or "1", it's interpreted as <a>True</a>.
261+-- Otherwise, it's interpreted as <a>False</a>.
266+-- -- /books?published
267+-- type MyApi = "books" :> QueryFlag "published" :> Get [Book]
271+-- | If you use <tt><a>QueryFlag</a> "published"</tt> in one of the
272+-- endpoints for your API, this automatically requires your server-side
273+-- handler to be a function that takes an argument of type <a>Bool</a>.
278+-- type MyApi = "books" :> QueryFlag "published" :> Get [Book]
280+-- server :: Server MyApi
282+-- where getBooks :: Bool -> EitherT (Int, String) IO [Book]
283+-- getBooks onlyPublished = ...return all books, or only the ones that are already published, depending on the argument...
285+instance (KnownSymbol sym, HasServer sublayout) => HasServer (QueryFlag sym :> sublayout)
286+instance (KnownSymbol sym, FromText a, HasServer sublayout) => HasServer (QueryParams sym a :> sublayout)
287+instance (KnownSymbol sym, FromText a, HasServer sublayout) => HasServer (QueryParam sym a :> sublayout)
289+module Servant.API.ReqBody
291+-- | Extract the request body as a value of type <tt>a</tt>.
297+-- type MyApi = "books" :> ReqBody Book :> Post Book
301+-- | If you use <a>ReqBody</a> in one of the endpoints for your API, this
302+-- automatically requires your server-side handler to be a function that
303+-- takes an argument of the type specified by <a>ReqBody</a>. This lets
304+-- servant worry about extracting it from the request and turning it into
305+-- a value of the type you specify.
307+-- All it asks is for a <a>FromJSON</a> instance.
312+-- type MyApi = "books" :> ReqBody Book :> Post Book
314+-- server :: Server MyApi
316+-- where postBook :: Book -> EitherT (Int, String) IO Book
317+-- postBook book = ...insert into your db...
319+instance (FromJSON a, HasServer sublayout) => HasServer (ReqBody a :> sublayout)
321+module Servant.API.Get
323+-- | Endpoint for simple GET requests. Serves the result as JSON.
328+-- type MyApi = "books" :> Get [Book]
332+-- | When implementing the handler for a <a>Get</a> endpoint, just like for
333+-- <a>Delete</a>, <a>Post</a> and <a>Put</a>, the handler code runs in
334+-- the <tt>EitherT (Int, String) IO</tt> monad, where the <a>Int</a>
335+-- represents the status code and the <a>String</a> a message, returned
336+-- in case of failure. You can quite handily use <a>left</a> to quickly
337+-- fail if some conditions are not met.
339+-- If successfully returning a value, we just require that its type has a
340+-- <a>ToJSON</a> instance and servant takes care of encoding it for you,
341+-- yielding status code 200 along the way.
342+instance Typeable Get
343+instance ToJSON result => HasServer (Get result)
345+module Servant.API.Post
347+-- | Endpoint for POST requests. The type variable represents the type of
348+-- the response body (not the request body, use <a>RQBody</a> for that).
354+-- -- with a JSON encoded Book as the request body
355+-- -- returning the just-created Book
356+-- type MyApi = "books" :> ReqBody Book :> Post Book
360+-- | When implementing the handler for a <a>Post</a> endpoint, just like
361+-- for <a>Delete</a>, <a>Get</a> and <a>Put</a>, the handler code runs in
362+-- the <tt>EitherT (Int, String) IO</tt> monad, where the <a>Int</a>
363+-- represents the status code and the <a>String</a> a message, returned
364+-- in case of failure. You can quite handily use <a>left</a> to quickly
365+-- fail if some conditions are not met.
367+-- If successfully returning a value, we just require that its type has a
368+-- <a>ToJSON</a> instance and servant takes care of encoding it for you,
369+-- yielding status code 201 along the way.
370+instance Typeable Post
371+instance ToJSON a => HasServer (Post a)
373+module Servant.API.Delete
375+-- | Combinator for DELETE requests.
380+-- -- DELETE /books/:isbn
381+-- type MyApi = "books" :> Capture "isbn" Text :> Delete
385+-- | If you have a <a>Delete</a> endpoint in your API, the handler for this
386+-- endpoint is meant to delete a resource.
388+-- The code of the handler will, just like for <a>Get</a>, <a>Post</a>
389+-- and <a>Put</a>, run in <tt>EitherT (Int, String) IO ()</tt>. The
390+-- <a>Int</a> represents the status code and the <a>String</a> a message
391+-- to be returned. You can use <a>left</a> to painlessly error out if the
392+-- conditions for a successful deletion are not met.
393+instance Typeable Delete
394+instance HasServer Delete
396+module Servant.API.Put
398+-- | Endpoint for PUT requests, usually used to update a ressource. The
399+-- type <tt>a</tt> is the type of the response body that's returned.
404+-- -- PUT /books/:isbn
405+-- -- with a Book as request body, returning the updated Book
406+-- type MyApi = "books" :> Capture "isbn" Text :> ReqBody Book :> Put Book
410+-- | When implementing the handler for a <a>Put</a> endpoint, just like for
411+-- <a>Delete</a>, <a>Get</a> and <a>Post</a>, the handler code runs in
412+-- the <tt>EitherT (Int, String) IO</tt> monad, where the <a>Int</a>
413+-- represents the status code and the <a>String</a> a message, returned
414+-- in case of failure. You can quite handily use <a>left</a> to quickly
415+-- fail if some conditions are not met.
417+-- If successfully returning a value, we just require that its type has a
418+-- <a>ToJSON</a> instance and servant takes care of encoding it for you,
419+-- yielding status code 200 along the way.
420+instance Typeable Put
421+instance ToJSON a => HasServer (Put a)
424+-- | QuasiQuoting utilities for API types.
426+-- <a>sitemap</a> allows you to write your type in a very natural way:
430+-- PUT hello String -> ()
431+-- POST hello/p:Int String -> ()
432+-- GET hello/?name:String Int
439+-- "hello" :> ReqBody String :> Put ()
440+-- :<|> "hello" :> Capture "p" Int :> ReqBody String :> Post ()
441+-- :<|> "hello" :> QueryParam "name" String :> Get Int
444+-- Note the <tt>/</tt> before a <tt>QueryParam</tt>!
447+-- | Finally-tagless encoding for our DSL. Keeping <tt>repr'</tt> and
448+-- <tt>repr</tt> distinct when writing functions with an <tt>ExpSYM</tt>
449+-- context ensures certain invariants (for instance, that there is only
450+-- one of <a>get</a>, <a>post</a>, <a>put</a>, and <a>delete</a> in a
451+-- value), but sometimes requires a little more work.
452+class ExpSYM repr' repr | repr -> repr', repr' -> repr
453+lit :: ExpSYM repr' repr => String -> repr' -> repr
454+capture :: ExpSYM repr' repr => String -> String -> repr -> repr
455+reqBody :: ExpSYM repr' repr => String -> repr -> repr
456+queryParam :: ExpSYM repr' repr => String -> String -> repr -> repr
457+conj :: ExpSYM repr' repr => repr' -> repr -> repr
458+get :: ExpSYM repr' repr => String -> repr
459+post :: ExpSYM repr' repr => String -> repr
460+put :: ExpSYM repr' repr => String -> repr
461+delete :: ExpSYM repr' repr => String -> repr
462+(>:) :: Type -> Type -> Type
463+parseMethod :: ExpSYM repr' repr => Parser (String -> repr)
464+parseUrlSegment :: ExpSYM repr repr => Parser (repr -> repr)
465+parseUrl :: ExpSYM repr repr => Parser (repr -> repr)
468+ReqArgVal :: String -> String -> Typ
469+parseTyp :: Parser Typ
470+parseEntry :: ExpSYM repr repr => Parser repr
471+blockComment :: Parser ()
472+inlineComment :: Parser ()
475+parseAll :: Parser Type
477+-- | The sitemap QuasiQuoter.
480+-- <li><tt>...<i><a>var</a>:<a>type</a></i>...</tt> becomes a
482+-- <li><tt>.../?<a>var</a>:<a>type</a></tt> becomes a query
484+-- <li><tt><a>method</a> ... <a>typ</a></tt> becomes a method returning
485+-- <tt><a>typ</a></tt></li>
486+-- <li><tt><a>method</a> ... <a>typ1</a> -> <a>typ2</a></tt> becomes a
487+-- method with request body of <tt><a>typ1</a></tt> and returning
488+-- <tt><a>typ2</a></tt></li>
491+-- Comments are allowed, and have the standard Haskell format
494+-- <li><tt>--</tt> for inline</li>
495+-- <li><tt>{- ... -}</tt> for block</li>
497+sitemap :: QuasiQuoter
498+instance ExpSYM Type Type
501+-- | Type safe internal links.
503+-- Provides the function <a>mkLink</a>:
506+-- type API = Proxy ("hello" :> Get Int
507+-- :<a>|</a> "bye" :> QueryParam "name" String :> Post Bool)
512+-- link1 :: Proxy ("hello" :> Get Int)
515+-- link2 :: Proxy ("hello" :> Delete)
518+-- mkLink link1 API -- typechecks, returns 'Link "/hello"'
520+-- mkLink link2 API -- doesn't typecheck
523+-- That is, <a>mkLink</a> takes two arguments, a link proxy and a
524+-- sitemap, and returns a <a>Link</a>, but only typechecks if the link
525+-- proxy is a valid link, and part of the sitemap.
527+-- <b>N.B.:</b> <a>mkLink</a> assumes a capture matches any string
528+-- (without slashes).
529+module Servant.Utils.Links
531+-- | The 'ValidLinkIn f s' constraint holds when <tt>s</tt> is an API that
532+-- contains <tt>f</tt>, and <tt>f</tt> is a link.
533+class ValidLinkIn f s
534+mkLink :: ValidLinkIn f s => f -> s -> Link
536+Link :: String -> Link
538+vlh :: VLinkHelper f => proxy f -> String
540+instance VLinkHelper (Post x)
541+instance VLinkHelper (Get x)
542+instance (KnownSymbol s, VLinkHelper e) => VLinkHelper (s :> e)
543+instance (IsElem f s ~ 'True, IsLink f ~ 'True, VLinkHelper f) => ValidLinkIn f s
545+module Servant.API.Raw
547+-- | Endpoint for plugging in your own Wai <a>Application</a>s.
549+-- The given <a>Application</a> will get the request as received by the
550+-- server, potentially with a modified (stripped) <a>pathInfo</a> if the
551+-- <a>Application</a> is being routed with <a>:></a>.
553+-- In addition to just letting you plug in your existing WAI
554+-- <a>Application</a>s, this can also be used with <a>serveDirectory</a>
555+-- to serve static files stored in a particular directory on your
556+-- filesystem, or to serve your API's documentation with
557+-- <a>serveDocumentation</a>.
560+-- | Just pass the request to the underlying application and serve its
566+-- type MyApi = "images" :> Raw
568+-- server :: Server MyApi
569+-- server = serveDirectory "/var/www/images"
571+instance HasServer Raw
574+-- | This module defines a sever-side handler that lets you serve static
578+-- <li><a>serveDirectory</a> lets you serve anything that lives under a
579+-- particular directory on your filesystem.</li>
581+module Servant.Utils.StaticFiles
583+-- | Serve anything under the specified directory as a <a>Raw</a> endpoint.
586+-- type MyApi = "static" :> Raw
588+-- server :: Server MyApi
589+-- server = serveDirectory "/var/www"
592+-- would capture any request to <tt>/static/<something></tt> and
593+-- look for <tt><something></tt> under <tt>/var/www</tt>.
595+-- It will do its best to guess the MIME type for that file, based on the
596+-- extension, and send an appropriate <i>Content-Type</i> header if
599+-- If your goal is to serve HTML, CSS and Javascript files that use the
600+-- rest of the API as a webapp backend, you will most likely not want the
601+-- static files to be hidden behind a <i>/static/</i> prefix. In that
602+-- case, remember to put the <a>serveDirectory</a> handler in the last
603+-- position, because <i>servant</i> will try to match the handlers in
605+serveDirectory :: FilePath -> Server Raw
611+-- | A concrete, poly-kinded proxy type
612+data Proxy (t :: k) :: k -> *