git.iko.soy/typeable/servant
on 63563ca help sign in
94 files changed+3467−2052
since splitsnapshots
unifiedsplit
.ghci−1 .travis.yml−12 LICENSE−30 Servant-API-Alternative.html+13 Servant-API-Capture.html+15 Servant-API-Delete.html+13 Servant-API-Get.html+12 Servant-API-Post.html+17 Servant-API-Put.html+15 Servant-API-QueryParam.html+45 Servant-API-Raw.html+11 Servant-API-ReqBody.html+14 Servant-API-Sub.html+56 Servant-API.html+4 Servant-Common-Text.html+7 Servant-QQ.html+17 Servant-Server.html+116 Servant-Utils-Links.html+23 Servant-Utils-StaticFiles.html+15 Servant.html+6 Setup.hs−2 doc-index.html+4 example/README.md−2 example/greet.hs−72 example/greet.md−52 frames.html+30 haddock-util.js+344 hslogo-16.png index-frames.html+4 index.html+4 mini_Servant-API-Alternative.html+4 mini_Servant-API-Capture.html+4 mini_Servant-API-Delete.html+4 mini_Servant-API-Get.html+4 mini_Servant-API-Post.html+4 mini_Servant-API-Put.html+4 mini_Servant-API-QueryParam.html+4 mini_Servant-API-Raw.html+4 mini_Servant-API-ReqBody.html+4 mini_Servant-API-Sub.html+4 mini_Servant-API.html+4 mini_Servant-Common-Text.html+4 mini_Servant-QQ.html+4 mini_Servant-Server.html+4 mini_Servant-Utils-Links.html+4 mini_Servant-Utils-StaticFiles.html+4 mini_Servant.html+4 minus.gif ocean.css+577 plus.gif servant.cabal−97 servant.haddock servant.txt+613 src/Servant-API-Alternative.html+50 src/Servant-API-Capture.html+71 src/Servant-API-Delete.html+59 src/Servant-API-Get.html+58 src/Servant-API-Post.html+64 src/Servant-API-Put.html+63 src/Servant-API-QueryParam.html+173 src/Servant-API-Raw.html+43 src/Servant-API-ReqBody.html+60 src/Servant-API-Sub.html+47 src/Servant-API.html+62 src/Servant-Common-Text.html+141 src/Servant-QQ.html+209 src/Servant-Server.html+116 src/Servant-Utils-Links.html+121 src/Servant-Utils-StaticFiles.html+47 src/Servant.hs−24 src/Servant.html+35 src/Servant/API.hs−51 src/Servant/API/Alternative.hs−39 src/Servant/API/Capture.hs−60 src/Servant/API/Delete.hs−48 src/Servant/API/Get.hs−47 src/Servant/API/Post.hs−53 src/Servant/API/Put.hs−52 src/Servant/API/QueryParam.hs−162 src/Servant/API/Raw.hs−32 src/Servant/API/ReqBody.hs−49 src/Servant/API/Sub.hs−36 src/Servant/Common/Text.hs−130 src/Servant/QQ.hs−198 src/Servant/Server.hs−105 src/Servant/Utils/Links.hs−110 src/Servant/Utils/StaticFiles.hs−36 src/hscolour.css+5 synopsis.png test/Servant/QQSpec.hs−177 test/Servant/ServerSpec.hs−258 test/Servant/Utils/LinksSpec.hs−52 test/Servant/Utils/StaticFilesSpec.hs−64 test/Spec.hs−1
.ghcideleted−1
@@ -1 +0,0 @@
1−:set -itest -isrc -packagehspec2
.travis.ymldeleted−12
@@ -1,12 +0,0 @@
1−language: haskell
2−
3−notifications:
4− irc:
5− channels:
6− - "irc.freenode.org#servant"
7− template:
8− - "%{repository}#%{build_number} - %{commit} on %{branch} by %{author}: %{message}"
9− - "Build details: %{build_url} - Change view: %{compare_url}"
10− skip_join: true
11− on_success: change
12− on_failure: always
LICENSEdeleted−30
@@ -1,30 +0,0 @@
1−Copyright (c) 2014, Zalora South East Asia Pte Ltd
2−
3−All rights reserved.
4−
5−Redistribution and use in source and binary forms, with or without
6−modification, are permitted provided that the following conditions are met:
7−
8− * Redistributions of source code must retain the above copyright
9− notice, this list of conditions and the following disclaimer.
10−
11− * Redistributions in binary form must reproduce the above
12− copyright notice, this list of conditions and the following
13− disclaimer in the documentation and/or other materials provided
14− with the distribution.
15−
16− * Neither the name of Zalora South East Asia Pte Ltd nor the names of other
17− contributors may be used to endorse or promote products derived
18− from this software without specific prior written permission.
19−
20−THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21−"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22−LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23−A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24−OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25−SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26−LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27−DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28−THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29−(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30−OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Servant-API-Alternative.htmlnew file+13
@@ -0,0 +1,13 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.API.Alternative</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();setSynopsis("mini_Servant-API-Alternative.html");};
3+//]]>
4+</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="src/Servant-API-Alternative.html">Source</a></li><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">servant-0.2: A family of combinators for defining webservices APIs and serving them</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr><tr><th>Language</th><td>Haskell2010</td></tr></table><p class="caption">Servant.API.Alternative</p></div><div id="synopsis"><p id="control.syn" class="caption expander" onclick="toggleSection('syn')">Synopsis</p><ul id="section.syn" class="hide" onclick="toggleSection('syn')"><li class="src short"><span class="keyword">data</span> a <a href="#t::-60--124--62-">:&lt;|&gt;</a> b = a <a href="#v::-60--124--62-">:&lt;|&gt;</a> b</li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><span class="keyword">data</span> a <a name="t::-60--124--62-" class="def">:&lt;|&gt;</a> b <span class="fixity">infixr 8</span><span class="rightedge"></span> <a href="src/Servant-API-Alternative.html#%3A%3C%7C%3E" class="link">Source</a></p><div class="doc"><p>Union of two APIs, first takes precedence in case of overlap.</p><p>Example:</p><pre>type MyApi = &quot;books&quot; :&gt; Get [Book] -- GET /books
5+ :&lt;|&gt; &quot;books&quot; :&gt; ReqBody Book :&gt; Post Book -- POST /books</pre></div><div class="subs constructors"><p class="caption">Constructors</p><table><tr><td class="src">a <a name="v::-60--124--62-" class="def">:&lt;|&gt;</a> b <span class="fixity">infixr 8</span><span class="rightedge"></span></td><td class="doc empty">&nbsp;</td></tr></table></div><div class="subs instances"><p id="control.i::-60--124--62-" class="caption collapser" onclick="toggleSection('i::-60--124--62-')">Instances</p><div id="section.i::-60--124--62-" class="show"><table><tr><td class="src">(<a href="Servant-Server.html#t:HasServer">HasServer</a> a, <a href="Servant-Server.html#t:HasServer">HasServer</a> b) =&gt; <a href="Servant-Server.html#t:HasServer">HasServer</a> (<a href="Servant-API-Alternative.html#t::-60--124--62-">(:&lt;|&gt;)</a> a b)</td><td class="doc"><p>A server for <code>a <code><a href="Servant-API-Alternative.html#t::-60--124--62-">:&lt;|&gt;</a></code> b</code> first tries to match the request again the route
6+ represented by <code>a</code> and if it fails tries <code>b</code>. You must provide a request
7+ handler for each route.</p><pre>type MyApi = &quot;books&quot; :&gt; Get [Book] -- GET /books
8+ :&lt;|&gt; &quot;books&quot; :&gt; ReqBody Book :&gt; Post Book -- POST /books
9+
10+server :: Server MyApi
11+server = listAllBooks :&lt;|&gt; postBook
12+ where listAllBooks = ...
13+ postBook book = ...</pre></td></tr><tr><td class="src"><span class="keyword">type</span> <a href="Servant-Server.html#t:Server">Server</a> (<a href="Servant-API-Alternative.html#t::-60--124--62-">(:&lt;|&gt;)</a> a b) = <a href="Servant-API-Alternative.html#t::-60--124--62-">(:&lt;|&gt;)</a> (<a href="Servant-Server.html#t:Server">Server</a> a) (<a href="Servant-Server.html#t:Server">Server</a> b)</td><td class="doc empty">&nbsp;</td></tr></table></div></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.15.0</p></div></body></html>
Servant-API-Capture.htmlnew file+15
@@ -0,0 +1,15 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.API.Capture</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();setSynopsis("mini_Servant-API-Capture.html");};
3+//]]>
4+</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="src/Servant-API-Capture.html">Source</a></li><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">servant-0.2: A family of combinators for defining webservices APIs and serving them</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr><tr><th>Language</th><td>Haskell2010</td></tr></table><p class="caption">Servant.API.Capture</p></div><div id="synopsis"><p id="control.syn" class="caption expander" onclick="toggleSection('syn')">Synopsis</p><ul id="section.syn" class="hide" onclick="toggleSection('syn')"><li class="src short"><span class="keyword">data</span> <a href="#t:Capture">Capture</a> sym a</li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><span class="keyword">data</span> <a name="t:Capture" class="def">Capture</a> sym a <a href="src/Servant-API-Capture.html#Capture" class="link">Source</a></p><div class="doc"><p>Capture a value from the request path under a certain type <code>a</code>.</p><p>Example:</p><pre> -- GET /books/:isbn
5+type MyApi = &quot;books&quot; :&gt; Capture &quot;isbn&quot; Text :&gt; Get Book</pre></div><div class="subs instances"><p id="control.i:Capture" class="caption collapser" onclick="toggleSection('i:Capture')">Instances</p><div id="section.i:Capture" class="show"><table><tr><td class="src">(<a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:KnownSymbol">KnownSymbol</a> capture, <a href="Servant-Common-Text.html#t:FromText">FromText</a> a, <a href="Servant-Server.html#t:HasServer">HasServer</a> sublayout) =&gt; <a href="Servant-Server.html#t:HasServer">HasServer</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> * (<a href="Servant-API-Capture.html#t:Capture">Capture</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a> * capture a) sublayout)</td><td class="doc"><p>If you use <code><a href="Servant-API-Capture.html#t:Capture">Capture</a></code> in one of the endpoints for your API,
6+ this automatically requires your server-side handler to be a function
7+ that takes an argument of the type specified by the <code><a href="Servant-API-Capture.html#t:Capture">Capture</a></code>.
8+ This lets servant worry about getting it from the URL and turning
9+ it into a value of the type you specify.</p><p>You can control how it'll be converted from <code><a href="https://hackage.haskell.org/package/text-1.2.0.0/docs/Data-Text.html#t:Text">Text</a></code> to your type
10+ by simply providing an instance of <code><a href="Servant-Common-Text.html#t:FromText">FromText</a></code> for your type.</p><p>Example:</p><pre>type MyApi = &quot;books&quot; :&gt; Capture &quot;isbn&quot; Text :&gt; Get Book
11+
12+server :: Server MyApi
13+server = getBook
14+ where getBook :: Text -&gt; EitherT (Int, String) IO Book
15+ getBook isbn = ...</pre></td></tr><tr><td class="src"><span class="keyword">type</span> <a href="Servant-Server.html#t:Server">Server</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> * (<a href="Servant-API-Capture.html#t:Capture">Capture</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a> * capture a) sublayout) = a -&gt; <a href="Servant-Server.html#t:Server">Server</a> sublayout</td><td class="doc empty">&nbsp;</td></tr></table></div></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.15.0</p></div></body></html>
Servant-API-Delete.htmlnew file+13
@@ -0,0 +1,13 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.API.Delete</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();setSynopsis("mini_Servant-API-Delete.html");};
3+//]]>
4+</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="src/Servant-API-Delete.html">Source</a></li><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">servant-0.2: A family of combinators for defining webservices APIs and serving them</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr><tr><th>Language</th><td>Haskell2010</td></tr></table><p class="caption">Servant.API.Delete</p></div><div id="synopsis"><p id="control.syn" class="caption expander" onclick="toggleSection('syn')">Synopsis</p><ul id="section.syn" class="hide" onclick="toggleSection('syn')"><li class="src short"><span class="keyword">data</span> <a href="#t:Delete">Delete</a></li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><span class="keyword">data</span> <a name="t:Delete" class="def">Delete</a> <a href="src/Servant-API-Delete.html#Delete" class="link">Source</a></p><div class="doc"><p>Combinator for DELETE requests.</p><p>Example:</p><pre> -- DELETE /books/:isbn
5+type MyApi = &quot;books&quot; :&gt; Capture &quot;isbn&quot; Text :&gt; Delete</pre></div><div class="subs instances"><p id="control.i:Delete" class="caption collapser" onclick="toggleSection('i:Delete')">Instances</p><div id="section.i:Delete" class="show"><table><tr><td class="src"><a href="Servant-Server.html#t:HasServer">HasServer</a> <a href="Servant-API-Delete.html#t:Delete">Delete</a></td><td class="doc"><p>If you have a <code><a href="Servant-API-Delete.html#t:Delete">Delete</a></code> endpoint in your API,
6+ the handler for this endpoint is meant to delete
7+ a resource.</p><p>The code of the handler will, just like
8+ for <code><a href="Servant-API-Get.html#t:Get">Get</a></code>, <code><a href="Servant-API-Post.html#t:Post">Post</a></code> and
9+ <code><a href="Servant-API-Put.html#t:Put">Put</a></code>, run in <code>EitherT (Int, String) IO ()</code>.
10+ The <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Int.html#t:Int">Int</a></code> represents the status code and the <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a></code> a message
11+ to be returned. You can use <code><a href="https://hackage.haskell.org/package/either-4.3.2/docs/Control-Monad-Trans-Either.html#v:left">left</a></code> to
12+ painlessly error out if the conditions for a successful deletion
13+ are not met.</p></td></tr><tr><td class="src"><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Typeable-Internal.html#t:Typeable">Typeable</a> * <a href="Servant-API-Delete.html#t:Delete">Delete</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><span class="keyword">type</span> <a href="Servant-Server.html#t:Server">Server</a> <a href="Servant-API-Delete.html#t:Delete">Delete</a> = <a href="https://hackage.haskell.org/package/either-4.3.2/docs/Control-Monad-Trans-Either.html#t:EitherT">EitherT</a> (<a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Int.html#t:Int">Int</a>, <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a>) <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/System-IO.html#t:IO">IO</a> ()</td><td class="doc empty">&nbsp;</td></tr></table></div></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.15.0</p></div></body></html>
Servant-API-Get.htmlnew file+12
@@ -0,0 +1,12 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.API.Get</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();setSynopsis("mini_Servant-API-Get.html");};
3+//]]>
4+</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="src/Servant-API-Get.html">Source</a></li><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">servant-0.2: A family of combinators for defining webservices APIs and serving them</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr><tr><th>Language</th><td>Haskell2010</td></tr></table><p class="caption">Servant.API.Get</p></div><div id="synopsis"><p id="control.syn" class="caption expander" onclick="toggleSection('syn')">Synopsis</p><ul id="section.syn" class="hide" onclick="toggleSection('syn')"><li class="src short"><span class="keyword">data</span> <a href="#t:Get">Get</a> a</li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><span class="keyword">data</span> <a name="t:Get" class="def">Get</a> a <a href="src/Servant-API-Get.html#Get" class="link">Source</a></p><div class="doc"><p>Endpoint for simple GET requests. Serves the result as JSON.</p><p>Example:</p><pre>type MyApi = &quot;books&quot; :&gt; Get [Book]</pre></div><div class="subs instances"><p id="control.i:Get" class="caption collapser" onclick="toggleSection('i:Get')">Instances</p><div id="section.i:Get" class="show"><table><tr><td class="src"><a href="Servant-Utils-Links.html#t:VLinkHelper">VLinkHelper</a> * (<a href="Servant-API-Get.html#t:Get">Get</a> x)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="https://hackage.haskell.org/package/aeson-0.8.0.2/docs/Data-Aeson-Types.html#t:ToJSON">ToJSON</a> result =&gt; <a href="Servant-Server.html#t:HasServer">HasServer</a> (<a href="Servant-API-Get.html#t:Get">Get</a> result)</td><td class="doc"><p>When implementing the handler for a <code><a href="Servant-API-Get.html#t:Get">Get</a></code> endpoint,
5+ just like for <code><a href="Servant-API-Delete.html#t:Delete">Delete</a></code>, <code><a href="Servant-API-Post.html#t:Post">Post</a></code>
6+ and <code><a href="Servant-API-Put.html#t:Put">Put</a></code>, the handler code runs in the
7+ <code>EitherT (Int, String) IO</code> monad, where the <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Int.html#t:Int">Int</a></code> represents
8+ the status code and the <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a></code> a message, returned in case of
9+ failure. You can quite handily use <code><a href="Control-Monad-Trans-EitherT.html#v:left">left</a></code>
10+ to quickly fail if some conditions are not met.</p><p>If successfully returning a value, we just require that its type has
11+ a <code><a href="https://hackage.haskell.org/package/aeson-0.8.0.2/docs/Data-Aeson-Types.html#t:ToJSON">ToJSON</a></code> instance and servant takes care of encoding it for you,
12+ yielding status code 200 along the way.</p></td></tr><tr><td class="src"><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Typeable-Internal.html#t:Typeable">Typeable</a> (* -&gt; *) <a href="Servant-API-Get.html#t:Get">Get</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><span class="keyword">type</span> <a href="Servant-Server.html#t:Server">Server</a> (<a href="Servant-API-Get.html#t:Get">Get</a> result) = <a href="https://hackage.haskell.org/package/either-4.3.2/docs/Control-Monad-Trans-Either.html#t:EitherT">EitherT</a> (<a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Int.html#t:Int">Int</a>, <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a>) <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/System-IO.html#t:IO">IO</a> result</td><td class="doc empty">&nbsp;</td></tr></table></div></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.15.0</p></div></body></html>
Servant-API-Post.htmlnew file+17
@@ -0,0 +1,17 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.API.Post</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();setSynopsis("mini_Servant-API-Post.html");};
3+//]]>
4+</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="src/Servant-API-Post.html">Source</a></li><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">servant-0.2: A family of combinators for defining webservices APIs and serving them</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr><tr><th>Language</th><td>Haskell2010</td></tr></table><p class="caption">Servant.API.Post</p></div><div id="synopsis"><p id="control.syn" class="caption expander" onclick="toggleSection('syn')">Synopsis</p><ul id="section.syn" class="hide" onclick="toggleSection('syn')"><li class="src short"><span class="keyword">data</span> <a href="#t:Post">Post</a> a</li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><span class="keyword">data</span> <a name="t:Post" class="def">Post</a> a <a href="src/Servant-API-Post.html#Post" class="link">Source</a></p><div class="doc"><p>Endpoint for POST requests. The type variable represents the type of the
5+ response body (not the request body, use <code><a href="Servant-API-RQBody.html#t:RQBody">RQBody</a></code> for
6+ that).</p><p>Example:</p><pre> -- POST /books
7+ -- with a JSON encoded Book as the request body
8+ -- returning the just-created Book
9+type MyApi = &quot;books&quot; :&gt; ReqBody Book :&gt; Post Book</pre></div><div class="subs instances"><p id="control.i:Post" class="caption collapser" onclick="toggleSection('i:Post')">Instances</p><div id="section.i:Post" class="show"><table><tr><td class="src"><a href="Servant-Utils-Links.html#t:VLinkHelper">VLinkHelper</a> * (<a href="Servant-API-Post.html#t:Post">Post</a> x)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="https://hackage.haskell.org/package/aeson-0.8.0.2/docs/Data-Aeson-Types.html#t:ToJSON">ToJSON</a> a =&gt; <a href="Servant-Server.html#t:HasServer">HasServer</a> (<a href="Servant-API-Post.html#t:Post">Post</a> a)</td><td class="doc"><p>When implementing the handler for a <code><a href="Servant-API-Post.html#t:Post">Post</a></code> endpoint,
10+ just like for <code><a href="Servant-API-Delete.html#t:Delete">Delete</a></code>, <code><a href="Servant-API-Get.html#t:Get">Get</a></code>
11+ and <code><a href="Servant-API-Put.html#t:Put">Put</a></code>, the handler code runs in the
12+ <code>EitherT (Int, String) IO</code> monad, where the <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Int.html#t:Int">Int</a></code> represents
13+ the status code and the <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a></code> a message, returned in case of
14+ failure. You can quite handily use <code><a href="Control-Monad-Trans-EitherT.html#v:left">left</a></code>
15+ to quickly fail if some conditions are not met.</p><p>If successfully returning a value, we just require that its type has
16+ a <code><a href="https://hackage.haskell.org/package/aeson-0.8.0.2/docs/Data-Aeson-Types.html#t:ToJSON">ToJSON</a></code> instance and servant takes care of encoding it for you,
17+ yielding status code 201 along the way.</p></td></tr><tr><td class="src"><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Typeable-Internal.html#t:Typeable">Typeable</a> (* -&gt; *) <a href="Servant-API-Post.html#t:Post">Post</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><span class="keyword">type</span> <a href="Servant-Server.html#t:Server">Server</a> (<a href="Servant-API-Post.html#t:Post">Post</a> a) = <a href="https://hackage.haskell.org/package/either-4.3.2/docs/Control-Monad-Trans-Either.html#t:EitherT">EitherT</a> (<a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Int.html#t:Int">Int</a>, <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a>) <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/System-IO.html#t:IO">IO</a> a</td><td class="doc empty">&nbsp;</td></tr></table></div></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.15.0</p></div></body></html>
Servant-API-Put.htmlnew file+15
@@ -0,0 +1,15 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.API.Put</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();setSynopsis("mini_Servant-API-Put.html");};
3+//]]>
4+</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="src/Servant-API-Put.html">Source</a></li><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">servant-0.2: A family of combinators for defining webservices APIs and serving them</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr><tr><th>Language</th><td>Haskell2010</td></tr></table><p class="caption">Servant.API.Put</p></div><div id="synopsis"><p id="control.syn" class="caption expander" onclick="toggleSection('syn')">Synopsis</p><ul id="section.syn" class="hide" onclick="toggleSection('syn')"><li class="src short"><span class="keyword">data</span> <a href="#t:Put">Put</a> a</li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><span class="keyword">data</span> <a name="t:Put" class="def">Put</a> a <a href="src/Servant-API-Put.html#Put" class="link">Source</a></p><div class="doc"><p>Endpoint for PUT requests, usually used to update a ressource.
5+ The type <code>a</code> is the type of the response body that's returned.</p><p>Example:</p><pre>-- PUT /books/:isbn
6+-- with a Book as request body, returning the updated Book
7+type MyApi = &quot;books&quot; :&gt; Capture &quot;isbn&quot; Text :&gt; ReqBody Book :&gt; Put Book</pre></div><div class="subs instances"><p id="control.i:Put" class="caption collapser" onclick="toggleSection('i:Put')">Instances</p><div id="section.i:Put" class="show"><table><tr><td class="src"><a href="https://hackage.haskell.org/package/aeson-0.8.0.2/docs/Data-Aeson-Types.html#t:ToJSON">ToJSON</a> a =&gt; <a href="Servant-Server.html#t:HasServer">HasServer</a> (<a href="Servant-API-Put.html#t:Put">Put</a> a)</td><td class="doc"><p>When implementing the handler for a <code><a href="Servant-API-Put.html#t:Put">Put</a></code> endpoint,
8+ just like for <code><a href="Servant-API-Delete.html#t:Delete">Delete</a></code>, <code><a href="Servant-API-Get.html#t:Get">Get</a></code>
9+ and <code><a href="Servant-API-Post.html#t:Post">Post</a></code>, the handler code runs in the
10+ <code>EitherT (Int, String) IO</code> monad, where the <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Int.html#t:Int">Int</a></code> represents
11+ the status code and the <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a></code> a message, returned in case of
12+ failure. You can quite handily use <code><a href="Control-Monad-Trans-EitherT.html#v:left">left</a></code>
13+ to quickly fail if some conditions are not met.</p><p>If successfully returning a value, we just require that its type has
14+ a <code><a href="https://hackage.haskell.org/package/aeson-0.8.0.2/docs/Data-Aeson-Types.html#t:ToJSON">ToJSON</a></code> instance and servant takes care of encoding it for you,
15+ yielding status code 200 along the way.</p></td></tr><tr><td class="src"><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Typeable-Internal.html#t:Typeable">Typeable</a> (* -&gt; *) <a href="Servant-API-Put.html#t:Put">Put</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><span class="keyword">type</span> <a href="Servant-Server.html#t:Server">Server</a> (<a href="Servant-API-Put.html#t:Put">Put</a> a) = <a href="https://hackage.haskell.org/package/either-4.3.2/docs/Control-Monad-Trans-Either.html#t:EitherT">EitherT</a> (<a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Int.html#t:Int">Int</a>, <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a>) <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/System-IO.html#t:IO">IO</a> a</td><td class="doc empty">&nbsp;</td></tr></table></div></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.15.0</p></div></body></html>
Servant-API-QueryParam.htmlnew file+45
@@ -0,0 +1,45 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.API.QueryParam</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();setSynopsis("mini_Servant-API-QueryParam.html");};
3+//]]>
4+</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="src/Servant-API-QueryParam.html">Source</a></li><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">servant-0.2: A family of combinators for defining webservices APIs and serving them</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr><tr><th>Language</th><td>Haskell2010</td></tr></table><p class="caption">Servant.API.QueryParam</p></div><div id="synopsis"><p id="control.syn" class="caption expander" onclick="toggleSection('syn')">Synopsis</p><ul id="section.syn" class="hide" onclick="toggleSection('syn')"><li class="src short"><span class="keyword">data</span> <a href="#t:QueryParam">QueryParam</a> sym a</li><li class="src short"><span class="keyword">data</span> <a href="#t:QueryParams">QueryParams</a> sym a</li><li class="src short"><span class="keyword">data</span> <a href="#t:QueryFlag">QueryFlag</a> sym</li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><span class="keyword">data</span> <a name="t:QueryParam" class="def">QueryParam</a> sym a <a href="src/Servant-API-QueryParam.html#QueryParam" class="link">Source</a></p><div class="doc"><p>Lookup the value associated to the <code>sym</code> query string parameter
5+ and try to extract it as a value of type <code>a</code>.</p><p>Example:</p><pre>-- /books?author=&lt;author name&gt;
6+type MyApi = &quot;books&quot; :&gt; QueryParam &quot;author&quot; Text :&gt; Get [Book]</pre></div><div class="subs instances"><p id="control.i:QueryParam" class="caption collapser" onclick="toggleSection('i:QueryParam')">Instances</p><div id="section.i:QueryParam" class="show"><table><tr><td class="src">(<a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:KnownSymbol">KnownSymbol</a> sym, <a href="Servant-Common-Text.html#t:FromText">FromText</a> a, <a href="Servant-Server.html#t:HasServer">HasServer</a> sublayout) =&gt; <a href="Servant-Server.html#t:HasServer">HasServer</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> * (<a href="Servant-API-QueryParam.html#t:QueryParam">QueryParam</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a> * sym a) sublayout)</td><td class="doc"><p>If you use <code><code><a href="Servant-API-QueryParam.html#t:QueryParam">QueryParam</a></code> &quot;author&quot; Text</code> in one of the endpoints for your API,
7+ this automatically requires your server-side handler to be a function
8+ that takes an argument of type <code><code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Maybe.html#t:Maybe">Maybe</a></code> <code>Text</code></code>.</p><p>This lets servant worry about looking it up in the query string
9+ and turning it into a value of the type you specify, enclosed
10+ in <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Maybe.html#t:Maybe">Maybe</a></code>, because it may not be there and servant would then
11+ hand you <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Maybe.html#v:Nothing">Nothing</a></code>.</p><p>You can control how it'll be converted from <code>Text</code> to your type
12+ by simply providing an instance of <code><a href="Servant-Common-Text.html#t:FromText">FromText</a></code> for your type.</p><p>Example:</p><pre>type MyApi = &quot;books&quot; :&gt; QueryParam &quot;author&quot; Text :&gt; Get [Book]
13+
14+server :: Server MyApi
15+server = getBooksBy
16+ where getBooksBy :: Maybe Text -&gt; EitherT (Int, String) IO [Book]
17+ getBooksBy Nothing = ...return all books...
18+ getBooksBy (Just author) = ...return books by the given author...</pre></td></tr><tr><td class="src"><span class="keyword">type</span> <a href="Servant-Server.html#t:Server">Server</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> * (<a href="Servant-API-QueryParam.html#t:QueryParam">QueryParam</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a> * sym a) sublayout) = <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Maybe.html#t:Maybe">Maybe</a> a -&gt; <a href="Servant-Server.html#t:Server">Server</a> sublayout</td><td class="doc empty">&nbsp;</td></tr></table></div></div></div><div class="top"><p class="src"><span class="keyword">data</span> <a name="t:QueryParams" class="def">QueryParams</a> sym a <a href="src/Servant-API-QueryParam.html#QueryParams" class="link">Source</a></p><div class="doc"><p>Lookup the values associated to the <code>sym</code> query string parameter
19+ and try to extract it as a value of type <code>[a]</code>. This is typically
20+ meant to support query string parameters of the form
21+ <code>param[]=val1&amp;param[]=val2</code> and so on. Note that servant doesn't actually
22+ require the <code>[]</code>s and will fetch the values just fine with
23+ <code>param=val1&amp;param=val2</code>, too.</p><p>Example:</p><pre>-- /books?authors[]=&lt;author1&gt;&amp;authors[]=&lt;author2&gt;&amp;...
24+type MyApi = &quot;books&quot; :&gt; QueryParams &quot;authors&quot; Text :&gt; Get [Book]</pre></div><div class="subs instances"><p id="control.i:QueryParams" class="caption collapser" onclick="toggleSection('i:QueryParams')">Instances</p><div id="section.i:QueryParams" class="show"><table><tr><td class="src">(<a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:KnownSymbol">KnownSymbol</a> sym, <a href="Servant-Common-Text.html#t:FromText">FromText</a> a, <a href="Servant-Server.html#t:HasServer">HasServer</a> sublayout) =&gt; <a href="Servant-Server.html#t:HasServer">HasServer</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> * (<a href="Servant-API-QueryParam.html#t:QueryParams">QueryParams</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a> * sym a) sublayout)</td><td class="doc"><p>If you use <code><code><a href="Servant-API-QueryParam.html#t:QueryParams">QueryParams</a></code> &quot;authors&quot; Text</code> in one of the endpoints for your API,
25+ this automatically requires your server-side handler to be a function
26+ that takes an argument of type <code>[<code>Text</code>]</code>.</p><p>This lets servant worry about looking up 0 or more values in the query string
27+ associated to <code>authors</code> and turning each of them into a value of
28+ the type you specify.</p><p>You can control how the individual values are converted from <code>Text</code> to your type
29+ by simply providing an instance of <code><a href="Servant-Common-Text.html#t:FromText">FromText</a></code> for your type.</p><p>Example:</p><pre>type MyApi = &quot;books&quot; :&gt; QueryParams &quot;authors&quot; Text :&gt; Get [Book]
30+
31+server :: Server MyApi
32+server = getBooksBy
33+ where getBooksBy :: [Text] -&gt; EitherT (Int, String) IO [Book]
34+ getBooksBy authors = ...return all books by these authors...</pre></td></tr><tr><td class="src"><span class="keyword">type</span> <a href="Servant-Server.html#t:Server">Server</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> * (<a href="Servant-API-QueryParam.html#t:QueryParams">QueryParams</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a> * sym a) sublayout) = [a] -&gt; <a href="Servant-Server.html#t:Server">Server</a> sublayout</td><td class="doc empty">&nbsp;</td></tr></table></div></div></div><div class="top"><p class="src"><span class="keyword">data</span> <a name="t:QueryFlag" class="def">QueryFlag</a> sym <a href="src/Servant-API-QueryParam.html#QueryFlag" class="link">Source</a></p><div class="doc"><p>Lookup a potentially value-less query string parameter
35+ with boolean semantics. If the param <code>sym</code> is there without any value,
36+ or if it's there with value &quot;true&quot; or &quot;1&quot;, it's interpreted as <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#v:True">True</a></code>.
37+ Otherwise, it's interpreted as <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#v:False">False</a></code>.</p><p>Example:</p><pre>-- /books?published
38+type MyApi = &quot;books&quot; :&gt; QueryFlag &quot;published&quot; :&gt; Get [Book]</pre></div><div class="subs instances"><p id="control.i:QueryFlag" class="caption collapser" onclick="toggleSection('i:QueryFlag')">Instances</p><div id="section.i:QueryFlag" class="show"><table><tr><td class="src">(<a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:KnownSymbol">KnownSymbol</a> sym, <a href="Servant-Server.html#t:HasServer">HasServer</a> sublayout) =&gt; <a href="Servant-Server.html#t:HasServer">HasServer</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> * (<a href="Servant-API-QueryParam.html#t:QueryFlag">QueryFlag</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a> sym) sublayout)</td><td class="doc"><p>If you use <code><code><a href="Servant-API-QueryParam.html#t:QueryFlag">QueryFlag</a></code> &quot;published&quot;</code> in one of the endpoints for your API,
39+ this automatically requires your server-side handler to be a function
40+ that takes an argument of type <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#t:Bool">Bool</a></code>.</p><p>Example:</p><pre>type MyApi = &quot;books&quot; :&gt; QueryFlag &quot;published&quot; :&gt; Get [Book]
41+
42+server :: Server MyApi
43+server = getBooks
44+ where getBooks :: Bool -&gt; EitherT (Int, String) IO [Book]
45+ getBooks onlyPublished = ...return all books, or only the ones that are already published, depending on the argument...</pre></td></tr><tr><td class="src"><span class="keyword">type</span> <a href="Servant-Server.html#t:Server">Server</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> * (<a href="Servant-API-QueryParam.html#t:QueryFlag">QueryFlag</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a> sym) sublayout) = <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#t:Bool">Bool</a> -&gt; <a href="Servant-Server.html#t:Server">Server</a> sublayout</td><td class="doc empty">&nbsp;</td></tr></table></div></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.15.0</p></div></body></html>
Servant-API-Raw.htmlnew file+11
@@ -0,0 +1,11 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.API.Raw</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();setSynopsis("mini_Servant-API-Raw.html");};
3+//]]>
4+</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="src/Servant-API-Raw.html">Source</a></li><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">servant-0.2: A family of combinators for defining webservices APIs and serving them</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr><tr><th>Language</th><td>Haskell2010</td></tr></table><p class="caption">Servant.API.Raw</p></div><div id="synopsis"><p id="control.syn" class="caption expander" onclick="toggleSection('syn')">Synopsis</p><ul id="section.syn" class="hide" onclick="toggleSection('syn')"><li class="src short"><span class="keyword">data</span> <a href="#t:Raw">Raw</a></li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><span class="keyword">data</span> <a name="t:Raw" class="def">Raw</a> <a href="src/Servant-API-Raw.html#Raw" class="link">Source</a></p><div class="doc"><p>Endpoint for plugging in your own Wai <code><a href="https://hackage.haskell.org/package/wai-3.0.2/docs/Network-Wai.html#t:Application">Application</a></code>s.</p><p>The given <code><a href="https://hackage.haskell.org/package/wai-3.0.2/docs/Network-Wai.html#t:Application">Application</a></code> will get the request as received by the server, potentially with
5+ a modified (stripped) <code><a href="https://hackage.haskell.org/package/wai-3.0.2/docs/Network-Wai.html#v:pathInfo">pathInfo</a></code> if the <code><a href="https://hackage.haskell.org/package/wai-3.0.2/docs/Network-Wai.html#t:Application">Application</a></code> is being routed with <code><a href="Servant-API-Sub.html#t::-62-">:&gt;</a></code>.</p><p>In addition to just letting you plug in your existing WAI <code><a href="https://hackage.haskell.org/package/wai-3.0.2/docs/Network-Wai.html#t:Application">Application</a></code>s,
6+ this can also be used with <code><a href="Servant-Utils-StaticFiles.html#v:serveDirectory">serveDirectory</a></code> to serve
7+ static files stored in a particular directory on your filesystem, or to serve
8+ your API's documentation with <code><a href="Servant-Utils-StaticFiles.html#v:serveDocumentation">serveDocumentation</a></code>.</p></div><div class="subs instances"><p id="control.i:Raw" class="caption collapser" onclick="toggleSection('i:Raw')">Instances</p><div id="section.i:Raw" class="show"><table><tr><td class="src"><a href="Servant-Server.html#t:HasServer">HasServer</a> <a href="Servant-API-Raw.html#t:Raw">Raw</a></td><td class="doc"><p>Just pass the request to the underlying application and serve its response.</p><p>Example:</p><pre>type MyApi = &quot;images&quot; :&gt; Raw
9+
10+server :: Server MyApi
11+server = serveDirectory &quot;/var/www/images&quot;</pre></td></tr><tr><td class="src"><span class="keyword">type</span> <a href="Servant-Server.html#t:Server">Server</a> <a href="Servant-API-Raw.html#t:Raw">Raw</a> = <a href="https://hackage.haskell.org/package/wai-3.0.2/docs/Network-Wai.html#t:Application">Application</a></td><td class="doc empty">&nbsp;</td></tr></table></div></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.15.0</p></div></body></html>
Servant-API-ReqBody.htmlnew file+14
@@ -0,0 +1,14 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.API.ReqBody</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();setSynopsis("mini_Servant-API-ReqBody.html");};
3+//]]>
4+</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="src/Servant-API-ReqBody.html">Source</a></li><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">servant-0.2: A family of combinators for defining webservices APIs and serving them</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr><tr><th>Language</th><td>Haskell2010</td></tr></table><p class="caption">Servant.API.ReqBody</p></div><div id="synopsis"><p id="control.syn" class="caption expander" onclick="toggleSection('syn')">Synopsis</p><ul id="section.syn" class="hide" onclick="toggleSection('syn')"><li class="src short"><span class="keyword">data</span> <a href="#t:ReqBody">ReqBody</a> a</li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><span class="keyword">data</span> <a name="t:ReqBody" class="def">ReqBody</a> a <a href="src/Servant-API-ReqBody.html#ReqBody" class="link">Source</a></p><div class="doc"><p>Extract the request body as a value of type <code>a</code>.</p><p>Example:</p><pre> -- POST /books
5+type MyApi = &quot;books&quot; :&gt; ReqBody Book :&gt; Post Book</pre></div><div class="subs instances"><p id="control.i:ReqBody" class="caption collapser" onclick="toggleSection('i:ReqBody')">Instances</p><div id="section.i:ReqBody" class="show"><table><tr><td class="src">(<a href="https://hackage.haskell.org/package/aeson-0.8.0.2/docs/Data-Aeson-Types.html#t:FromJSON">FromJSON</a> a, <a href="Servant-Server.html#t:HasServer">HasServer</a> sublayout) =&gt; <a href="Servant-Server.html#t:HasServer">HasServer</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> * (<a href="Servant-API-ReqBody.html#t:ReqBody">ReqBody</a> * a) sublayout)</td><td class="doc"><p>If you use <code><a href="Servant-API-ReqBody.html#t:ReqBody">ReqBody</a></code> in one of the endpoints for your API,
6+ this automatically requires your server-side handler to be a function
7+ that takes an argument of the type specified by <code><a href="Servant-API-ReqBody.html#t:ReqBody">ReqBody</a></code>.
8+ This lets servant worry about extracting it from the request and turning
9+ it into a value of the type you specify.</p><p>All it asks is for a <code><a href="https://hackage.haskell.org/package/aeson-0.8.0.2/docs/Data-Aeson-Types.html#t:FromJSON">FromJSON</a></code> instance.</p><p>Example:</p><pre>type MyApi = &quot;books&quot; :&gt; ReqBody Book :&gt; Post Book
10+
11+server :: Server MyApi
12+server = postBook
13+ where postBook :: Book -&gt; EitherT (Int, String) IO Book
14+ postBook book = ...insert into your db...</pre></td></tr><tr><td class="src"><span class="keyword">type</span> <a href="Servant-Server.html#t:Server">Server</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> * (<a href="Servant-API-ReqBody.html#t:ReqBody">ReqBody</a> * a) sublayout) = a -&gt; <a href="Servant-Server.html#t:Server">Server</a> sublayout</td><td class="doc empty">&nbsp;</td></tr></table></div></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.15.0</p></div></body></html>
Servant-API-Sub.htmlnew file+56
@@ -0,0 +1,56 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.API.Sub</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();setSynopsis("mini_Servant-API-Sub.html");};
3+//]]>
4+</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="src/Servant-API-Sub.html">Source</a></li><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">servant-0.2: A family of combinators for defining webservices APIs and serving them</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr><tr><th>Language</th><td>Haskell2010</td></tr></table><p class="caption">Servant.API.Sub</p></div><div id="synopsis"><p id="control.syn" class="caption expander" onclick="toggleSection('syn')">Synopsis</p><ul id="section.syn" class="hide" onclick="toggleSection('syn')"><li class="src short"><span class="keyword">data</span> path <a href="#t::-62-">:&gt;</a> a = (<a href="Servant.html#t:Proxy">Proxy</a> path) <a href="#v::-62-">:&gt;</a> a</li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><span class="keyword">data</span> path <a name="t::-62-" class="def">:&gt;</a> a <span class="fixity">infixr 9</span><span class="rightedge"></span> <a href="src/Servant-API-Sub.html#%3A%3E" class="link">Source</a></p><div class="doc"><p>The contained API (second argument) can be found under <code>(&quot;/&quot; ++ path)</code>
5+ (path being the first argument).</p><p>Example:</p><pre>-- GET /hello/world
6+-- returning a JSON encoded World value
7+type MyApi = &quot;hello&quot; :&gt; &quot;world&quot; :&gt; Get World</pre></div><div class="subs constructors"><p class="caption">Constructors</p><table><tr><td class="src">(<a href="Servant.html#t:Proxy">Proxy</a> path) <a name="v::-62-" class="def">:&gt;</a> a <span class="fixity">infixr 9</span><span class="rightedge"></span></td><td class="doc empty">&nbsp;</td></tr></table></div><div class="subs instances"><p id="control.i::-62-" class="caption collapser" onclick="toggleSection('i::-62-')">Instances</p><div id="section.i::-62-" class="show"><table><tr><td class="src">(<a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:KnownSymbol">KnownSymbol</a> s, <a href="Servant-Utils-Links.html#t:VLinkHelper">VLinkHelper</a> * e) =&gt; <a href="Servant-Utils-Links.html#t:VLinkHelper">VLinkHelper</a> * (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a> s e)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src">(<a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:KnownSymbol">KnownSymbol</a> capture, <a href="Servant-Common-Text.html#t:FromText">FromText</a> a, <a href="Servant-Server.html#t:HasServer">HasServer</a> sublayout) =&gt; <a href="Servant-Server.html#t:HasServer">HasServer</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> * (<a href="Servant-API-Capture.html#t:Capture">Capture</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a> * capture a) sublayout)</td><td class="doc"><p>If you use <code><a href="Servant-API-Capture.html#t:Capture">Capture</a></code> in one of the endpoints for your API,
8+ this automatically requires your server-side handler to be a function
9+ that takes an argument of the type specified by the <code><a href="Servant-API-Capture.html#t:Capture">Capture</a></code>.
10+ This lets servant worry about getting it from the URL and turning
11+ it into a value of the type you specify.</p><p>You can control how it'll be converted from <code><a href="https://hackage.haskell.org/package/text-1.2.0.0/docs/Data-Text.html#t:Text">Text</a></code> to your type
12+ by simply providing an instance of <code><a href="Servant-Common-Text.html#t:FromText">FromText</a></code> for your type.</p><p>Example:</p><pre>type MyApi = &quot;books&quot; :&gt; Capture &quot;isbn&quot; Text :&gt; Get Book
13+
14+server :: Server MyApi
15+server = getBook
16+ where getBook :: Text -&gt; EitherT (Int, String) IO Book
17+ getBook isbn = ...</pre></td></tr><tr><td class="src">(<a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:KnownSymbol">KnownSymbol</a> sym, <a href="Servant-Server.html#t:HasServer">HasServer</a> sublayout) =&gt; <a href="Servant-Server.html#t:HasServer">HasServer</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> * (<a href="Servant-API-QueryParam.html#t:QueryFlag">QueryFlag</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a> sym) sublayout)</td><td class="doc"><p>If you use <code><code><a href="Servant-API-QueryParam.html#t:QueryFlag">QueryFlag</a></code> &quot;published&quot;</code> in one of the endpoints for your API,
18+ this automatically requires your server-side handler to be a function
19+ that takes an argument of type <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#t:Bool">Bool</a></code>.</p><p>Example:</p><pre>type MyApi = &quot;books&quot; :&gt; QueryFlag &quot;published&quot; :&gt; Get [Book]
20+
21+server :: Server MyApi
22+server = getBooks
23+ where getBooks :: Bool -&gt; EitherT (Int, String) IO [Book]
24+ getBooks onlyPublished = ...return all books, or only the ones that are already published, depending on the argument...</pre></td></tr><tr><td class="src">(<a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:KnownSymbol">KnownSymbol</a> sym, <a href="Servant-Common-Text.html#t:FromText">FromText</a> a, <a href="Servant-Server.html#t:HasServer">HasServer</a> sublayout) =&gt; <a href="Servant-Server.html#t:HasServer">HasServer</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> * (<a href="Servant-API-QueryParam.html#t:QueryParams">QueryParams</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a> * sym a) sublayout)</td><td class="doc"><p>If you use <code><code><a href="Servant-API-QueryParam.html#t:QueryParams">QueryParams</a></code> &quot;authors&quot; Text</code> in one of the endpoints for your API,
25+ this automatically requires your server-side handler to be a function
26+ that takes an argument of type <code>[<code>Text</code>]</code>.</p><p>This lets servant worry about looking up 0 or more values in the query string
27+ associated to <code>authors</code> and turning each of them into a value of
28+ the type you specify.</p><p>You can control how the individual values are converted from <code>Text</code> to your type
29+ by simply providing an instance of <code><a href="Servant-Common-Text.html#t:FromText">FromText</a></code> for your type.</p><p>Example:</p><pre>type MyApi = &quot;books&quot; :&gt; QueryParams &quot;authors&quot; Text :&gt; Get [Book]
30+
31+server :: Server MyApi
32+server = getBooksBy
33+ where getBooksBy :: [Text] -&gt; EitherT (Int, String) IO [Book]
34+ getBooksBy authors = ...return all books by these authors...</pre></td></tr><tr><td class="src">(<a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:KnownSymbol">KnownSymbol</a> sym, <a href="Servant-Common-Text.html#t:FromText">FromText</a> a, <a href="Servant-Server.html#t:HasServer">HasServer</a> sublayout) =&gt; <a href="Servant-Server.html#t:HasServer">HasServer</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> * (<a href="Servant-API-QueryParam.html#t:QueryParam">QueryParam</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a> * sym a) sublayout)</td><td class="doc"><p>If you use <code><code><a href="Servant-API-QueryParam.html#t:QueryParam">QueryParam</a></code> &quot;author&quot; Text</code> in one of the endpoints for your API,
35+ this automatically requires your server-side handler to be a function
36+ that takes an argument of type <code><code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Maybe.html#t:Maybe">Maybe</a></code> <code>Text</code></code>.</p><p>This lets servant worry about looking it up in the query string
37+ and turning it into a value of the type you specify, enclosed
38+ in <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Maybe.html#t:Maybe">Maybe</a></code>, because it may not be there and servant would then
39+ hand you <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Maybe.html#v:Nothing">Nothing</a></code>.</p><p>You can control how it'll be converted from <code>Text</code> to your type
40+ by simply providing an instance of <code><a href="Servant-Common-Text.html#t:FromText">FromText</a></code> for your type.</p><p>Example:</p><pre>type MyApi = &quot;books&quot; :&gt; QueryParam &quot;author&quot; Text :&gt; Get [Book]
41+
42+server :: Server MyApi
43+server = getBooksBy
44+ where getBooksBy :: Maybe Text -&gt; EitherT (Int, String) IO [Book]
45+ getBooksBy Nothing = ...return all books...
46+ getBooksBy (Just author) = ...return books by the given author...</pre></td></tr><tr><td class="src">(<a href="https://hackage.haskell.org/package/aeson-0.8.0.2/docs/Data-Aeson-Types.html#t:FromJSON">FromJSON</a> a, <a href="Servant-Server.html#t:HasServer">HasServer</a> sublayout) =&gt; <a href="Servant-Server.html#t:HasServer">HasServer</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> * (<a href="Servant-API-ReqBody.html#t:ReqBody">ReqBody</a> * a) sublayout)</td><td class="doc"><p>If you use <code><a href="Servant-API-ReqBody.html#t:ReqBody">ReqBody</a></code> in one of the endpoints for your API,
47+ this automatically requires your server-side handler to be a function
48+ that takes an argument of the type specified by <code><a href="Servant-API-ReqBody.html#t:ReqBody">ReqBody</a></code>.
49+ This lets servant worry about extracting it from the request and turning
50+ it into a value of the type you specify.</p><p>All it asks is for a <code><a href="https://hackage.haskell.org/package/aeson-0.8.0.2/docs/Data-Aeson-Types.html#t:FromJSON">FromJSON</a></code> instance.</p><p>Example:</p><pre>type MyApi = &quot;books&quot; :&gt; ReqBody Book :&gt; Post Book
51+
52+server :: Server MyApi
53+server = postBook
54+ where postBook :: Book -&gt; EitherT (Int, String) IO Book
55+ postBook book = ...insert into your db...</pre></td></tr><tr><td class="src">(<a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:KnownSymbol">KnownSymbol</a> path, <a href="Servant-Server.html#t:HasServer">HasServer</a> sublayout) =&gt; <a href="Servant-Server.html#t:HasServer">HasServer</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a> path sublayout)</td><td class="doc"><p>Make sure the incoming request starts with <code>&quot;/path&quot;</code>, strip it and
56+ pass the rest of the request path to <code>sublayout</code>.</p></td></tr><tr><td class="src"><span class="keyword">type</span> <a href="Servant-Server.html#t:Server">Server</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> * (<a href="Servant-API-Capture.html#t:Capture">Capture</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a> * capture a) sublayout) = a -&gt; <a href="Servant-Server.html#t:Server">Server</a> sublayout</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><span class="keyword">type</span> <a href="Servant-Server.html#t:Server">Server</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> * (<a href="Servant-API-QueryParam.html#t:QueryFlag">QueryFlag</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a> sym) sublayout) = <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#t:Bool">Bool</a> -&gt; <a href="Servant-Server.html#t:Server">Server</a> sublayout</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><span class="keyword">type</span> <a href="Servant-Server.html#t:Server">Server</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> * (<a href="Servant-API-QueryParam.html#t:QueryParams">QueryParams</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a> * sym a) sublayout) = [a] -&gt; <a href="Servant-Server.html#t:Server">Server</a> sublayout</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><span class="keyword">type</span> <a href="Servant-Server.html#t:Server">Server</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> * (<a href="Servant-API-QueryParam.html#t:QueryParam">QueryParam</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a> * sym a) sublayout) = <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Maybe.html#t:Maybe">Maybe</a> a -&gt; <a href="Servant-Server.html#t:Server">Server</a> sublayout</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><span class="keyword">type</span> <a href="Servant-Server.html#t:Server">Server</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> * (<a href="Servant-API-ReqBody.html#t:ReqBody">ReqBody</a> * a) sublayout) = a -&gt; <a href="Servant-Server.html#t:Server">Server</a> sublayout</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><span class="keyword">type</span> <a href="Servant-Server.html#t:Server">Server</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a> path sublayout) = <a href="Servant-Server.html#t:Server">Server</a> sublayout</td><td class="doc empty">&nbsp;</td></tr></table></div></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.15.0</p></div></body></html>
Servant-API.htmlnew file+4
@@ -0,0 +1,4 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.API</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();setSynopsis("mini_Servant-API.html");};
3+//]]>
4+</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="src/Servant-API.html">Source</a></li><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">servant-0.2: A family of combinators for defining webservices APIs and serving them</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr><tr><th>Language</th><td>Haskell2010</td></tr></table><p class="caption">Servant.API</p></div><div id="table-of-contents"><p class="caption">Contents</p><ul><li><a href="#g:1">Combinators</a></li><li><a href="#g:2">Accessing information from the request</a></li><li><a href="#g:3">Actual endpoints, distinguished by HTTP method</a></li><li><a href="#g:4">Untyped endpoints</a></li><li><a href="#g:5">Utilities</a></li></ul></div><div id="synopsis"><p id="control.syn" class="caption expander" onclick="toggleSection('syn')">Synopsis</p><ul id="section.syn" class="hide" onclick="toggleSection('syn')"><li class="src short">module <a href="Servant-API-Sub.html">Servant.API.Sub</a></li><li class="src short">module <a href="Servant-API-Alternative.html">Servant.API.Alternative</a></li><li class="src short">module <a href="Servant-API-Capture.html">Servant.API.Capture</a></li><li class="src short">module <a href="Servant-API-QueryParam.html">Servant.API.QueryParam</a></li><li class="src short">module <a href="Servant-API-ReqBody.html">Servant.API.ReqBody</a></li><li class="src short">module <a href="Servant-API-Get.html">Servant.API.Get</a></li><li class="src short">module <a href="Servant-API-Post.html">Servant.API.Post</a></li><li class="src short">module <a href="Servant-API-Delete.html">Servant.API.Delete</a></li><li class="src short">module <a href="Servant-API-Put.html">Servant.API.Put</a></li><li class="src short">module <a href="Servant-API-Raw.html">Servant.API.Raw</a></li><li class="src short">module <a href="Servant-Utils-StaticFiles.html">Servant.Utils.StaticFiles</a></li><li class="src short">module <a href="Servant-QQ.html">Servant.QQ</a></li><li class="src short">module <a href="Servant-Utils-Links.html">Servant.Utils.Links</a></li></ul></div><div id="interface"><h1 id="g:1">Combinators</h1><div class="doc"><p>Type-level combinator for expressing subrouting: <code><code><a href="Servant-API-Sub.html#t::-62-">:&gt;</a></code></code></p></div><div class="top"><p class="src">module <a href="Servant-API-Sub.html">Servant.API.Sub</a></p></div><div class="doc"><p>Type-level combinator for alternative endpoints: <code><code><a href="Servant-API-Alternative.html#t::-60--124--62-">:&lt;|&gt;</a></code></code></p></div><div class="top"><p class="src">module <a href="Servant-API-Alternative.html">Servant.API.Alternative</a></p></div><h1 id="g:2">Accessing information from the request</h1><div class="doc"><p>Capturing parts of the url path as parsed values: <code><code><a href="Servant-API-Capture.html#t:Capture">Capture</a></code></code></p></div><div class="top"><p class="src">module <a href="Servant-API-Capture.html">Servant.API.Capture</a></p></div><div class="doc"><p>Retrieving parameters from the query string of the <code>URI</code>: <code><code><a href="Servant-API-QueryParam.html#t:QueryParam">QueryParam</a></code></code></p></div><div class="top"><p class="src">module <a href="Servant-API-QueryParam.html">Servant.API.QueryParam</a></p></div><div class="doc"><p>Accessing the request body as a JSON-encoded type: <code><code><a href="Servant-API-ReqBody.html#t:ReqBody">ReqBody</a></code></code></p></div><div class="top"><p class="src">module <a href="Servant-API-ReqBody.html">Servant.API.ReqBody</a></p></div><h1 id="g:3">Actual endpoints, distinguished by HTTP method</h1><div class="doc"><p>GET requests</p></div><div class="top"><p class="src">module <a href="Servant-API-Get.html">Servant.API.Get</a></p></div><div class="doc"><p>POST requests</p></div><div class="top"><p class="src">module <a href="Servant-API-Post.html">Servant.API.Post</a></p></div><div class="doc"><p>DELETE requests</p></div><div class="top"><p class="src">module <a href="Servant-API-Delete.html">Servant.API.Delete</a></p></div><div class="doc"><p>PUT requests</p></div><div class="top"><p class="src">module <a href="Servant-API-Put.html">Servant.API.Put</a></p></div><h1 id="g:4">Untyped endpoints</h1><div class="doc"><p>Plugging in a wai <code><a href="https://hackage.haskell.org/package/wai-3.0.2/docs/Network-Wai.html#t:Application">Application</a></code>, serving directories</p></div><div class="top"><p class="src">module <a href="Servant-API-Raw.html">Servant.API.Raw</a></p></div><div class="top"><p class="src">module <a href="Servant-Utils-StaticFiles.html">Servant.Utils.StaticFiles</a></p></div><h1 id="g:5">Utilities</h1><div class="doc"><p>QuasiQuotes for endpoints</p></div><div class="top"><p class="src">module <a href="Servant-QQ.html">Servant.QQ</a></p></div><div class="doc"><p>Type-safe internal URLs</p></div><div class="top"><p class="src">module <a href="Servant-Utils-Links.html">Servant.Utils.Links</a></p></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.15.0</p></div></body></html>
Servant-Common-Text.htmlnew file+7
@@ -0,0 +1,7 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.Common.Text</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();setSynopsis("mini_Servant-Common-Text.html");};
3+//]]>
4+</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="src/Servant-Common-Text.html">Source</a></li><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">servant-0.2: A family of combinators for defining webservices APIs and serving them</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>Safe-Inferred</td></tr><tr><th>Language</th><td>Haskell2010</td></tr></table><p class="caption">Servant.Common.Text</p></div><div id="synopsis"><p id="control.syn" class="caption expander" onclick="toggleSection('syn')">Synopsis</p><ul id="section.syn" class="hide" onclick="toggleSection('syn')"><li class="src short"><span class="keyword">class</span> <a href="#t:FromText">FromText</a> a <span class="keyword">where</span><ul class="subs"><li><a href="#v:fromText">fromText</a> :: <a href="https://hackage.haskell.org/package/text-1.2.0.0/docs/Data-Text.html#t:Text">Text</a> -&gt; <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Maybe.html#t:Maybe">Maybe</a> a</li></ul></li><li class="src short"><span class="keyword">class</span> <a href="#t:ToText">ToText</a> a <span class="keyword">where</span><ul class="subs"><li><a href="#v:toText">toText</a> :: a -&gt; <a href="https://hackage.haskell.org/package/text-1.2.0.0/docs/Data-Text.html#t:Text">Text</a></li></ul></li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><span class="keyword">class</span> <a name="t:FromText" class="def">FromText</a> a <span class="keyword">where</span> <a href="src/Servant-Common-Text.html#FromText" class="link">Source</a></p><div class="doc"><p>For getting values from url captures and query string parameters</p></div><div class="subs methods"><p class="caption">Methods</p><p class="src"><a name="v:fromText" class="def">fromText</a> :: <a href="https://hackage.haskell.org/package/text-1.2.0.0/docs/Data-Text.html#t:Text">Text</a> -&gt; <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Maybe.html#t:Maybe">Maybe</a> a <a href="src/Servant-Common-Text.html#fromText" class="link">Source</a></p></div><div class="subs instances"><p id="control.i:FromText" class="caption collapser" onclick="toggleSection('i:FromText')">Instances</p><div id="section.i:FromText" class="show"><table><tr><td class="src"><a href="Servant-Common-Text.html#t:FromText">FromText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#t:Bool">Bool</a></td><td class="doc"><pre>fromText &quot;true&quot; = Just True
5+fromText &quot;false&quot; = Just False
6+fromText _ = Nothing</pre></td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:FromText">FromText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Prelude.html#t:Double">Double</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:FromText">FromText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Prelude.html#t:Float">Float</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:FromText">FromText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Int.html#t:Int">Int</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:FromText">FromText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Int.html#t:Int8">Int8</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:FromText">FromText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Int.html#t:Int16">Int16</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:FromText">FromText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Int.html#t:Int32">Int32</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:FromText">FromText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Int.html#t:Int64">Int64</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:FromText">FromText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Prelude.html#t:Integer">Integer</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:FromText">FromText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Word.html#t:Word">Word</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:FromText">FromText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Word.html#t:Word8">Word8</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:FromText">FromText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Word.html#t:Word16">Word16</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:FromText">FromText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Word.html#t:Word32">Word32</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:FromText">FromText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Word.html#t:Word64">Word64</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:FromText">FromText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:FromText">FromText</a> <a href="https://hackage.haskell.org/package/text-1.2.0.0/docs/Data-Text.html#t:Text">Text</a></td><td class="doc empty">&nbsp;</td></tr></table></div></div></div><div class="top"><p class="src"><span class="keyword">class</span> <a name="t:ToText" class="def">ToText</a> a <span class="keyword">where</span> <a href="src/Servant-Common-Text.html#ToText" class="link">Source</a></p><div class="doc"><p>For putting values in paths and query string parameters</p></div><div class="subs methods"><p class="caption">Methods</p><p class="src"><a name="v:toText" class="def">toText</a> :: a -&gt; <a href="https://hackage.haskell.org/package/text-1.2.0.0/docs/Data-Text.html#t:Text">Text</a> <a href="src/Servant-Common-Text.html#toText" class="link">Source</a></p></div><div class="subs instances"><p id="control.i:ToText" class="caption collapser" onclick="toggleSection('i:ToText')">Instances</p><div id="section.i:ToText" class="show"><table><tr><td class="src"><a href="Servant-Common-Text.html#t:ToText">ToText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#t:Bool">Bool</a></td><td class="doc"><pre>toText True = &quot;true&quot;
7+toText False = &quot;false&quot;</pre></td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:ToText">ToText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Prelude.html#t:Double">Double</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:ToText">ToText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Prelude.html#t:Float">Float</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:ToText">ToText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Int.html#t:Int">Int</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:ToText">ToText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Int.html#t:Int8">Int8</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:ToText">ToText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Int.html#t:Int16">Int16</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:ToText">ToText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Int.html#t:Int32">Int32</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:ToText">ToText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Int.html#t:Int64">Int64</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:ToText">ToText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Prelude.html#t:Integer">Integer</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:ToText">ToText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Word.html#t:Word">Word</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:ToText">ToText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Word.html#t:Word8">Word8</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:ToText">ToText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Word.html#t:Word16">Word16</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:ToText">ToText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Word.html#t:Word32">Word32</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:ToText">ToText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Word.html#t:Word64">Word64</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:ToText">ToText</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Common-Text.html#t:ToText">ToText</a> <a href="https://hackage.haskell.org/package/text-1.2.0.0/docs/Data-Text.html#t:Text">Text</a></td><td class="doc empty">&nbsp;</td></tr></table></div></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.15.0</p></div></body></html>
Servant-QQ.htmlnew file+17
@@ -0,0 +1,17 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.QQ</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();setSynopsis("mini_Servant-QQ.html");};
3+//]]>
4+</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="src/Servant-QQ.html">Source</a></li><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">servant-0.2: A family of combinators for defining webservices APIs and serving them</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr><tr><th>Language</th><td>Haskell2010</td></tr></table><p class="caption">Servant.QQ</p></div><div id="description"><p class="caption">Description</p><div class="doc"><p>QuasiQuoting utilities for API types.</p><p><code><a href="Servant-QQ.html#v:sitemap">sitemap</a></code> allows you to write your type in a very natural way:</p><pre>[sitemap|
5+PUT hello String -&gt; ()
6+POST hello/p:Int String -&gt; ()
7+GET hello/?name:String Int
8+|]
9+</pre><p>Will generate:</p><pre> &quot;hello&quot; :&gt; ReqBody String :&gt; Put ()
10+ :&lt;|&gt; &quot;hello&quot; :&gt; Capture &quot;p&quot; Int :&gt; ReqBody String :&gt; Post ()
11+ :&lt;|&gt; &quot;hello&quot; :&gt; QueryParam &quot;name&quot; String :&gt; Get Int
12+</pre><p>Note the <code>/</code> before a <code>QueryParam</code>!</p></div></div><div id="synopsis"><p id="control.syn" class="caption expander" onclick="toggleSection('syn')">Synopsis</p><ul id="section.syn" class="hide" onclick="toggleSection('syn')"><li class="src short"><span class="keyword">class</span> <a href="#t:ExpSYM">ExpSYM</a> repr' repr | repr -&gt; repr', repr' -&gt; repr <span class="keyword">where</span><ul class="subs"><li><a href="#v:lit">lit</a> :: <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> -&gt; repr' -&gt; repr</li><li><a href="#v:capture">capture</a> :: <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> -&gt; <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> -&gt; repr -&gt; repr</li><li><a href="#v:reqBody">reqBody</a> :: <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> -&gt; repr -&gt; repr</li><li><a href="#v:queryParam">queryParam</a> :: <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> -&gt; <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> -&gt; repr -&gt; repr</li><li><a href="#v:conj">conj</a> :: repr' -&gt; repr -&gt; repr</li><li><a href="#v:get">get</a> :: <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> -&gt; repr</li><li><a href="#v:post">post</a> :: <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> -&gt; repr</li><li><a href="#v:put">put</a> :: <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> -&gt; repr</li><li><a href="#v:delete">delete</a> :: <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> -&gt; repr</li></ul></li><li class="src short"><a href="#v:-62-:">(&gt;:)</a> :: <a href="https://hackage.haskell.org/package/template-haskell-2.9.0.0/docs/Language-Haskell-TH-Syntax.html#t:Type">Type</a> -&gt; <a href="https://hackage.haskell.org/package/template-haskell-2.9.0.0/docs/Language-Haskell-TH-Syntax.html#t:Type">Type</a> -&gt; <a href="https://hackage.haskell.org/package/template-haskell-2.9.0.0/docs/Language-Haskell-TH-Syntax.html#t:Type">Type</a></li><li class="src short"><a href="#v:parseMethod">parseMethod</a> :: <a href="Servant-QQ.html#t:ExpSYM">ExpSYM</a> repr' repr =&gt; <a href="https://hackage.haskell.org/package/parsec-3.1.7/docs/Text-Parsec-String.html#t:Parser">Parser</a> (<a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> -&gt; repr)</li><li class="src short"><a href="#v:parseUrlSegment">parseUrlSegment</a> :: <a href="Servant-QQ.html#t:ExpSYM">ExpSYM</a> repr repr =&gt; <a href="https://hackage.haskell.org/package/parsec-3.1.7/docs/Text-Parsec-String.html#t:Parser">Parser</a> (repr -&gt; repr)</li><li class="src short"><a href="#v:parseUrl">parseUrl</a> :: <a href="Servant-QQ.html#t:ExpSYM">ExpSYM</a> repr repr =&gt; <a href="https://hackage.haskell.org/package/parsec-3.1.7/docs/Text-Parsec-String.html#t:Parser">Parser</a> (repr -&gt; repr)</li><li class="src short"><span class="keyword">data</span> <a href="#t:Typ">Typ</a><ul class="subs"><li>= <a href="#v:Val">Val</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a></li><li>| <a href="#v:ReqArgVal">ReqArgVal</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a></li></ul></li><li class="src short"><a href="#v:parseTyp">parseTyp</a> :: <a href="https://hackage.haskell.org/package/parsec-3.1.7/docs/Text-Parsec-String.html#t:Parser">Parser</a> <a href="Servant-QQ.html#t:Typ">Typ</a></li><li class="src short"><a href="#v:parseEntry">parseEntry</a> :: <a href="Servant-QQ.html#t:ExpSYM">ExpSYM</a> repr repr =&gt; <a href="https://hackage.haskell.org/package/parsec-3.1.7/docs/Text-Parsec-String.html#t:Parser">Parser</a> repr</li><li class="src short"><a href="#v:blockComment">blockComment</a> :: <a href="https://hackage.haskell.org/package/parsec-3.1.7/docs/Text-Parsec-String.html#t:Parser">Parser</a> ()</li><li class="src short"><a href="#v:inlineComment">inlineComment</a> :: <a href="https://hackage.haskell.org/package/parsec-3.1.7/docs/Text-Parsec-String.html#t:Parser">Parser</a> ()</li><li class="src short"><a href="#v:eol">eol</a> :: <a href="https://hackage.haskell.org/package/parsec-3.1.7/docs/Text-Parsec-String.html#t:Parser">Parser</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a></li><li class="src short"><a href="#v:eols">eols</a> :: <a href="https://hackage.haskell.org/package/parsec-3.1.7/docs/Text-Parsec-String.html#t:Parser">Parser</a> ()</li><li class="src short"><a href="#v:parseAll">parseAll</a> :: <a href="https://hackage.haskell.org/package/parsec-3.1.7/docs/Text-Parsec-String.html#t:Parser">Parser</a> <a href="https://hackage.haskell.org/package/template-haskell-2.9.0.0/docs/Language-Haskell-TH-Syntax.html#t:Type">Type</a></li><li class="src short"><a href="#v:sitemap">sitemap</a> :: <a href="https://hackage.haskell.org/package/template-haskell-2.9.0.0/docs/Language-Haskell-TH-Quote.html#t:QuasiQuoter">QuasiQuoter</a></li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><span class="keyword">class</span> <a name="t:ExpSYM" class="def">ExpSYM</a> repr' repr | repr -&gt; repr', repr' -&gt; repr <span class="keyword">where</span> <a href="src/Servant-QQ.html#ExpSYM" class="link">Source</a></p><div class="doc"><p>Finally-tagless encoding for our DSL.
13+ Keeping <code>repr'</code> and <code>repr</code> distinct when writing functions with an
14+ <code>ExpSYM</code> context ensures certain invariants (for instance, that there is
15+ only one of <code><a href="Servant-QQ.html#v:get">get</a></code>, <code><a href="Servant-QQ.html#v:post">post</a></code>, <code><a href="Servant-QQ.html#v:put">put</a></code>, and <code><a href="Servant-QQ.html#v:delete">delete</a></code> in a value), but
16+ sometimes requires a little more work.</p></div><div class="subs methods"><p class="caption">Methods</p><p class="src"><a name="v:lit" class="def">lit</a> :: <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> -&gt; repr' -&gt; repr <a href="src/Servant-QQ.html#lit" class="link">Source</a></p><p class="src"><a name="v:capture" class="def">capture</a> :: <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> -&gt; <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> -&gt; repr -&gt; repr <a href="src/Servant-QQ.html#capture" class="link">Source</a></p><p class="src"><a name="v:reqBody" class="def">reqBody</a> :: <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> -&gt; repr -&gt; repr <a href="src/Servant-QQ.html#reqBody" class="link">Source</a></p><p class="src"><a name="v:queryParam" class="def">queryParam</a> :: <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> -&gt; <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> -&gt; repr -&gt; repr <a href="src/Servant-QQ.html#queryParam" class="link">Source</a></p><p class="src"><a name="v:conj" class="def">conj</a> :: repr' -&gt; repr -&gt; repr <a href="src/Servant-QQ.html#conj" class="link">Source</a></p><p class="src"><a name="v:get" class="def">get</a> :: <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> -&gt; repr <a href="src/Servant-QQ.html#get" class="link">Source</a></p><p class="src"><a name="v:post" class="def">post</a> :: <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> -&gt; repr <a href="src/Servant-QQ.html#post" class="link">Source</a></p><p class="src"><a name="v:put" class="def">put</a> :: <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> -&gt; repr <a href="src/Servant-QQ.html#put" class="link">Source</a></p><p class="src"><a name="v:delete" class="def">delete</a> :: <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> -&gt; repr <a href="src/Servant-QQ.html#delete" class="link">Source</a></p></div><div class="subs instances"><p id="control.i:ExpSYM" class="caption collapser" onclick="toggleSection('i:ExpSYM')">Instances</p><div id="section.i:ExpSYM" class="show"><table><tr><td class="src"><a href="Servant-QQ.html#t:ExpSYM">ExpSYM</a> <a href="https://hackage.haskell.org/package/template-haskell-2.9.0.0/docs/Language-Haskell-TH-Syntax.html#t:Type">Type</a> <a href="https://hackage.haskell.org/package/template-haskell-2.9.0.0/docs/Language-Haskell-TH-Syntax.html#t:Type">Type</a></td><td class="doc empty">&nbsp;</td></tr></table></div></div></div><div class="top"><p class="src"><a name="v:-62-:" class="def">(&gt;:)</a> :: <a href="https://hackage.haskell.org/package/template-haskell-2.9.0.0/docs/Language-Haskell-TH-Syntax.html#t:Type">Type</a> -&gt; <a href="https://hackage.haskell.org/package/template-haskell-2.9.0.0/docs/Language-Haskell-TH-Syntax.html#t:Type">Type</a> -&gt; <a href="https://hackage.haskell.org/package/template-haskell-2.9.0.0/docs/Language-Haskell-TH-Syntax.html#t:Type">Type</a> <span class="fixity">infixr 6</span><span class="rightedge"></span> <a href="src/Servant-QQ.html#%3E%3A" class="link">Source</a></p></div><div class="top"><p class="src"><a name="v:parseMethod" class="def">parseMethod</a> :: <a href="Servant-QQ.html#t:ExpSYM">ExpSYM</a> repr' repr =&gt; <a href="https://hackage.haskell.org/package/parsec-3.1.7/docs/Text-Parsec-String.html#t:Parser">Parser</a> (<a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> -&gt; repr) <a href="src/Servant-QQ.html#parseMethod" class="link">Source</a></p></div><div class="top"><p class="src"><a name="v:parseUrlSegment" class="def">parseUrlSegment</a> :: <a href="Servant-QQ.html#t:ExpSYM">ExpSYM</a> repr repr =&gt; <a href="https://hackage.haskell.org/package/parsec-3.1.7/docs/Text-Parsec-String.html#t:Parser">Parser</a> (repr -&gt; repr) <a href="src/Servant-QQ.html#parseUrlSegment" class="link">Source</a></p></div><div class="top"><p class="src"><a name="v:parseUrl" class="def">parseUrl</a> :: <a href="Servant-QQ.html#t:ExpSYM">ExpSYM</a> repr repr =&gt; <a href="https://hackage.haskell.org/package/parsec-3.1.7/docs/Text-Parsec-String.html#t:Parser">Parser</a> (repr -&gt; repr) <a href="src/Servant-QQ.html#parseUrl" class="link">Source</a></p></div><div class="top"><p class="src"><span class="keyword">data</span> <a name="t:Typ" class="def">Typ</a> <a href="src/Servant-QQ.html#Typ" class="link">Source</a></p><div class="subs constructors"><p class="caption">Constructors</p><table><tr><td class="src"><a name="v:Val" class="def">Val</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a name="v:ReqArgVal" class="def">ReqArgVal</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a></td><td class="doc empty">&nbsp;</td></tr></table></div></div><div class="top"><p class="src"><a name="v:parseTyp" class="def">parseTyp</a> :: <a href="https://hackage.haskell.org/package/parsec-3.1.7/docs/Text-Parsec-String.html#t:Parser">Parser</a> <a href="Servant-QQ.html#t:Typ">Typ</a> <a href="src/Servant-QQ.html#parseTyp" class="link">Source</a></p></div><div class="top"><p class="src"><a name="v:parseEntry" class="def">parseEntry</a> :: <a href="Servant-QQ.html#t:ExpSYM">ExpSYM</a> repr repr =&gt; <a href="https://hackage.haskell.org/package/parsec-3.1.7/docs/Text-Parsec-String.html#t:Parser">Parser</a> repr <a href="src/Servant-QQ.html#parseEntry" class="link">Source</a></p></div><div class="top"><p class="src"><a name="v:blockComment" class="def">blockComment</a> :: <a href="https://hackage.haskell.org/package/parsec-3.1.7/docs/Text-Parsec-String.html#t:Parser">Parser</a> () <a href="src/Servant-QQ.html#blockComment" class="link">Source</a></p></div><div class="top"><p class="src"><a name="v:inlineComment" class="def">inlineComment</a> :: <a href="https://hackage.haskell.org/package/parsec-3.1.7/docs/Text-Parsec-String.html#t:Parser">Parser</a> () <a href="src/Servant-QQ.html#inlineComment" class="link">Source</a></p></div><div class="top"><p class="src"><a name="v:eol" class="def">eol</a> :: <a href="https://hackage.haskell.org/package/parsec-3.1.7/docs/Text-Parsec-String.html#t:Parser">Parser</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> <a href="src/Servant-QQ.html#eol" class="link">Source</a></p></div><div class="top"><p class="src"><a name="v:eols" class="def">eols</a> :: <a href="https://hackage.haskell.org/package/parsec-3.1.7/docs/Text-Parsec-String.html#t:Parser">Parser</a> () <a href="src/Servant-QQ.html#eols" class="link">Source</a></p></div><div class="top"><p class="src"><a name="v:parseAll" class="def">parseAll</a> :: <a href="https://hackage.haskell.org/package/parsec-3.1.7/docs/Text-Parsec-String.html#t:Parser">Parser</a> <a href="https://hackage.haskell.org/package/template-haskell-2.9.0.0/docs/Language-Haskell-TH-Syntax.html#t:Type">Type</a> <a href="src/Servant-QQ.html#parseAll" class="link">Source</a></p></div><div class="top"><p class="src"><a name="v:sitemap" class="def">sitemap</a> :: <a href="https://hackage.haskell.org/package/template-haskell-2.9.0.0/docs/Language-Haskell-TH-Quote.html#t:QuasiQuoter">QuasiQuoter</a> <a href="src/Servant-QQ.html#sitemap" class="link">Source</a></p><div class="doc"><p>The sitemap QuasiQuoter.</p><ul><li><code>...<em><a href="var">var</a>:<a href="type">type</a></em>...</code> becomes a capture</li><li><code>.../?<a href="var">var</a>:<a href="type">type</a></code> becomes a query parameter</li><li><code><a href="method">method</a> ... <a href="typ">typ</a></code> becomes a method returning <code><a href="typ">typ</a></code></li><li><code><a href="method">method</a> ... <a href="typ1">typ1</a> -&gt; <a href="typ2">typ2</a></code> becomes a method with request
17+ body of <code><a href="typ1">typ1</a></code> and returning <code><a href="typ2">typ2</a></code></li></ul><p>Comments are allowed, and have the standard Haskell format</p><ul><li><code>--</code> for inline</li><li><code>{- ... -}</code> for block</li></ul></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.15.0</p></div></body></html>
Servant-Server.htmlnew file+116
@@ -0,0 +1,116 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.Server</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();setSynopsis("mini_Servant-Server.html");};
3+//]]>
4+</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="src/Servant-Server.html">Source</a></li><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">servant-0.2: A family of combinators for defining webservices APIs and serving them</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr><tr><th>Language</th><td>Haskell2010</td></tr></table><p class="caption">Servant.Server</p></div><div id="table-of-contents"><p class="caption">Contents</p><ul><li><a href="#g:1">Implementing Servers</a></li><li><a href="#g:2">Route mismatch</a></li></ul></div><div id="description"><p class="caption">Description</p><div class="doc"><p>This module lets you implement <code><a href="Servant-Server.html#t:Server">Server</a></code>s for defined APIs. You'll
5+ most likely just need <code><a href="Servant-Server.html#v:serve">serve</a></code>.</p></div></div><div id="synopsis"><p id="control.syn" class="caption expander" onclick="toggleSection('syn')">Synopsis</p><ul id="section.syn" class="hide" onclick="toggleSection('syn')"><li class="src short"><a href="#v:serve">serve</a> :: <a href="Servant-Server.html#t:HasServer">HasServer</a> layout =&gt; <a href="Servant.html#t:Proxy">Proxy</a> layout -&gt; <a href="Servant-Server.html#t:Server">Server</a> layout -&gt; <a href="https://hackage.haskell.org/package/wai-3.0.2/docs/Network-Wai.html#t:Application">Application</a></li><li class="src short"><a href="#v:toApplication">toApplication</a> :: <a href="Servant-Server.html#t:RoutingApplication">RoutingApplication</a> -&gt; <a href="https://hackage.haskell.org/package/wai-3.0.2/docs/Network-Wai.html#t:Application">Application</a></li><li class="src short"><span class="keyword">data</span> <a href="#t:RouteMismatch">RouteMismatch</a><ul class="subs"><li>= <a href="#v:NotFound">NotFound</a></li><li>| <a href="#v:WrongMethod">WrongMethod</a></li><li>| <a href="#v:InvalidBody">InvalidBody</a></li></ul></li><li class="src short"><span class="keyword">newtype</span> <a href="#t:RouteResult">RouteResult</a> a = <a href="#v:RR">RR</a> {<ul class="subs"><li><a href="#v:routeResult">routeResult</a> :: <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Either.html#t:Either">Either</a> <a href="Servant-Server.html#t:RouteMismatch">RouteMismatch</a> a</li></ul>}</li><li class="src short"><a href="#v:failWith">failWith</a> :: <a href="Servant-Server.html#t:RouteMismatch">RouteMismatch</a> -&gt; <a href="Servant-Server.html#t:RouteResult">RouteResult</a> a</li><li class="src short"><a href="#v:succeedWith">succeedWith</a> :: a -&gt; <a href="Servant-Server.html#t:RouteResult">RouteResult</a> a</li><li class="src short"><a href="#v:isMismatch">isMismatch</a> :: <a href="Servant-Server.html#t:RouteResult">RouteResult</a> a -&gt; <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#t:Bool">Bool</a></li><li class="src short"><span class="keyword">type</span> <a href="#t:RoutingApplication">RoutingApplication</a> = <a href="https://hackage.haskell.org/package/wai-3.0.2/docs/Network-Wai.html#t:Request">Request</a> -&gt; (<a href="Servant-Server.html#t:RouteResult">RouteResult</a> <a href="https://hackage.haskell.org/package/wai-3.0.2/docs/Network-Wai.html#t:Response">Response</a> -&gt; <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/System-IO.html#t:IO">IO</a> <a href="https://hackage.haskell.org/package/wai-3.0.2/docs/Network-Wai.html#t:ResponseReceived">ResponseReceived</a>) -&gt; <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/System-IO.html#t:IO">IO</a> <a href="https://hackage.haskell.org/package/wai-3.0.2/docs/Network-Wai.html#t:ResponseReceived">ResponseReceived</a></li><li class="src short"><span class="keyword">class</span> <a href="#t:HasServer">HasServer</a> layout <span class="keyword">where</span><ul class="subs"><li><span class="keyword">type</span> <a href="#t:Server">Server</a> layout :: *</li><li><a href="#v:route">route</a> :: <a href="Servant.html#t:Proxy">Proxy</a> layout -&gt; <a href="Servant-Server.html#t:Server">Server</a> layout -&gt; <a href="Servant-Server.html#t:RoutingApplication">RoutingApplication</a></li></ul></li></ul></div><div id="interface"><h1 id="g:1">Implementing Servers</h1><div class="top"><p class="src"><a name="v:serve" class="def">serve</a> :: <a href="Servant-Server.html#t:HasServer">HasServer</a> layout =&gt; <a href="Servant.html#t:Proxy">Proxy</a> layout -&gt; <a href="Servant-Server.html#t:Server">Server</a> layout -&gt; <a href="https://hackage.haskell.org/package/wai-3.0.2/docs/Network-Wai.html#t:Application">Application</a> <a href="src/Servant-Server.html#serve" class="link">Source</a></p><div class="doc"><p><code><a href="Servant-Server.html#v:serve">serve</a></code> allows you to implement an API and produce a wai <code><a href="https://hackage.haskell.org/package/wai-3.0.2/docs/Network-Wai.html#t:Application">Application</a></code>.</p><p>Example:</p><pre>type MyApi = &quot;books&quot; :&gt; Get [Book] -- GET /books
6+ :&lt;|&gt; &quot;books&quot; :&gt; ReqBody Book :&gt; Post Book -- POST /books
7+
8+server :: Server MyApi
9+server = listAllBooks :&lt;|&gt; postBook
10+ where listAllBooks = ...
11+ postBook book = ...
12+
13+app :: Application
14+app = serve myApi server
15+
16+main :: IO ()
17+main = Network.Wai.Handler.Warp.run 8080 app</pre></div></div><div class="top"><p class="src"><a name="v:toApplication" class="def">toApplication</a> :: <a href="Servant-Server.html#t:RoutingApplication">RoutingApplication</a> -&gt; <a href="https://hackage.haskell.org/package/wai-3.0.2/docs/Network-Wai.html#t:Application">Application</a> <a href="src/Servant-Server.html#toApplication" class="link">Source</a></p></div><h1 id="g:2">Route mismatch</h1><div class="top"><p class="src"><span class="keyword">data</span> <a name="t:RouteMismatch" class="def">RouteMismatch</a> <a href="src/Servant-Server.html#RouteMismatch" class="link">Source</a></p><div class="subs constructors"><p class="caption">Constructors</p><table><tr><td class="src"><a name="v:NotFound" class="def">NotFound</a></td><td class="doc"><p>the usual &quot;not found&quot; error</p></td></tr><tr><td class="src"><a name="v:WrongMethod" class="def">WrongMethod</a></td><td class="doc"><p>a more informative &quot;you just got the HTTP method wrong&quot; error</p></td></tr><tr><td class="src"><a name="v:InvalidBody" class="def">InvalidBody</a></td><td class="doc"><p>an even more informative &quot;your json request body wasn't valid&quot; error</p></td></tr></table></div><div class="subs instances"><p id="control.i:RouteMismatch" class="caption collapser" onclick="toggleSection('i:RouteMismatch')">Instances</p><div id="section.i:RouteMismatch" class="show"><table><tr><td class="src"><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Eq.html#t:Eq">Eq</a> <a href="Servant-Server.html#t:RouteMismatch">RouteMismatch</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Text-Show.html#t:Show">Show</a> <a href="Servant-Server.html#t:RouteMismatch">RouteMismatch</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Monoid.html#t:Monoid">Monoid</a> <a href="Servant-Server.html#t:RouteMismatch">RouteMismatch</a></td><td class="doc"><pre>&gt; mempty = NotFound
18+&gt;
19+&gt; NotFound <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Monoid.html#v:mappend">mappend</a></code> x = x
20+&gt; WrongMethod <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Monoid.html#v:mappend">mappend</a></code> InvalidBody = InvalidBody
21+&gt; WrongMethod <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Monoid.html#v:mappend">mappend</a></code> _ = WrongMethod
22+&gt; InvalidBody <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Monoid.html#v:mappend">mappend</a></code> _ = InvalidBody
23+</pre></td></tr></table></div></div></div><div class="top"><p class="src"><span class="keyword">newtype</span> <a name="t:RouteResult" class="def">RouteResult</a> a <a href="src/Servant-Server.html#RouteResult" class="link">Source</a></p><div class="doc"><p>A wrapper around <code><code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Either.html#t:Either">Either</a></code> <code><a href="Servant-Server.html#t:RouteMismatch">RouteMismatch</a></code> a</code>.</p></div><div class="subs constructors"><p class="caption">Constructors</p><table><tr><td class="src"><a name="v:RR" class="def">RR</a></td><td class="doc empty">&nbsp;</td></tr><tr><td colspan="2"><div class="subs fields"><p class="caption">Fields</p><dl><dt class="src"><a name="v:routeResult" class="def">routeResult</a> :: <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Either.html#t:Either">Either</a> <a href="Servant-Server.html#t:RouteMismatch">RouteMismatch</a> a</dt><dd class="doc empty">&nbsp;</dd></dl><div class="clear"></div></div></td></tr></table></div><div class="subs instances"><p id="control.i:RouteResult" class="caption collapser" onclick="toggleSection('i:RouteResult')">Instances</p><div id="section.i:RouteResult" class="show"><table><tr><td class="src"><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Eq.html#t:Eq">Eq</a> a =&gt; <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Eq.html#t:Eq">Eq</a> (<a href="Servant-Server.html#t:RouteResult">RouteResult</a> a)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Text-Show.html#t:Show">Show</a> a =&gt; <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Text-Show.html#t:Show">Show</a> (<a href="Servant-Server.html#t:RouteResult">RouteResult</a> a)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Monoid.html#t:Monoid">Monoid</a> (<a href="Servant-Server.html#t:RouteResult">RouteResult</a> a)</td><td class="doc"><p>If we get a <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Either.html#v:Right">Right</a></code>, it has precedence over everything else.</p><p>This in particular means that if we could get several <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Either.html#v:Right">Right</a></code>s,
24+ only the first we encounter would be taken into account.</p></td></tr></table></div></div></div><div class="top"><p class="src"><a name="v:failWith" class="def">failWith</a> :: <a href="Servant-Server.html#t:RouteMismatch">RouteMismatch</a> -&gt; <a href="Servant-Server.html#t:RouteResult">RouteResult</a> a <a href="src/Servant-Server.html#failWith" class="link">Source</a></p></div><div class="top"><p class="src"><a name="v:succeedWith" class="def">succeedWith</a> :: a -&gt; <a href="Servant-Server.html#t:RouteResult">RouteResult</a> a <a href="src/Servant-Server.html#succeedWith" class="link">Source</a></p></div><div class="top"><p class="src"><a name="v:isMismatch" class="def">isMismatch</a> :: <a href="Servant-Server.html#t:RouteResult">RouteResult</a> a -&gt; <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#t:Bool">Bool</a> <a href="src/Servant-Server.html#isMismatch" class="link">Source</a></p></div><div class="top"><p class="src"><span class="keyword">type</span> <a name="t:RoutingApplication" class="def">RoutingApplication</a> <a href="src/Servant-Server.html#RoutingApplication" class="link">Source</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">&nbsp;= <a href="https://hackage.haskell.org/package/wai-3.0.2/docs/Network-Wai.html#t:Request">Request</a></td><td class="doc"><p>the request, the field <code><a href="https://hackage.haskell.org/package/wai-3.0.2/docs/Network-Wai.html#v:pathInfo">pathInfo</a></code> may be modified by url routing</p></td></tr><tr><td class="src">-&gt; (<a href="Servant-Server.html#t:RouteResult">RouteResult</a> <a href="https://hackage.haskell.org/package/wai-3.0.2/docs/Network-Wai.html#t:Response">Response</a> -&gt; <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/System-IO.html#t:IO">IO</a> <a href="https://hackage.haskell.org/package/wai-3.0.2/docs/Network-Wai.html#t:ResponseReceived">ResponseReceived</a>)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src">-&gt; <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/System-IO.html#t:IO">IO</a> <a href="https://hackage.haskell.org/package/wai-3.0.2/docs/Network-Wai.html#t:ResponseReceived">ResponseReceived</a></td><td class="doc empty">&nbsp;</td></tr></table></div></div><div class="top"><p class="src"><span class="keyword">class</span> <a name="t:HasServer" class="def">HasServer</a> layout <span class="keyword">where</span> <a href="src/Servant-Server.html#HasServer" class="link">Source</a></p><div class="subs associated-types"><p class="caption">Associated Types</p><p class="src"><span class="keyword">type</span> <a name="t:Server" class="def">Server</a> layout :: * <a href="src/Servant-Server.html#Server" class="link">Source</a></p></div><div class="subs methods"><p class="caption">Methods</p><p class="src"><a name="v:route" class="def">route</a> :: <a href="Servant.html#t:Proxy">Proxy</a> layout -&gt; <a href="Servant-Server.html#t:Server">Server</a> layout -&gt; <a href="Servant-Server.html#t:RoutingApplication">RoutingApplication</a> <a href="src/Servant-Server.html#route" class="link">Source</a></p></div><div class="subs instances"><p id="control.i:HasServer" class="caption collapser" onclick="toggleSection('i:HasServer')">Instances</p><div id="section.i:HasServer" class="show"><table><tr><td class="src"><a href="Servant-Server.html#t:HasServer">HasServer</a> <a href="Servant-API-Delete.html#t:Delete">Delete</a></td><td class="doc"><p>If you have a <code><a href="Servant-API-Delete.html#t:Delete">Delete</a></code> endpoint in your API,
25+ the handler for this endpoint is meant to delete
26+ a resource.</p><p>The code of the handler will, just like
27+ for <code><a href="Servant-API-Get.html#t:Get">Get</a></code>, <code><a href="Servant-API-Post.html#t:Post">Post</a></code> and
28+ <code><a href="Servant-API-Put.html#t:Put">Put</a></code>, run in <code>EitherT (Int, String) IO ()</code>.
29+ The <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Int.html#t:Int">Int</a></code> represents the status code and the <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a></code> a message
30+ to be returned. You can use <code><a href="https://hackage.haskell.org/package/either-4.3.2/docs/Control-Monad-Trans-Either.html#v:left">left</a></code> to
31+ painlessly error out if the conditions for a successful deletion
32+ are not met.</p></td></tr><tr><td class="src"><a href="Servant-Server.html#t:HasServer">HasServer</a> <a href="Servant-API-Raw.html#t:Raw">Raw</a></td><td class="doc"><p>Just pass the request to the underlying application and serve its response.</p><p>Example:</p><pre>type MyApi = &quot;images&quot; :&gt; Raw
33+
34+server :: Server MyApi
35+server = serveDirectory &quot;/var/www/images&quot;</pre></td></tr><tr><td class="src"><a href="https://hackage.haskell.org/package/aeson-0.8.0.2/docs/Data-Aeson-Types.html#t:ToJSON">ToJSON</a> result =&gt; <a href="Servant-Server.html#t:HasServer">HasServer</a> (<a href="Servant-API-Get.html#t:Get">Get</a> result)</td><td class="doc"><p>When implementing the handler for a <code><a href="Servant-API-Get.html#t:Get">Get</a></code> endpoint,
36+ just like for <code><a href="Servant-API-Delete.html#t:Delete">Delete</a></code>, <code><a href="Servant-API-Post.html#t:Post">Post</a></code>
37+ and <code><a href="Servant-API-Put.html#t:Put">Put</a></code>, the handler code runs in the
38+ <code>EitherT (Int, String) IO</code> monad, where the <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Int.html#t:Int">Int</a></code> represents
39+ the status code and the <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a></code> a message, returned in case of
40+ failure. You can quite handily use <code><a href="Control-Monad-Trans-EitherT.html#v:left">left</a></code>
41+ to quickly fail if some conditions are not met.</p><p>If successfully returning a value, we just require that its type has
42+ a <code><a href="https://hackage.haskell.org/package/aeson-0.8.0.2/docs/Data-Aeson-Types.html#t:ToJSON">ToJSON</a></code> instance and servant takes care of encoding it for you,
43+ yielding status code 200 along the way.</p></td></tr><tr><td class="src"><a href="https://hackage.haskell.org/package/aeson-0.8.0.2/docs/Data-Aeson-Types.html#t:ToJSON">ToJSON</a> a =&gt; <a href="Servant-Server.html#t:HasServer">HasServer</a> (<a href="Servant-API-Post.html#t:Post">Post</a> a)</td><td class="doc"><p>When implementing the handler for a <code><a href="Servant-API-Post.html#t:Post">Post</a></code> endpoint,
44+ just like for <code><a href="Servant-API-Delete.html#t:Delete">Delete</a></code>, <code><a href="Servant-API-Get.html#t:Get">Get</a></code>
45+ and <code><a href="Servant-API-Put.html#t:Put">Put</a></code>, the handler code runs in the
46+ <code>EitherT (Int, String) IO</code> monad, where the <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Int.html#t:Int">Int</a></code> represents
47+ the status code and the <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a></code> a message, returned in case of
48+ failure. You can quite handily use <code><a href="Control-Monad-Trans-EitherT.html#v:left">left</a></code>
49+ to quickly fail if some conditions are not met.</p><p>If successfully returning a value, we just require that its type has
50+ a <code><a href="https://hackage.haskell.org/package/aeson-0.8.0.2/docs/Data-Aeson-Types.html#t:ToJSON">ToJSON</a></code> instance and servant takes care of encoding it for you,
51+ yielding status code 201 along the way.</p></td></tr><tr><td class="src"><a href="https://hackage.haskell.org/package/aeson-0.8.0.2/docs/Data-Aeson-Types.html#t:ToJSON">ToJSON</a> a =&gt; <a href="Servant-Server.html#t:HasServer">HasServer</a> (<a href="Servant-API-Put.html#t:Put">Put</a> a)</td><td class="doc"><p>When implementing the handler for a <code><a href="Servant-API-Put.html#t:Put">Put</a></code> endpoint,
52+ just like for <code><a href="Servant-API-Delete.html#t:Delete">Delete</a></code>, <code><a href="Servant-API-Get.html#t:Get">Get</a></code>
53+ and <code><a href="Servant-API-Post.html#t:Post">Post</a></code>, the handler code runs in the
54+ <code>EitherT (Int, String) IO</code> monad, where the <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Int.html#t:Int">Int</a></code> represents
55+ the status code and the <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a></code> a message, returned in case of
56+ failure. You can quite handily use <code><a href="Control-Monad-Trans-EitherT.html#v:left">left</a></code>
57+ to quickly fail if some conditions are not met.</p><p>If successfully returning a value, we just require that its type has
58+ a <code><a href="https://hackage.haskell.org/package/aeson-0.8.0.2/docs/Data-Aeson-Types.html#t:ToJSON">ToJSON</a></code> instance and servant takes care of encoding it for you,
59+ yielding status code 200 along the way.</p></td></tr><tr><td class="src">(<a href="Servant-Server.html#t:HasServer">HasServer</a> a, <a href="Servant-Server.html#t:HasServer">HasServer</a> b) =&gt; <a href="Servant-Server.html#t:HasServer">HasServer</a> (<a href="Servant-API-Alternative.html#t::-60--124--62-">(:&lt;|&gt;)</a> a b)</td><td class="doc"><p>A server for <code>a <code><a href="Servant-API-Alternative.html#t::-60--124--62-">:&lt;|&gt;</a></code> b</code> first tries to match the request again the route
60+ represented by <code>a</code> and if it fails tries <code>b</code>. You must provide a request
61+ handler for each route.</p><pre>type MyApi = &quot;books&quot; :&gt; Get [Book] -- GET /books
62+ :&lt;|&gt; &quot;books&quot; :&gt; ReqBody Book :&gt; Post Book -- POST /books
63+
64+server :: Server MyApi
65+server = listAllBooks :&lt;|&gt; postBook
66+ where listAllBooks = ...
67+ postBook book = ...</pre></td></tr><tr><td class="src">(<a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:KnownSymbol">KnownSymbol</a> capture, <a href="Servant-Common-Text.html#t:FromText">FromText</a> a, <a href="Servant-Server.html#t:HasServer">HasServer</a> sublayout) =&gt; <a href="Servant-Server.html#t:HasServer">HasServer</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> * (<a href="Servant-API-Capture.html#t:Capture">Capture</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a> * capture a) sublayout)</td><td class="doc"><p>If you use <code><a href="Servant-API-Capture.html#t:Capture">Capture</a></code> in one of the endpoints for your API,
68+ this automatically requires your server-side handler to be a function
69+ that takes an argument of the type specified by the <code><a href="Servant-API-Capture.html#t:Capture">Capture</a></code>.
70+ This lets servant worry about getting it from the URL and turning
71+ it into a value of the type you specify.</p><p>You can control how it'll be converted from <code><a href="https://hackage.haskell.org/package/text-1.2.0.0/docs/Data-Text.html#t:Text">Text</a></code> to your type
72+ by simply providing an instance of <code><a href="Servant-Common-Text.html#t:FromText">FromText</a></code> for your type.</p><p>Example:</p><pre>type MyApi = &quot;books&quot; :&gt; Capture &quot;isbn&quot; Text :&gt; Get Book
73+
74+server :: Server MyApi
75+server = getBook
76+ where getBook :: Text -&gt; EitherT (Int, String) IO Book
77+ getBook isbn = ...</pre></td></tr><tr><td class="src">(<a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:KnownSymbol">KnownSymbol</a> sym, <a href="Servant-Server.html#t:HasServer">HasServer</a> sublayout) =&gt; <a href="Servant-Server.html#t:HasServer">HasServer</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> * (<a href="Servant-API-QueryParam.html#t:QueryFlag">QueryFlag</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a> sym) sublayout)</td><td class="doc"><p>If you use <code><code><a href="Servant-API-QueryParam.html#t:QueryFlag">QueryFlag</a></code> &quot;published&quot;</code> in one of the endpoints for your API,
78+ this automatically requires your server-side handler to be a function
79+ that takes an argument of type <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#t:Bool">Bool</a></code>.</p><p>Example:</p><pre>type MyApi = &quot;books&quot; :&gt; QueryFlag &quot;published&quot; :&gt; Get [Book]
80+
81+server :: Server MyApi
82+server = getBooks
83+ where getBooks :: Bool -&gt; EitherT (Int, String) IO [Book]
84+ getBooks onlyPublished = ...return all books, or only the ones that are already published, depending on the argument...</pre></td></tr><tr><td class="src">(<a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:KnownSymbol">KnownSymbol</a> sym, <a href="Servant-Common-Text.html#t:FromText">FromText</a> a, <a href="Servant-Server.html#t:HasServer">HasServer</a> sublayout) =&gt; <a href="Servant-Server.html#t:HasServer">HasServer</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> * (<a href="Servant-API-QueryParam.html#t:QueryParams">QueryParams</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a> * sym a) sublayout)</td><td class="doc"><p>If you use <code><code><a href="Servant-API-QueryParam.html#t:QueryParams">QueryParams</a></code> &quot;authors&quot; Text</code> in one of the endpoints for your API,
85+ this automatically requires your server-side handler to be a function
86+ that takes an argument of type <code>[<code>Text</code>]</code>.</p><p>This lets servant worry about looking up 0 or more values in the query string
87+ associated to <code>authors</code> and turning each of them into a value of
88+ the type you specify.</p><p>You can control how the individual values are converted from <code>Text</code> to your type
89+ by simply providing an instance of <code><a href="Servant-Common-Text.html#t:FromText">FromText</a></code> for your type.</p><p>Example:</p><pre>type MyApi = &quot;books&quot; :&gt; QueryParams &quot;authors&quot; Text :&gt; Get [Book]
90+
91+server :: Server MyApi
92+server = getBooksBy
93+ where getBooksBy :: [Text] -&gt; EitherT (Int, String) IO [Book]
94+ getBooksBy authors = ...return all books by these authors...</pre></td></tr><tr><td class="src">(<a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:KnownSymbol">KnownSymbol</a> sym, <a href="Servant-Common-Text.html#t:FromText">FromText</a> a, <a href="Servant-Server.html#t:HasServer">HasServer</a> sublayout) =&gt; <a href="Servant-Server.html#t:HasServer">HasServer</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> * (<a href="Servant-API-QueryParam.html#t:QueryParam">QueryParam</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a> * sym a) sublayout)</td><td class="doc"><p>If you use <code><code><a href="Servant-API-QueryParam.html#t:QueryParam">QueryParam</a></code> &quot;author&quot; Text</code> in one of the endpoints for your API,
95+ this automatically requires your server-side handler to be a function
96+ that takes an argument of type <code><code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Maybe.html#t:Maybe">Maybe</a></code> <code>Text</code></code>.</p><p>This lets servant worry about looking it up in the query string
97+ and turning it into a value of the type you specify, enclosed
98+ in <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Maybe.html#t:Maybe">Maybe</a></code>, because it may not be there and servant would then
99+ hand you <code><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Maybe.html#v:Nothing">Nothing</a></code>.</p><p>You can control how it'll be converted from <code>Text</code> to your type
100+ by simply providing an instance of <code><a href="Servant-Common-Text.html#t:FromText">FromText</a></code> for your type.</p><p>Example:</p><pre>type MyApi = &quot;books&quot; :&gt; QueryParam &quot;author&quot; Text :&gt; Get [Book]
101+
102+server :: Server MyApi
103+server = getBooksBy
104+ where getBooksBy :: Maybe Text -&gt; EitherT (Int, String) IO [Book]
105+ getBooksBy Nothing = ...return all books...
106+ getBooksBy (Just author) = ...return books by the given author...</pre></td></tr><tr><td class="src">(<a href="https://hackage.haskell.org/package/aeson-0.8.0.2/docs/Data-Aeson-Types.html#t:FromJSON">FromJSON</a> a, <a href="Servant-Server.html#t:HasServer">HasServer</a> sublayout) =&gt; <a href="Servant-Server.html#t:HasServer">HasServer</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> * (<a href="Servant-API-ReqBody.html#t:ReqBody">ReqBody</a> * a) sublayout)</td><td class="doc"><p>If you use <code><a href="Servant-API-ReqBody.html#t:ReqBody">ReqBody</a></code> in one of the endpoints for your API,
107+ this automatically requires your server-side handler to be a function
108+ that takes an argument of the type specified by <code><a href="Servant-API-ReqBody.html#t:ReqBody">ReqBody</a></code>.
109+ This lets servant worry about extracting it from the request and turning
110+ it into a value of the type you specify.</p><p>All it asks is for a <code><a href="https://hackage.haskell.org/package/aeson-0.8.0.2/docs/Data-Aeson-Types.html#t:FromJSON">FromJSON</a></code> instance.</p><p>Example:</p><pre>type MyApi = &quot;books&quot; :&gt; ReqBody Book :&gt; Post Book
111+
112+server :: Server MyApi
113+server = postBook
114+ where postBook :: Book -&gt; EitherT (Int, String) IO Book
115+ postBook book = ...insert into your db...</pre></td></tr><tr><td class="src">(<a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:KnownSymbol">KnownSymbol</a> path, <a href="Servant-Server.html#t:HasServer">HasServer</a> sublayout) =&gt; <a href="Servant-Server.html#t:HasServer">HasServer</a> (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a> path sublayout)</td><td class="doc"><p>Make sure the incoming request starts with <code>&quot;/path&quot;</code>, strip it and
116+ pass the rest of the request path to <code>sublayout</code>.</p></td></tr></table></div></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.15.0</p></div></body></html>
Servant-Utils-Links.htmlnew file+23
@@ -0,0 +1,23 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.Utils.Links</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();setSynopsis("mini_Servant-Utils-Links.html");};
3+//]]>
4+</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="src/Servant-Utils-Links.html">Source</a></li><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">servant-0.2: A family of combinators for defining webservices APIs and serving them</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr><tr><th>Language</th><td>Haskell2010</td></tr></table><p class="caption">Servant.Utils.Links</p></div><div id="description"><p class="caption">Description</p><div class="doc"><p>Type safe internal links.</p><p>Provides the function <code><a href="Servant-Utils-Links.html#v:mkLink">mkLink</a></code>:</p><pre> type API = Proxy (&quot;hello&quot; :&gt; Get Int
5+ :<a href="|">|</a> &quot;bye&quot; :&gt; QueryParam &quot;name&quot; String :&gt; Post Bool)
6+
7+ api :: API
8+ api = proxy
9+
10+ link1 :: Proxy (&quot;hello&quot; :&gt; Get Int)
11+ link1 = proxy
12+
13+ link2 :: Proxy (&quot;hello&quot; :&gt; Delete)
14+ link2 = proxy
15+
16+ mkLink link1 API -- typechecks, returns 'Link &quot;/hello&quot;'
17+
18+ mkLink link2 API -- doesn't typecheck
19+</pre><p>That is, <code><a href="Servant-Utils-Links.html#v:mkLink">mkLink</a></code> takes two arguments, a link proxy and a sitemap, and
20+ returns a <code><a href="Servant-Utils-Links.html#t:Link">Link</a></code>, but only typechecks if the link proxy is a valid link,
21+ and part of the sitemap.</p><p><strong>N.B.:</strong> <code><a href="Servant-Utils-Links.html#v:mkLink">mkLink</a></code> assumes a capture matches any string (without slashes).</p></div></div><div id="synopsis"><p id="control.syn" class="caption expander" onclick="toggleSection('syn')">Synopsis</p><ul id="section.syn" class="hide" onclick="toggleSection('syn')"><li class="src short"><span class="keyword">type family</span> <a href="#t:Or">Or</a> a b</li><li class="src short"><span class="keyword">type family</span> <a href="#t:And">And</a> a b</li><li class="src short"><span class="keyword">type family</span> <a href="#t:IsElem">IsElem</a> a s</li><li class="src short"><span class="keyword">type family</span> <a href="#t:IsLink-39--39-">IsLink''</a> l</li><li class="src short"><span class="keyword">type family</span> <a href="#t:IsLink-39-">IsLink'</a> e</li><li class="src short"><span class="keyword">type family</span> <a href="#t:IsLink">IsLink</a> e</li><li class="src short"><span class="keyword">class</span> <a href="#t:ValidLinkIn">ValidLinkIn</a> f s <span class="keyword">where</span><ul class="subs"><li><a href="#v:mkLink">mkLink</a> :: f -&gt; s -&gt; <a href="Servant-Utils-Links.html#t:Link">Link</a></li></ul></li><li class="src short"><span class="keyword">data</span> <a href="#t:Link">Link</a> = <a href="#v:Link">Link</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a></li><li class="src short"><span class="keyword">class</span> <a href="#t:VLinkHelper">VLinkHelper</a> f <span class="keyword">where</span><ul class="subs"><li><a href="#v:vlh">vlh</a> :: <span class="keyword">forall</span> proxy. proxy f -&gt; <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a></li></ul></li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><span class="keyword">type family</span> <a name="t:Or" class="def">Or</a> a b <a href="src/Servant-Utils-Links.html#Or" class="link">Source</a></p><div class="subs equations"><p class="caption">Equations</p><table><tr><td class="src"><a href="Servant-Utils-Links.html#t:Or">Or</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#v:False">False</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#v:False">False</a> = <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#v:False">False</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Utils-Links.html#t:Or">Or</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#v:True">True</a> b = <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#v:True">True</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Utils-Links.html#t:Or">Or</a> a <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#v:True">True</a> = <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#v:True">True</a></td><td class="doc empty">&nbsp;</td></tr></table></div></div><div class="top"><p class="src"><span class="keyword">type family</span> <a name="t:And" class="def">And</a> a b <a href="src/Servant-Utils-Links.html#And" class="link">Source</a></p><div class="subs equations"><p class="caption">Equations</p><table><tr><td class="src"><a href="Servant-Utils-Links.html#t:And">And</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#v:True">True</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#v:True">True</a> = <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#v:True">True</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Utils-Links.html#t:And">And</a> a <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#v:False">False</a> = <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#v:False">False</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Utils-Links.html#t:And">And</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#v:False">False</a> b = <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#v:False">False</a></td><td class="doc empty">&nbsp;</td></tr></table></div></div><div class="top"><p class="src"><span class="keyword">type family</span> <a name="t:IsElem" class="def">IsElem</a> a s <a href="src/Servant-Utils-Links.html#IsElem" class="link">Source</a></p><div class="subs equations"><p class="caption">Equations</p><table><tr><td class="src"><a href="Servant-Utils-Links.html#t:IsElem">IsElem</a> e (sa <a href="Servant-API-Alternative.html#t::-60--124--62-">:&lt;|&gt;</a> sb) = <a href="Servant-Utils-Links.html#t:Or">Or</a> (<a href="Servant-Utils-Links.html#t:IsElem">IsElem</a> e sa) (<a href="Servant-Utils-Links.html#t:IsElem">IsElem</a> e sb)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Utils-Links.html#t:IsElem">IsElem</a> (e <a href="Servant-API-Sub.html#t::-62-">:&gt;</a> sa) (e <a href="Servant-API-Sub.html#t::-62-">:&gt;</a> sb) = <a href="Servant-Utils-Links.html#t:IsElem">IsElem</a> sa sb</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Utils-Links.html#t:IsElem">IsElem</a> (e <a href="Servant-API-Sub.html#t::-62-">:&gt;</a> sa) (<a href="Servant-API-Capture.html#t:Capture">Capture</a> x y <a href="Servant-API-Sub.html#t::-62-">:&gt;</a> sb) = <a href="Servant-Utils-Links.html#t:IsElem">IsElem</a> sa sb</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Utils-Links.html#t:IsElem">IsElem</a> sa (<a href="Servant-API-ReqBody.html#t:ReqBody">ReqBody</a> x <a href="Servant-API-Sub.html#t::-62-">:&gt;</a> sb) = <a href="Servant-Utils-Links.html#t:IsElem">IsElem</a> sa sb</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Utils-Links.html#t:IsElem">IsElem</a> sa (<a href="Servant-API-QueryParam.html#t:QueryParam">QueryParam</a> x y <a href="Servant-API-Sub.html#t::-62-">:&gt;</a> sb) = <a href="Servant-Utils-Links.html#t:IsElem">IsElem</a> sa sb</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Utils-Links.html#t:IsElem">IsElem</a> e e = <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#v:True">True</a></td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Utils-Links.html#t:IsElem">IsElem</a> e a = <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#v:False">False</a></td><td class="doc empty">&nbsp;</td></tr></table></div></div><div class="top"><p class="src"><span class="keyword">type family</span> <a name="t:IsLink-39--39-" class="def">IsLink''</a> l <a href="src/Servant-Utils-Links.html#IsLink%27%27" class="link">Source</a></p><div class="subs equations"><p class="caption">Equations</p><table><tr><td class="src"><a href="Servant-Utils-Links.html#t:IsLink-39--39-">IsLink''</a> (e <a href="Servant-API-Sub.html#t::-62-">:&gt;</a> <a href="Servant-API-Get.html#t:Get">Get</a> x) = <a href="Servant-Utils-Links.html#t:IsLink-39-">IsLink'</a> e</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Utils-Links.html#t:IsLink-39--39-">IsLink''</a> (e <a href="Servant-API-Sub.html#t::-62-">:&gt;</a> <a href="Servant-API-Post.html#t:Post">Post</a> x) = <a href="Servant-Utils-Links.html#t:IsLink-39-">IsLink'</a> e</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Utils-Links.html#t:IsLink-39--39-">IsLink''</a> (e <a href="Servant-API-Sub.html#t::-62-">:&gt;</a> <a href="Servant-API-Put.html#t:Put">Put</a> x) = <a href="Servant-Utils-Links.html#t:IsLink-39-">IsLink'</a> e</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Utils-Links.html#t:IsLink-39--39-">IsLink''</a> (e <a href="Servant-API-Sub.html#t::-62-">:&gt;</a> <a href="Servant-API-Delete.html#t:Delete">Delete</a>) = <a href="Servant-Utils-Links.html#t:IsLink-39-">IsLink'</a> e</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Utils-Links.html#t:IsLink-39--39-">IsLink''</a> a = <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#v:False">False</a></td><td class="doc empty">&nbsp;</td></tr></table></div></div><div class="top"><p class="src"><span class="keyword">type family</span> <a name="t:IsLink-39-" class="def">IsLink'</a> e <a href="src/Servant-Utils-Links.html#IsLink%27" class="link">Source</a></p><div class="subs equations"><p class="caption">Equations</p><table><tr><td class="src"><a href="Servant-Utils-Links.html#t:IsLink-39-">IsLink'</a> (f :: <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a>) = <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#v:True">True</a></td><td class="doc empty">&nbsp;</td></tr></table></div></div><div class="top"><p class="src"><span class="keyword">type family</span> <a name="t:IsLink" class="def">IsLink</a> e <a href="src/Servant-Utils-Links.html#IsLink" class="link">Source</a></p><div class="subs equations"><p class="caption">Equations</p><table><tr><td class="src"><a href="Servant-Utils-Links.html#t:IsLink">IsLink</a> (a <a href="Servant-API-Sub.html#t::-62-">:&gt;</a> b) = <a href="Servant-Utils-Links.html#t:Or">Or</a> (<a href="Servant-Utils-Links.html#t:And">And</a> (<a href="Servant-Utils-Links.html#t:IsLink-39-">IsLink'</a> a) (<a href="Servant-Utils-Links.html#t:IsLink-39--39-">IsLink''</a> b)) (<a href="Servant-Utils-Links.html#t:IsLink-39--39-">IsLink''</a> (a <a href="Servant-API-Sub.html#t::-62-">:&gt;</a> b))</td><td class="doc empty">&nbsp;</td></tr></table></div></div><div class="top"><p class="src"><span class="keyword">class</span> <a name="t:ValidLinkIn" class="def">ValidLinkIn</a> f s <span class="keyword">where</span> <a href="src/Servant-Utils-Links.html#ValidLinkIn" class="link">Source</a></p><div class="doc"><p>The 'ValidLinkIn f s' constraint holds when <code>s</code> is an API that
22+ contains <code>f</code>, and <code>f</code> is a link.</p></div><div class="subs methods"><p class="caption">Methods</p><p class="src"><a name="v:mkLink" class="def">mkLink</a> <a href="src/Servant-Utils-Links.html#mkLink" class="link">Source</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">:: f</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src">-&gt; s</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src">-&gt; <a href="Servant-Utils-Links.html#t:Link">Link</a></td><td class="doc"><p>This function will only typecheck if <code>f</code>
23+ is an URI within <code>s</code></p></td></tr></table></div></div><div class="subs instances"><p id="control.i:ValidLinkIn" class="caption collapser" onclick="toggleSection('i:ValidLinkIn')">Instances</p><div id="section.i:ValidLinkIn" class="show"><table><tr><td class="src">((~) <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#t:Bool">Bool</a> (<a href="Servant-Utils-Links.html#t:IsElem">IsElem</a> f s) <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#v:True">True</a>, (~) <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#t:Bool">Bool</a> (<a href="Servant-Utils-Links.html#t:IsLink">IsLink</a> f) <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Bool.html#v:True">True</a>, <a href="Servant-Utils-Links.html#t:VLinkHelper">VLinkHelper</a> * f) =&gt; <a href="Servant-Utils-Links.html#t:ValidLinkIn">ValidLinkIn</a> f s</td><td class="doc empty">&nbsp;</td></tr></table></div></div></div><div class="top"><p class="src"><span class="keyword">data</span> <a name="t:Link" class="def">Link</a> <a href="src/Servant-Utils-Links.html#Link" class="link">Source</a></p><div class="subs constructors"><p class="caption">Constructors</p><table><tr><td class="src"><a name="v:Link" class="def">Link</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a></td><td class="doc empty">&nbsp;</td></tr></table></div><div class="subs instances"><p id="control.i:Link" class="caption collapser" onclick="toggleSection('i:Link')">Instances</p><div id="section.i:Link" class="show"><table><tr><td class="src"><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Text-Show.html#t:Show">Show</a> <a href="Servant-Utils-Links.html#t:Link">Link</a></td><td class="doc empty">&nbsp;</td></tr></table></div></div></div><div class="top"><p class="src"><span class="keyword">class</span> <a name="t:VLinkHelper" class="def">VLinkHelper</a> f <span class="keyword">where</span> <a href="src/Servant-Utils-Links.html#VLinkHelper" class="link">Source</a></p><div class="subs methods"><p class="caption">Methods</p><p class="src"><a name="v:vlh" class="def">vlh</a> :: <span class="keyword">forall</span> proxy. proxy f -&gt; <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-String.html#t:String">String</a> <a href="src/Servant-Utils-Links.html#vlh" class="link">Source</a></p></div><div class="subs instances"><p id="control.i:VLinkHelper" class="caption collapser" onclick="toggleSection('i:VLinkHelper')">Instances</p><div id="section.i:VLinkHelper" class="show"><table><tr><td class="src"><a href="Servant-Utils-Links.html#t:VLinkHelper">VLinkHelper</a> * (<a href="Servant-API-Get.html#t:Get">Get</a> x)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="Servant-Utils-Links.html#t:VLinkHelper">VLinkHelper</a> * (<a href="Servant-API-Post.html#t:Post">Post</a> x)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src">(<a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:KnownSymbol">KnownSymbol</a> s, <a href="Servant-Utils-Links.html#t:VLinkHelper">VLinkHelper</a> * e) =&gt; <a href="Servant-Utils-Links.html#t:VLinkHelper">VLinkHelper</a> * (<a href="Servant-API-Sub.html#t::-62-">(:&gt;)</a> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-TypeLits.html#t:Symbol">Symbol</a> s e)</td><td class="doc empty">&nbsp;</td></tr></table></div></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.15.0</p></div></body></html>
Servant-Utils-StaticFiles.htmlnew file+15
@@ -0,0 +1,15 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.Utils.StaticFiles</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();setSynopsis("mini_Servant-Utils-StaticFiles.html");};
3+//]]>
4+</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="src/Servant-Utils-StaticFiles.html">Source</a></li><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">servant-0.2: A family of combinators for defining webservices APIs and serving them</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr><tr><th>Language</th><td>Haskell2010</td></tr></table><p class="caption">Servant.Utils.StaticFiles</p></div><div id="description"><p class="caption">Description</p><div class="doc"><p>This module defines a sever-side handler that lets you serve static files.</p><ul><li><code><a href="Servant-Utils-StaticFiles.html#v:serveDirectory">serveDirectory</a></code> lets you serve anything that lives under a particular
5+ directory on your filesystem.</li></ul></div></div><div id="synopsis"><p id="control.syn" class="caption expander" onclick="toggleSection('syn')">Synopsis</p><ul id="section.syn" class="hide" onclick="toggleSection('syn')"><li class="src short"><a href="#v:serveDirectory">serveDirectory</a> :: <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/System-IO.html#t:FilePath">FilePath</a> -&gt; <a href="Servant-Server.html#t:Server">Server</a> <a href="Servant-API-Raw.html#t:Raw">Raw</a></li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><a name="v:serveDirectory" class="def">serveDirectory</a> :: <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/System-IO.html#t:FilePath">FilePath</a> -&gt; <a href="Servant-Server.html#t:Server">Server</a> <a href="Servant-API-Raw.html#t:Raw">Raw</a> <a href="src/Servant-Utils-StaticFiles.html#serveDirectory" class="link">Source</a></p><div class="doc"><p>Serve anything under the specified directory as a <code><a href="Servant-API-Raw.html#t:Raw">Raw</a></code> endpoint.</p><pre>type MyApi = &quot;static&quot; :&gt; Raw
6+
7+server :: Server MyApi
8+server = serveDirectory &quot;/var/www&quot;
9+</pre><p>would capture any request to <code>/static/&lt;something&gt;</code> and look for
10+ <code>&lt;something&gt;</code> under <code>/var/www</code>.</p><p>It will do its best to guess the MIME type for that file, based on the extension,
11+ and send an appropriate <em>Content-Type</em> header if possible.</p><p>If your goal is to serve HTML, CSS and Javascript files that use the rest of the API
12+ as a webapp backend, you will most likely not want the static files to be hidden
13+ behind a <em>/static/</em> prefix. In that case, remember to put the <code><a href="Servant-Utils-StaticFiles.html#v:serveDirectory">serveDirectory</a></code>
14+ handler in the last position, because <em>servant</em> will try to match the handlers
15+ in order.</p></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.15.0</p></div></body></html>
Servant.htmlnew file+6
@@ -0,0 +1,6 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();setSynopsis("mini_Servant.html");};
3+//]]>
4+</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="src/Servant.html">Source</a></li><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">servant-0.2: A family of combinators for defining webservices APIs and serving them</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr><tr><th>Language</th><td>Haskell2010</td></tr></table><p class="caption">Servant</p></div><div id="synopsis"><p id="control.syn" class="caption expander" onclick="toggleSection('syn')">Synopsis</p><ul id="section.syn" class="hide" onclick="toggleSection('syn')"><li class="src short">module <a href="Servant-API.html">Servant.API</a></li><li class="src short">module <a href="Servant-Server.html">Servant.Server</a></li><li class="src short">module <a href="Servant-Common-Text.html">Servant.Common.Text</a></li><li class="src short">module <a href="Servant-QQ.html">Servant.QQ</a></li><li class="src short">module <a href="Servant-Utils-Links.html">Servant.Utils.Links</a></li><li class="src short">module <a href="Servant-Utils-StaticFiles.html">Servant.Utils.StaticFiles</a></li><li class="src short"><span class="keyword">data</span> <a href="#t:Proxy">Proxy</a> t :: k -&gt; * = <a href="#v:Proxy">Proxy</a></li></ul></div><div id="interface"><h1>Documentation</h1><div class="doc"><p>This module and its submodules can be used to define servant APIs. Note
5+ that these API definitions don't directly implement a server (or anything
6+ else).</p></div><div class="top"><p class="src">module <a href="Servant-API.html">Servant.API</a></p></div><div class="doc"><p>For implementing servers for servant APIs.</p></div><div class="top"><p class="src">module <a href="Servant-Server.html">Servant.Server</a></p></div><div class="doc"><p>Using your types in request paths and query string parameters</p></div><div class="top"><p class="src">module <a href="Servant-Common-Text.html">Servant.Common.Text</a></p></div><div class="doc"><p>Utilities on top of the servant core</p></div><div class="top"><p class="src">module <a href="Servant-QQ.html">Servant.QQ</a></p></div><div class="top"><p class="src">module <a href="Servant-Utils-Links.html">Servant.Utils.Links</a></p></div><div class="top"><p class="src">module <a href="Servant-Utils-StaticFiles.html">Servant.Utils.StaticFiles</a></p></div><div class="doc"><p>Useful re-exports</p></div><div class="top"><p class="src"><span class="keyword">data</span> <a name="t:Proxy" class="def">Proxy</a> t :: k -&gt; *</p><div class="doc"><p>A concrete, poly-kinded proxy type</p></div><div class="subs constructors"><p class="caption">Constructors</p><table><tr><td class="src"><a name="v:Proxy" class="def">Proxy</a></td><td class="doc empty">&nbsp;</td></tr></table></div><div class="subs instances"><p id="control.i:Proxy" class="caption collapser" onclick="toggleSection('i:Proxy')">Instances</p><div id="section.i:Proxy" class="show"><table><tr><td class="src"><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Control-Monad.html#t:Monad">Monad</a> (<a href="Servant.html#t:Proxy">Proxy</a> *)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Control-Monad.html#t:Functor">Functor</a> (<a href="Servant.html#t:Proxy">Proxy</a> *)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Control-Applicative.html#t:Applicative">Applicative</a> (<a href="Servant.html#t:Proxy">Proxy</a> *)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Prelude.html#t:Bounded">Bounded</a> (<a href="Servant.html#t:Proxy">Proxy</a> k s)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Prelude.html#t:Enum">Enum</a> (<a href="Servant.html#t:Proxy">Proxy</a> k s)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Eq.html#t:Eq">Eq</a> (<a href="Servant.html#t:Proxy">Proxy</a> k s)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Ord.html#t:Ord">Ord</a> (<a href="Servant.html#t:Proxy">Proxy</a> k s)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Text-Read.html#t:Read">Read</a> (<a href="Servant.html#t:Proxy">Proxy</a> k s)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Text-Show.html#t:Show">Show</a> (<a href="Servant.html#t:Proxy">Proxy</a> k s)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Ix.html#t:Ix">Ix</a> (<a href="Servant.html#t:Proxy">Proxy</a> k s)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-Generics.html#t:Generic">Generic</a> (<a href="Servant.html#t:Proxy">Proxy</a> * t)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Monoid.html#t:Monoid">Monoid</a> (<a href="Servant.html#t:Proxy">Proxy</a> * s)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Typeable-Internal.html#t:Typeable">Typeable</a> (k -&gt; *) (<a href="Servant.html#t:Proxy">Proxy</a> k)</td><td class="doc empty">&nbsp;</td></tr><tr><td class="src"><span class="keyword">type</span> <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-Generics.html#t:Rep">Rep</a> (<a href="Servant.html#t:Proxy">Proxy</a> k t) = <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-Generics.html#t:D1">D1</a> D1Proxy (<a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-Generics.html#t:C1">C1</a> C1_0Proxy <a href="https://hackage.haskell.org/package/base-4.7.0.1/docs/GHC-Generics.html#t:U1">U1</a>)</td><td class="doc empty">&nbsp;</td></tr></table></div></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.15.0</p></div></body></html>
Setup.hsdeleted−2
@@ -1,2 +0,0 @@
1−import Distribution.Simple
2−main = defaultMain
doc-index.htmlnew file+4
@@ -0,0 +1,4 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>servant-0.2: A family of combinators for defining webservices APIs and serving them (Index)</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();};
3+//]]>
4+</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">servant-0.2: A family of combinators for defining webservices APIs and serving them</p></div><div id="content"><div id="index"><p class="caption">Index</p><table><tr><td class="src">:&lt;|&gt;</td><td>&nbsp;</td></tr><tr><td class="alt">1 (Type/Class)</td><td class="module"><a href="Servant-API-Alternative.html#t::-60--124--62-">Servant.API.Alternative</a>, Servant.API, Servant</td></tr><tr><td class="alt">2 (Data Constructor)</td><td class="module"><a href="Servant-API-Alternative.html#v::-60--124--62-">Servant.API.Alternative</a>, Servant.API, Servant</td></tr><tr><td class="src">:&gt;</td><td>&nbsp;</td></tr><tr><td class="alt">1 (Type/Class)</td><td class="module"><a href="Servant-API-Sub.html#t::-62-">Servant.API.Sub</a>, Servant.API, Servant</td></tr><tr><td class="alt">2 (Data Constructor)</td><td class="module"><a href="Servant-API-Sub.html#v::-62-">Servant.API.Sub</a>, Servant.API, Servant</td></tr><tr><td class="src">&gt;:</td><td class="module"><a href="Servant-QQ.html#v:-62-:">Servant.QQ</a>, Servant</td></tr><tr><td class="src">And</td><td class="module"><a href="Servant-Utils-Links.html#t:And">Servant.Utils.Links</a>, Servant</td></tr><tr><td class="src">blockComment</td><td class="module"><a href="Servant-QQ.html#v:blockComment">Servant.QQ</a>, Servant</td></tr><tr><td class="src">Capture</td><td class="module"><a href="Servant-API-Capture.html#t:Capture">Servant.API.Capture</a>, Servant.API, Servant</td></tr><tr><td class="src">capture</td><td class="module"><a href="Servant-QQ.html#v:capture">Servant.QQ</a>, Servant</td></tr><tr><td class="src">conj</td><td class="module"><a href="Servant-QQ.html#v:conj">Servant.QQ</a>, Servant</td></tr><tr><td class="src">Delete</td><td class="module"><a href="Servant-API-Delete.html#t:Delete">Servant.API.Delete</a>, Servant.API, Servant</td></tr><tr><td class="src">delete</td><td class="module"><a href="Servant-QQ.html#v:delete">Servant.QQ</a>, Servant</td></tr><tr><td class="src">eol</td><td class="module"><a href="Servant-QQ.html#v:eol">Servant.QQ</a>, Servant</td></tr><tr><td class="src">eols</td><td class="module"><a href="Servant-QQ.html#v:eols">Servant.QQ</a>, Servant</td></tr><tr><td class="src">ExpSYM</td><td class="module"><a href="Servant-QQ.html#t:ExpSYM">Servant.QQ</a>, Servant</td></tr><tr><td class="src">failWith</td><td class="module"><a href="Servant-Server.html#v:failWith">Servant.Server</a>, Servant</td></tr><tr><td class="src">FromText</td><td class="module"><a href="Servant-Common-Text.html#t:FromText">Servant.Common.Text</a>, Servant</td></tr><tr><td class="src">fromText</td><td class="module"><a href="Servant-Common-Text.html#v:fromText">Servant.Common.Text</a>, Servant</td></tr><tr><td class="src">Get</td><td class="module"><a href="Servant-API-Get.html#t:Get">Servant.API.Get</a>, Servant.API, Servant</td></tr><tr><td class="src">get</td><td class="module"><a href="Servant-QQ.html#v:get">Servant.QQ</a>, Servant</td></tr><tr><td class="src">HasServer</td><td class="module"><a href="Servant-Server.html#t:HasServer">Servant.Server</a>, Servant</td></tr><tr><td class="src">inlineComment</td><td class="module"><a href="Servant-QQ.html#v:inlineComment">Servant.QQ</a>, Servant</td></tr><tr><td class="src">InvalidBody</td><td class="module"><a href="Servant-Server.html#v:InvalidBody">Servant.Server</a>, Servant</td></tr><tr><td class="src">IsElem</td><td class="module"><a href="Servant-Utils-Links.html#t:IsElem">Servant.Utils.Links</a>, Servant</td></tr><tr><td class="src">IsLink</td><td class="module"><a href="Servant-Utils-Links.html#t:IsLink">Servant.Utils.Links</a>, Servant</td></tr><tr><td class="src">IsLink'</td><td class="module"><a href="Servant-Utils-Links.html#t:IsLink-39-">Servant.Utils.Links</a>, Servant</td></tr><tr><td class="src">IsLink''</td><td class="module"><a href="Servant-Utils-Links.html#t:IsLink-39--39-">Servant.Utils.Links</a>, Servant</td></tr><tr><td class="src">isMismatch</td><td class="module"><a href="Servant-Server.html#v:isMismatch">Servant.Server</a>, Servant</td></tr><tr><td class="src">Link</td><td>&nbsp;</td></tr><tr><td class="alt">1 (Type/Class)</td><td class="module"><a href="Servant-Utils-Links.html#t:Link">Servant.Utils.Links</a>, Servant</td></tr><tr><td class="alt">2 (Data Constructor)</td><td class="module"><a href="Servant-Utils-Links.html#v:Link">Servant.Utils.Links</a>, Servant</td></tr><tr><td class="src">lit</td><td class="module"><a href="Servant-QQ.html#v:lit">Servant.QQ</a>, Servant</td></tr><tr><td class="src">mkLink</td><td class="module"><a href="Servant-Utils-Links.html#v:mkLink">Servant.Utils.Links</a>, Servant.API, Servant</td></tr><tr><td class="src">NotFound</td><td class="module"><a href="Servant-Server.html#v:NotFound">Servant.Server</a>, Servant</td></tr><tr><td class="src">Or</td><td class="module"><a href="Servant-Utils-Links.html#t:Or">Servant.Utils.Links</a>, Servant</td></tr><tr><td class="src">parseAll</td><td class="module"><a href="Servant-QQ.html#v:parseAll">Servant.QQ</a>, Servant</td></tr><tr><td class="src">parseEntry</td><td class="module"><a href="Servant-QQ.html#v:parseEntry">Servant.QQ</a>, Servant</td></tr><tr><td class="src">parseMethod</td><td class="module"><a href="Servant-QQ.html#v:parseMethod">Servant.QQ</a>, Servant</td></tr><tr><td class="src">parseTyp</td><td class="module"><a href="Servant-QQ.html#v:parseTyp">Servant.QQ</a>, Servant</td></tr><tr><td class="src">parseUrl</td><td class="module"><a href="Servant-QQ.html#v:parseUrl">Servant.QQ</a>, Servant</td></tr><tr><td class="src">parseUrlSegment</td><td class="module"><a href="Servant-QQ.html#v:parseUrlSegment">Servant.QQ</a>, Servant</td></tr><tr><td class="src">Post</td><td class="module"><a href="Servant-API-Post.html#t:Post">Servant.API.Post</a>, Servant.API, Servant</td></tr><tr><td class="src">post</td><td class="module"><a href="Servant-QQ.html#v:post">Servant.QQ</a>, Servant</td></tr><tr><td class="src">Proxy</td><td>&nbsp;</td></tr><tr><td class="alt">1 (Data Constructor)</td><td class="module"><a href="Servant.html#v:Proxy">Servant</a></td></tr><tr><td class="alt">2 (Type/Class)</td><td class="module"><a href="Servant.html#t:Proxy">Servant</a></td></tr><tr><td class="src">Put</td><td class="module"><a href="Servant-API-Put.html#t:Put">Servant.API.Put</a>, Servant.API, Servant</td></tr><tr><td class="src">put</td><td class="module"><a href="Servant-QQ.html#v:put">Servant.QQ</a>, Servant</td></tr><tr><td class="src">QueryFlag</td><td class="module"><a href="Servant-API-QueryParam.html#t:QueryFlag">Servant.API.QueryParam</a>, Servant.API, Servant</td></tr><tr><td class="src">QueryParam</td><td class="module"><a href="Servant-API-QueryParam.html#t:QueryParam">Servant.API.QueryParam</a>, Servant.API, Servant</td></tr><tr><td class="src">queryParam</td><td class="module"><a href="Servant-QQ.html#v:queryParam">Servant.QQ</a>, Servant</td></tr><tr><td class="src">QueryParams</td><td class="module"><a href="Servant-API-QueryParam.html#t:QueryParams">Servant.API.QueryParam</a>, Servant.API, Servant</td></tr><tr><td class="src">Raw</td><td class="module"><a href="Servant-API-Raw.html#t:Raw">Servant.API.Raw</a>, Servant.API, Servant</td></tr><tr><td class="src">ReqArgVal</td><td class="module"><a href="Servant-QQ.html#v:ReqArgVal">Servant.QQ</a>, Servant</td></tr><tr><td class="src">ReqBody</td><td class="module"><a href="Servant-API-ReqBody.html#t:ReqBody">Servant.API.ReqBody</a>, Servant.API, Servant</td></tr><tr><td class="src">reqBody</td><td class="module"><a href="Servant-QQ.html#v:reqBody">Servant.QQ</a>, Servant</td></tr><tr><td class="src">route</td><td class="module"><a href="Servant-Server.html#v:route">Servant.Server</a>, Servant</td></tr><tr><td class="src">RouteMismatch</td><td class="module"><a href="Servant-Server.html#t:RouteMismatch">Servant.Server</a>, Servant</td></tr><tr><td class="src">RouteResult</td><td class="module"><a href="Servant-Server.html#t:RouteResult">Servant.Server</a>, Servant</td></tr><tr><td class="src">routeResult</td><td class="module"><a href="Servant-Server.html#v:routeResult">Servant.Server</a>, Servant</td></tr><tr><td class="src">RoutingApplication</td><td class="module"><a href="Servant-Server.html#t:RoutingApplication">Servant.Server</a>, Servant</td></tr><tr><td class="src">RR</td><td class="module"><a href="Servant-Server.html#v:RR">Servant.Server</a>, Servant</td></tr><tr><td class="src">serve</td><td class="module"><a href="Servant-Server.html#v:serve">Servant.Server</a>, Servant</td></tr><tr><td class="src">serveDirectory</td><td class="module"><a href="Servant-Utils-StaticFiles.html#v:serveDirectory">Servant.Utils.StaticFiles</a>, Servant.API, Servant</td></tr><tr><td class="src">Server</td><td class="module"><a href="Servant-Server.html#t:Server">Servant.Server</a>, Servant</td></tr><tr><td class="src">sitemap</td><td class="module"><a href="Servant-QQ.html#v:sitemap">Servant.QQ</a>, Servant.API, Servant</td></tr><tr><td class="src">succeedWith</td><td class="module"><a href="Servant-Server.html#v:succeedWith">Servant.Server</a>, Servant</td></tr><tr><td class="src">toApplication</td><td class="module"><a href="Servant-Server.html#v:toApplication">Servant.Server</a>, Servant</td></tr><tr><td class="src">ToText</td><td class="module"><a href="Servant-Common-Text.html#t:ToText">Servant.Common.Text</a>, Servant</td></tr><tr><td class="src">toText</td><td class="module"><a href="Servant-Common-Text.html#v:toText">Servant.Common.Text</a>, Servant</td></tr><tr><td class="src">Typ</td><td class="module"><a href="Servant-QQ.html#t:Typ">Servant.QQ</a>, Servant</td></tr><tr><td class="src">Val</td><td class="module"><a href="Servant-QQ.html#v:Val">Servant.QQ</a>, Servant</td></tr><tr><td class="src">ValidLinkIn</td><td class="module"><a href="Servant-Utils-Links.html#t:ValidLinkIn">Servant.Utils.Links</a>, Servant</td></tr><tr><td class="src">vlh</td><td class="module"><a href="Servant-Utils-Links.html#v:vlh">Servant.Utils.Links</a>, Servant</td></tr><tr><td class="src">VLinkHelper</td><td class="module"><a href="Servant-Utils-Links.html#t:VLinkHelper">Servant.Utils.Links</a>, Servant</td></tr><tr><td class="src">WrongMethod</td><td class="module"><a href="Servant-Server.html#v:WrongMethod">Servant.Server</a>, Servant</td></tr></table></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.15.0</p></div></body></html>
example/README.mddeleted−2
@@ -1,2 +0,0 @@
1−- `greet.hs` shows how to write a simple webservice, run it, query it with automatically-derived haskell functions and print the (generated) markdown documentation for the API.
2−- `greet.md` contains the aforementionned generated documentation.
example/greet.hsdeleted−72
@@ -1,72 +0,0 @@
1−{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE PolyKinds #-}
3−{-# LANGUAGE TypeFamilies #-}
4−{-# LANGUAGE DeriveGeneric #-}
5−{-# LANGUAGE TypeOperators #-}
6−{-# LANGUAGE OverloadedStrings #-}
7−
8−import Data.Aeson
9−import Data.Monoid
10−import Data.Proxy
11−import Data.Text
12−import GHC.Generics
13−import Network.Wai
14−import Network.Wai.Handler.Warp
15−
16−import Servant
17−
18−-- * Example
19−
20−-- | A greet message data type
21−newtype Greet = Greet { msg :: Text }
22− deriving (Generic, Show)
23−
24−instance FromJSON Greet
25−instance ToJSON Greet
26−
27−-- API specification
28−type TestApi =
29− -- GET /hello/:name?capital={true, false} returns a Greet as JSON
30− "hello" :> Capture "name" Text :> QueryParam "capital" Bool :> Get Greet
31−
32− -- POST /greet with a Greet as JSON in the request body,
33− -- returns a Greet as JSON
34− :<|> "greet" :> ReqBody Greet :> Post Greet
35−
36− -- DELETE /greet/:greetid
37− :<|> "greet" :> Capture "greetid" Text :> Delete
38−
39−testApi :: Proxy TestApi
40−testApi = Proxy
41−
42−-- Server-side handlers.
43−--
44−-- There's one handler per endpoint, which, just like in the type
45−-- that represents the API, are glued together using :<|>.
46−--
47−-- Each handler runs in the 'EitherT (Int, String) IO' monad.
48−server :: Server TestApi
49−server = helloH :<|> postGreetH :<|> deleteGreetH
50−
51− where helloH name Nothing = helloH name (Just False)
52− helloH name (Just False) = return . Greet $ "Hello, " <> name
53− helloH name (Just True) = return . Greet . toUpper $ "Hello, " <> name
54−
55− postGreetH greet = return greet
56−
57− deleteGreetH _ = return ()
58−
59−-- Turn the server into a WAI app. 'serve' is provided by servant,
60−-- more precisely by the Servant.Server module.
61−test :: Application
62−test = serve testApi server
63−
64−-- Run the server.
65−--
66−-- 'run' comes from Network.Wai.Handler.Warp
67−runTestServer :: Port -> IO ()
68−runTestServer port = run port test
69−
70−-- Put this all to work!
71−main :: IO ()
72−main = runTestServer 8001
example/greet.mddeleted−52
@@ -1,52 +0,0 @@
1−POST /greet
2−-----------
3−
4−**Request Body**:
5−
6−``` javascript
7−{"msg":"Hello, haskeller!"}
8−```
9−
10−**Response**:
11−
12− - Status code 201
13− - Response body as below.
14−
15−``` javascript
16−{"msg":"Hello, haskeller!"}
17−```
18−
19−GET /hello/:name
20−----------------
21−
22−**Captures**:
23−
24−- *name*: name of the person to greet
25−
26−**GET Parameters**:
27−
28− - capital
29− - **Values**: *true, false*
30− - **Description**: Get the greeting message in uppercase (true) or not (false). Default is false.
31−
32−
33−**Response**:
34−
35− - Status code 200
36− - Response body as below.
37−
38−``` javascript
39−{"msg":"Hello, haskeller!"}
40−```
41−
42−DELETE /greet/:greetid
43−----------------------
44−
45−**Captures**:
46−
47−- *greetid*: identifier of the greet msg to remove
48−
49−**Response**:
50−
51− - Status code 204
52− - No response body
frames.htmlnew file+30
@@ -0,0 +1,30 @@
1+<!DOCTYPE html
2+ PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
3+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
4+<html xmlns="http://www.w3.org/1999/xhtml">
5+<head>
6+<title></title>
7+<script src="haddock-util.js" type="text/javascript"></script>
8+<script type="text/javascript"><!--
9+/*
10+
11+ The synopsis frame needs to be updated using javascript, so we hide
12+ it by default and only show it if javascript is enabled.
13+
14+ TODO: provide some means to disable it.
15+*/
16+function load() {
17+ var d = document.getElementById("inner-fs");
18+ d.rows = "50%,50%";
19+ postReframe();
20+}
21+--></script>
22+</head>
23+<frameset id="outer-fs" cols="25%,75%" onload="load()">
24+ <frameset id="inner-fs" rows="100%,0%">
25+ <frame src="index-frames.html" name="modules" />
26+ <frame src="" name="synopsis" />
27+ </frameset>
28+ <frame src="index.html" name="main" />
29+</frameset>
30+</html>
haddock-util.jsnew file+344
@@ -0,0 +1,344 @@
1+// Haddock JavaScript utilities
2+
3+var rspace = /\s\s+/g,
4+ rtrim = /^\s+|\s+$/g;
5+
6+function spaced(s) { return (" " + s + " ").replace(rspace, " "); }
7+function trim(s) { return s.replace(rtrim, ""); }
8+
9+function hasClass(elem, value) {
10+ var className = spaced(elem.className || "");
11+ return className.indexOf( " " + value + " " ) >= 0;
12+}
13+
14+function addClass(elem, value) {
15+ var className = spaced(elem.className || "");
16+ if ( className.indexOf( " " + value + " " ) < 0 ) {
17+ elem.className = trim(className + " " + value);
18+ }
19+}
20+
21+function removeClass(elem, value) {
22+ var className = spaced(elem.className || "");
23+ className = className.replace(" " + value + " ", " ");
24+ elem.className = trim(className);
25+}
26+
27+function toggleClass(elem, valueOn, valueOff, bool) {
28+ if (bool == null) { bool = ! hasClass(elem, valueOn); }
29+ if (bool) {
30+ removeClass(elem, valueOff);
31+ addClass(elem, valueOn);
32+ }
33+ else {
34+ removeClass(elem, valueOn);
35+ addClass(elem, valueOff);
36+ }
37+ return bool;
38+}
39+
40+
41+function makeClassToggle(valueOn, valueOff)
42+{
43+ return function(elem, bool) {
44+ return toggleClass(elem, valueOn, valueOff, bool);
45+ }
46+}
47+
48+toggleShow = makeClassToggle("show", "hide");
49+toggleCollapser = makeClassToggle("collapser", "expander");
50+
51+function toggleSection(id)
52+{
53+ var b = toggleShow(document.getElementById("section." + id));
54+ toggleCollapser(document.getElementById("control." + id), b);
55+ rememberCollapsed(id, b);
56+ return b;
57+}
58+
59+var collapsed = {};
60+function rememberCollapsed(id, b)
61+{
62+ if(b)
63+ delete collapsed[id]
64+ else
65+ collapsed[id] = null;
66+
67+ var sections = [];
68+ for(var i in collapsed)
69+ {
70+ if(collapsed.hasOwnProperty(i))
71+ sections.push(i);
72+ }
73+ // cookie specific to this page; don't use setCookie which sets path=/
74+ document.cookie = "collapsed=" + escape(sections.join('+'));
75+}
76+
77+function restoreCollapsed()
78+{
79+ var cookie = getCookie("collapsed");
80+ if(!cookie)
81+ return;
82+
83+ var ids = cookie.split('+');
84+ for(var i in ids)
85+ {
86+ if(document.getElementById("section." + ids[i]))
87+ toggleSection(ids[i]);
88+ }
89+}
90+
91+function setCookie(name, value) {
92+ document.cookie = name + "=" + escape(value) + ";path=/;";
93+}
94+
95+function clearCookie(name) {
96+ document.cookie = name + "=;path=/;expires=Thu, 01-Jan-1970 00:00:01 GMT;";
97+}
98+
99+function getCookie(name) {
100+ var nameEQ = name + "=";
101+ var ca = document.cookie.split(';');
102+ for(var i=0;i < ca.length;i++) {
103+ var c = ca[i];
104+ while (c.charAt(0)==' ') c = c.substring(1,c.length);
105+ if (c.indexOf(nameEQ) == 0) {
106+ return unescape(c.substring(nameEQ.length,c.length));
107+ }
108+ }
109+ return null;
110+}
111+
112+
113+
114+var max_results = 75; // 50 is not enough to search for map in the base libraries
115+var shown_range = null;
116+var last_search = null;
117+
118+function quick_search()
119+{
120+ perform_search(false);
121+}
122+
123+function full_search()
124+{
125+ perform_search(true);
126+}
127+
128+
129+function perform_search(full)
130+{
131+ var text = document.getElementById("searchbox").value.toLowerCase();
132+ if (text == last_search && !full) return;
133+ last_search = text;
134+
135+ var table = document.getElementById("indexlist");
136+ var status = document.getElementById("searchmsg");
137+ var children = table.firstChild.childNodes;
138+
139+ // first figure out the first node with the prefix
140+ var first = bisect(-1);
141+ var last = (first == -1 ? -1 : bisect(1));
142+
143+ if (first == -1)
144+ {
145+ table.className = "";
146+ status.innerHTML = "No results found, displaying all";
147+ }
148+ else if (first == 0 && last == children.length - 1)
149+ {
150+ table.className = "";
151+ status.innerHTML = "";
152+ }
153+ else if (last - first >= max_results && !full)
154+ {
155+ table.className = "";
156+ status.innerHTML = "More than " + max_results + ", press Search to display";
157+ }
158+ else
159+ {
160+ // decide what you need to clear/show
161+ if (shown_range)
162+ setclass(shown_range[0], shown_range[1], "indexrow");
163+ setclass(first, last, "indexshow");
164+ shown_range = [first, last];
165+ table.className = "indexsearch";
166+ status.innerHTML = "";
167+ }
168+
169+
170+ function setclass(first, last, status)
171+ {
172+ for (var i = first; i <= last; i++)
173+ {
174+ children[i].className = status;
175+ }
176+ }
177+
178+
179+ // do a binary search, treating 0 as ...
180+ // return either -1 (no 0's found) or location of most far match
181+ function bisect(dir)
182+ {
183+ var first = 0, finish = children.length - 1;
184+ var mid, success = false;
185+
186+ while (finish - first > 3)
187+ {
188+ mid = Math.floor((finish + first) / 2);
189+
190+ var i = checkitem(mid);
191+ if (i == 0) i = dir;
192+ if (i == -1)
193+ finish = mid;
194+ else
195+ first = mid;
196+ }
197+ var a = (dir == 1 ? first : finish);
198+ var b = (dir == 1 ? finish : first);
199+ for (var i = b; i != a - dir; i -= dir)
200+ {
201+ if (checkitem(i) == 0) return i;
202+ }
203+ return -1;
204+ }
205+
206+
207+ // from an index, decide what the result is
208+ // 0 = match, -1 is lower, 1 is higher
209+ function checkitem(i)
210+ {
211+ var s = getitem(i).toLowerCase().substr(0, text.length);
212+ if (s == text) return 0;
213+ else return (s > text ? -1 : 1);
214+ }
215+
216+
217+ // from an index, get its string
218+ // this abstracts over alternates
219+ function getitem(i)
220+ {
221+ for ( ; i >= 0; i--)
222+ {
223+ var s = children[i].firstChild.firstChild.data;
224+ if (s.indexOf(' ') == -1)
225+ return s;
226+ }
227+ return ""; // should never be reached
228+ }
229+}
230+
231+function setSynopsis(filename) {
232+ if (parent.window.synopsis) {
233+ if (parent.window.synopsis.location.replace) {
234+ // In Firefox this avoids adding the change to the history.
235+ parent.window.synopsis.location.replace(filename);
236+ } else {
237+ parent.window.synopsis.location = filename;
238+ }
239+ }
240+}
241+
242+function addMenuItem(html) {
243+ var menu = document.getElementById("page-menu");
244+ if (menu) {
245+ var btn = menu.firstChild.cloneNode(false);
246+ btn.innerHTML = html;
247+ menu.appendChild(btn);
248+ }
249+}
250+
251+function adjustForFrames() {
252+ var bodyCls;
253+
254+ if (parent.location.href == window.location.href) {
255+ // not in frames, so add Frames button
256+ addMenuItem("<a href='#' onclick='reframe();return true;'>Frames</a>");
257+ bodyCls = "no-frame";
258+ }
259+ else {
260+ bodyCls = "in-frame";
261+ }
262+ addClass(document.body, bodyCls);
263+}
264+
265+function reframe() {
266+ setCookie("haddock-reframe", document.URL);
267+ window.location = "frames.html";
268+}
269+
270+function postReframe() {
271+ var s = getCookie("haddock-reframe");
272+ if (s) {
273+ parent.window.main.location = s;
274+ clearCookie("haddock-reframe");
275+ }
276+}
277+
278+function styles() {
279+ var i, a, es = document.getElementsByTagName("link"), rs = [];
280+ for (i = 0; a = es[i]; i++) {
281+ if(a.rel.indexOf("style") != -1 && a.title) {
282+ rs.push(a);
283+ }
284+ }
285+ return rs;
286+}
287+
288+function addStyleMenu() {
289+ var as = styles();
290+ var i, a, btns = "";
291+ for(i=0; a = as[i]; i++) {
292+ btns += "<li><a href='#' onclick=\"setActiveStyleSheet('"
293+ + a.title + "'); return false;\">"
294+ + a.title + "</a></li>"
295+ }
296+ if (as.length > 1) {
297+ var h = "<div id='style-menu-holder'>"
298+ + "<a href='#' onclick='styleMenu(); return false;'>Style &#9662;</a>"
299+ + "<ul id='style-menu' class='hide'>" + btns + "</ul>"
300+ + "</div>";
301+ addMenuItem(h);
302+ }
303+}
304+
305+function setActiveStyleSheet(title) {
306+ var as = styles();
307+ var i, a, found;
308+ for(i=0; a = as[i]; i++) {
309+ a.disabled = true;
310+ // need to do this always, some browsers are edge triggered
311+ if(a.title == title) {
312+ found = a;
313+ }
314+ }
315+ if (found) {
316+ found.disabled = false;
317+ setCookie("haddock-style", title);
318+ }
319+ else {
320+ as[0].disabled = false;
321+ clearCookie("haddock-style");
322+ }
323+ styleMenu(false);
324+}
325+
326+function resetStyle() {
327+ var s = getCookie("haddock-style");
328+ if (s) setActiveStyleSheet(s);
329+}
330+
331+
332+function styleMenu(show) {
333+ var m = document.getElementById('style-menu');
334+ if (m) toggleShow(m, show);
335+}
336+
337+
338+function pageLoad() {
339+ addStyleMenu();
340+ adjustForFrames();
341+ resetStyle();
342+ restoreCollapsed();
343+}
344+
hslogo-16.pngnew file

Binary file not shown.

index-frames.htmlnew file+4
@@ -0,0 +1,4 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>servant-0.2: A family of combinators for defining webservices APIs and serving them</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();};
3+//]]>
4+</script></head><body id="mini"><div id="module-list"><p class="caption">Modules</p><ul><li class="module"><a href="Servant.html" target="main">Servant</a></li><li class="module"><a href="Servant-API.html" target="main">Servant.API</a></li><li class="module"><a href="Servant-API-Alternative.html" target="main">Servant.API.Alternative</a></li><li class="module"><a href="Servant-API-Capture.html" target="main">Servant.API.Capture</a></li><li class="module"><a href="Servant-API-Delete.html" target="main">Servant.API.Delete</a></li><li class="module"><a href="Servant-API-Get.html" target="main">Servant.API.Get</a></li><li class="module"><a href="Servant-API-Post.html" target="main">Servant.API.Post</a></li><li class="module"><a href="Servant-API-Put.html" target="main">Servant.API.Put</a></li><li class="module"><a href="Servant-API-QueryParam.html" target="main">Servant.API.QueryParam</a></li><li class="module"><a href="Servant-API-Raw.html" target="main">Servant.API.Raw</a></li><li class="module"><a href="Servant-API-ReqBody.html" target="main">Servant.API.ReqBody</a></li><li class="module"><a href="Servant-API-Sub.html" target="main">Servant.API.Sub</a></li><li class="module"><a href="Servant-Common-Text.html" target="main">Servant.Common.Text</a></li><li class="module"><a href="Servant-QQ.html" target="main">Servant.QQ</a></li><li class="module"><a href="Servant-Server.html" target="main">Servant.Server</a></li><li class="module"><a href="Servant-Utils-Links.html" target="main">Servant.Utils.Links</a></li><li class="module"><a href="Servant-Utils-StaticFiles.html" target="main">Servant.Utils.StaticFiles</a></li></ul></div></body></html>
index.htmlnew file+4
@@ -0,0 +1,4 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>servant-0.2: A family of combinators for defining webservices APIs and serving them</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();};
3+//]]>
4+</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">servant-0.2: A family of combinators for defining webservices APIs and serving them</p></div><div id="content"><div id="description"><h1>servant-0.2: A family of combinators for defining webservices APIs and serving them</h1><div class="doc empty">&nbsp;</div></div><div id="module-list"><p class="caption">Modules</p><ul><li><span class="module"><span id="control.n.1" class="collapser" onclick="toggleSection('n.1')">&nbsp;</span><a href="Servant.html">Servant</a></span><ul id="section.n.1" class="show"><li><span class="module"><span id="control.n.1.1" class="collapser" onclick="toggleSection('n.1.1')">&nbsp;</span><a href="Servant-API.html">Servant.API</a></span><ul id="section.n.1.1" class="show"><li><span class="module"><a href="Servant-API-Alternative.html">Servant.API.Alternative</a></span></li><li><span class="module"><a href="Servant-API-Capture.html">Servant.API.Capture</a></span></li><li><span class="module"><a href="Servant-API-Delete.html">Servant.API.Delete</a></span></li><li><span class="module"><a href="Servant-API-Get.html">Servant.API.Get</a></span></li><li><span class="module"><a href="Servant-API-Post.html">Servant.API.Post</a></span></li><li><span class="module"><a href="Servant-API-Put.html">Servant.API.Put</a></span></li><li><span class="module"><a href="Servant-API-QueryParam.html">Servant.API.QueryParam</a></span></li><li><span class="module"><a href="Servant-API-Raw.html">Servant.API.Raw</a></span></li><li><span class="module"><a href="Servant-API-ReqBody.html">Servant.API.ReqBody</a></span></li><li><span class="module"><a href="Servant-API-Sub.html">Servant.API.Sub</a></span></li></ul></li><li><span id="control.n.1.2" class="module collapser" onclick="toggleSection('n.1.2')">Common</span><ul id="section.n.1.2" class="show"><li><span class="module"><a href="Servant-Common-Text.html">Servant.Common.Text</a></span></li></ul></li><li><span class="module"><a href="Servant-QQ.html">Servant.QQ</a></span></li><li><span class="module"><a href="Servant-Server.html">Servant.Server</a></span></li><li><span id="control.n.1.5" class="module collapser" onclick="toggleSection('n.1.5')">Utils</span><ul id="section.n.1.5" class="show"><li><span class="module"><a href="Servant-Utils-Links.html">Servant.Utils.Links</a></span></li><li><span class="module"><a href="Servant-Utils-StaticFiles.html">Servant.Utils.StaticFiles</a></span></li></ul></li></ul></li></ul></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.15.0</p></div></body></html>
mini_Servant-API-Alternative.htmlnew file+4
@@ -0,0 +1,4 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.API.Alternative</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();};
3+//]]>
4+</script></head><body id="mini"><div id="module-header"><p class="caption">Servant.API.Alternative</p></div><div id="interface"><div class="top"><p class="src"><span class="keyword">data</span> a <a href="Servant-API-Alternative.html#t::-60--124--62-" target="main">:&lt;|&gt;</a> b</p></div></div></body></html>
mini_Servant-API-Capture.htmlnew file+4
@@ -0,0 +1,4 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.API.Capture</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();};
3+//]]>
4+</script></head><body id="mini"><div id="module-header"><p class="caption">Servant.API.Capture</p></div><div id="interface"><div class="top"><p class="src"><span class="keyword">data</span> <a href="Servant-API-Capture.html#t:Capture" target="main">Capture</a> sym a</p></div></div></body></html>
mini_Servant-API-Delete.htmlnew file+4
@@ -0,0 +1,4 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.API.Delete</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();};
3+//]]>
4+</script></head><body id="mini"><div id="module-header"><p class="caption">Servant.API.Delete</p></div><div id="interface"><div class="top"><p class="src"><span class="keyword">data</span> <a href="Servant-API-Delete.html#t:Delete" target="main">Delete</a></p></div></div></body></html>
mini_Servant-API-Get.htmlnew file+4
@@ -0,0 +1,4 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.API.Get</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();};
3+//]]>
4+</script></head><body id="mini"><div id="module-header"><p class="caption">Servant.API.Get</p></div><div id="interface"><div class="top"><p class="src"><span class="keyword">data</span> <a href="Servant-API-Get.html#t:Get" target="main">Get</a> a</p></div></div></body></html>
mini_Servant-API-Post.htmlnew file+4
@@ -0,0 +1,4 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.API.Post</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();};
3+//]]>
4+</script></head><body id="mini"><div id="module-header"><p class="caption">Servant.API.Post</p></div><div id="interface"><div class="top"><p class="src"><span class="keyword">data</span> <a href="Servant-API-Post.html#t:Post" target="main">Post</a> a</p></div></div></body></html>
mini_Servant-API-Put.htmlnew file+4
@@ -0,0 +1,4 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.API.Put</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();};
3+//]]>
4+</script></head><body id="mini"><div id="module-header"><p class="caption">Servant.API.Put</p></div><div id="interface"><div class="top"><p class="src"><span class="keyword">data</span> <a href="Servant-API-Put.html#t:Put" target="main">Put</a> a</p></div></div></body></html>
mini_Servant-API-QueryParam.htmlnew file+4
@@ -0,0 +1,4 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.API.QueryParam</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();};
3+//]]>
4+</script></head><body id="mini"><div id="module-header"><p class="caption">Servant.API.QueryParam</p></div><div id="interface"><div class="top"><p class="src"><span class="keyword">data</span> <a href="Servant-API-QueryParam.html#t:QueryParam" target="main">QueryParam</a> sym a</p></div><div class="top"><p class="src"><span class="keyword">data</span> <a href="Servant-API-QueryParam.html#t:QueryParams" target="main">QueryParams</a> sym a</p></div><div class="top"><p class="src"><span class="keyword">data</span> <a href="Servant-API-QueryParam.html#t:QueryFlag" target="main">QueryFlag</a> sym</p></div></div></body></html>
mini_Servant-API-Raw.htmlnew file+4
@@ -0,0 +1,4 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.API.Raw</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();};
3+//]]>
4+</script></head><body id="mini"><div id="module-header"><p class="caption">Servant.API.Raw</p></div><div id="interface"><div class="top"><p class="src"><span class="keyword">data</span> <a href="Servant-API-Raw.html#t:Raw" target="main">Raw</a></p></div></div></body></html>
mini_Servant-API-ReqBody.htmlnew file+4
@@ -0,0 +1,4 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.API.ReqBody</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();};
3+//]]>
4+</script></head><body id="mini"><div id="module-header"><p class="caption">Servant.API.ReqBody</p></div><div id="interface"><div class="top"><p class="src"><span class="keyword">data</span> <a href="Servant-API-ReqBody.html#t:ReqBody" target="main">ReqBody</a> a</p></div></div></body></html>
mini_Servant-API-Sub.htmlnew file+4
@@ -0,0 +1,4 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.API.Sub</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();};
3+//]]>
4+</script></head><body id="mini"><div id="module-header"><p class="caption">Servant.API.Sub</p></div><div id="interface"><div class="top"><p class="src"><span class="keyword">data</span> path <a href="Servant-API-Sub.html#t::-62-" target="main">:&gt;</a> a</p></div></div></body></html>
mini_Servant-API.htmlnew file+4
@@ -0,0 +1,4 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.API</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();};
3+//]]>
4+</script></head><body id="mini"><div id="module-header"><p class="caption">Servant.API</p></div><div id="interface"><h1>Combinators</h1><h1>Accessing information from the request</h1><h1>Actual endpoints, distinguished by HTTP method</h1><h1>Untyped endpoints</h1><h1>Utilities</h1></div></body></html>
mini_Servant-Common-Text.htmlnew file+4
@@ -0,0 +1,4 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.Common.Text</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();};
3+//]]>
4+</script></head><body id="mini"><div id="module-header"><p class="caption">Servant.Common.Text</p></div><div id="interface"><div class="top"><p class="src"><span class="keyword">class</span> <a href="Servant-Common-Text.html#t:FromText" target="main">FromText</a> a</p></div><div class="top"><p class="src"><span class="keyword">class</span> <a href="Servant-Common-Text.html#t:ToText" target="main">ToText</a> a</p></div></div></body></html>
mini_Servant-QQ.htmlnew file+4
@@ -0,0 +1,4 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.QQ</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();};
3+//]]>
4+</script></head><body id="mini"><div id="module-header"><p class="caption">Servant.QQ</p></div><div id="interface"><div class="top"><p class="src"><span class="keyword">class</span> <a href="Servant-QQ.html#t:ExpSYM" target="main">ExpSYM</a> repr' repr</p></div><div class="top"><p class="src"><a href="Servant-QQ.html#v:-62-:" target="main">(&gt;:)</a></p></div><div class="top"><p class="src"><a href="Servant-QQ.html#v:parseMethod" target="main">parseMethod</a></p></div><div class="top"><p class="src"><a href="Servant-QQ.html#v:parseUrlSegment" target="main">parseUrlSegment</a></p></div><div class="top"><p class="src"><a href="Servant-QQ.html#v:parseUrl" target="main">parseUrl</a></p></div><div class="top"><p class="src"><span class="keyword">data</span> <a href="Servant-QQ.html#t:Typ" target="main">Typ</a></p></div><div class="top"><p class="src"><a href="Servant-QQ.html#v:parseTyp" target="main">parseTyp</a></p></div><div class="top"><p class="src"><a href="Servant-QQ.html#v:parseEntry" target="main">parseEntry</a></p></div><div class="top"><p class="src"><a href="Servant-QQ.html#v:blockComment" target="main">blockComment</a></p></div><div class="top"><p class="src"><a href="Servant-QQ.html#v:inlineComment" target="main">inlineComment</a></p></div><div class="top"><p class="src"><a href="Servant-QQ.html#v:eol" target="main">eol</a></p></div><div class="top"><p class="src"><a href="Servant-QQ.html#v:eols" target="main">eols</a></p></div><div class="top"><p class="src"><a href="Servant-QQ.html#v:parseAll" target="main">parseAll</a></p></div><div class="top"><p class="src"><a href="Servant-QQ.html#v:sitemap" target="main">sitemap</a></p></div></div></body></html>
mini_Servant-Server.htmlnew file+4
@@ -0,0 +1,4 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.Server</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();};
3+//]]>
4+</script></head><body id="mini"><div id="module-header"><p class="caption">Servant.Server</p></div><div id="interface"><h1>Implementing Servers</h1><div class="top"><p class="src"><a href="Servant-Server.html#v:serve" target="main">serve</a></p></div><div class="top"><p class="src"><a href="Servant-Server.html#v:toApplication" target="main">toApplication</a></p></div><h1>Route mismatch</h1><div class="top"><p class="src"><span class="keyword">data</span> <a href="Servant-Server.html#t:RouteMismatch" target="main">RouteMismatch</a></p></div><div class="top"><p class="src"><span class="keyword">data</span> <a href="Servant-Server.html#t:RouteResult" target="main">RouteResult</a> a</p></div><div class="top"><p class="src"><a href="Servant-Server.html#v:failWith" target="main">failWith</a></p></div><div class="top"><p class="src"><a href="Servant-Server.html#v:succeedWith" target="main">succeedWith</a></p></div><div class="top"><p class="src"><a href="Servant-Server.html#v:isMismatch" target="main">isMismatch</a></p></div><div class="top"><p class="src"><span class="keyword">type</span> <a href="Servant-Server.html#t:RoutingApplication" target="main">RoutingApplication</a></p></div><div class="top"><p class="src"><span class="keyword">class</span> <a href="Servant-Server.html#t:HasServer" target="main">HasServer</a> layout</p></div></div></body></html>
mini_Servant-Utils-Links.htmlnew file+4
@@ -0,0 +1,4 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.Utils.Links</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();};
3+//]]>
4+</script></head><body id="mini"><div id="module-header"><p class="caption">Servant.Utils.Links</p></div><div id="interface"><div class="top"><p class="src"><span class="keyword">type family</span> <a href="#t:Or">Or</a> a b</p></div><div class="top"><p class="src"><span class="keyword">type family</span> <a href="#t:And">And</a> a b</p></div><div class="top"><p class="src"><span class="keyword">type family</span> <a href="#t:IsElem">IsElem</a> a s</p></div><div class="top"><p class="src"><span class="keyword">type family</span> <a href="#t:IsLink-39--39-">IsLink''</a> l</p></div><div class="top"><p class="src"><span class="keyword">type family</span> <a href="#t:IsLink-39-">IsLink'</a> e</p></div><div class="top"><p class="src"><span class="keyword">type family</span> <a href="#t:IsLink">IsLink</a> e</p></div><div class="top"><p class="src"><span class="keyword">class</span> <a href="Servant-Utils-Links.html#t:ValidLinkIn" target="main">ValidLinkIn</a> f s</p></div><div class="top"><p class="src"><span class="keyword">data</span> <a href="Servant-Utils-Links.html#t:Link" target="main">Link</a></p></div><div class="top"><p class="src"><span class="keyword">class</span> <a href="Servant-Utils-Links.html#t:VLinkHelper" target="main">VLinkHelper</a> f</p></div></div></body></html>
mini_Servant-Utils-StaticFiles.htmlnew file+4
@@ -0,0 +1,4 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant.Utils.StaticFiles</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();};
3+//]]>
4+</script></head><body id="mini"><div id="module-header"><p class="caption">Servant.Utils.StaticFiles</p></div><div id="interface"><div class="top"><p class="src"><a href="Servant-Utils-StaticFiles.html#v:serveDirectory" target="main">serveDirectory</a></p></div></div></body></html>
mini_Servant.htmlnew file+4
@@ -0,0 +1,4 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Servant</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
2+window.onload = function () {pageLoad();};
3+//]]>
4+</script></head><body id="mini"><div id="module-header"><p class="caption">Servant</p></div><div id="interface"><div class="top"><p class="src"><span class="keyword">data</span> <a href="Servant.html#t:Proxy" target="main">Proxy</a> t</p></div></div></body></html>
minus.gifnew file

Binary file not shown.

ocean.cssnew file+577
@@ -0,0 +1,577 @@
1+/* @group Fundamentals */
2+
3+* { margin: 0; padding: 0 }
4+
5+/* Is this portable? */
6+html {
7+ background-color: white;
8+ width: 100%;
9+ height: 100%;
10+}
11+
12+body {
13+ background: white;
14+ color: black;
15+ text-align: left;
16+ min-height: 100%;
17+ position: relative;
18+}
19+
20+p {
21+ margin: 0.8em 0;
22+}
23+
24+ul, ol {
25+ margin: 0.8em 0 0.8em 2em;
26+}
27+
28+dl {
29+ margin: 0.8em 0;
30+}
31+
32+dt {
33+ font-weight: bold;
34+}
35+dd {
36+ margin-left: 2em;
37+}
38+
39+a { text-decoration: none; }
40+a[href]:link { color: rgb(196,69,29); }
41+a[href]:visited { color: rgb(171,105,84); }
42+a[href]:hover { text-decoration:underline; }
43+
44+/* @end */
45+
46+/* @group Fonts & Sizes */
47+
48+/* Basic technique & IE workarounds from YUI 3
49+ For reasons, see:
50+ http://yui.yahooapis.com/3.1.1/build/cssfonts/fonts.css
51+ */
52+
53+body {
54+ font:13px/1.4 sans-serif;
55+ *font-size:small; /* for IE */
56+ *font:x-small; /* for IE in quirks mode */
57+}
58+
59+h1 { font-size: 146.5%; /* 19pt */ }
60+h2 { font-size: 131%; /* 17pt */ }
61+h3 { font-size: 116%; /* 15pt */ }
62+h4 { font-size: 100%; /* 13pt */ }
63+h5 { font-size: 100%; /* 13pt */ }
64+
65+select, input, button, textarea {
66+ font:99% sans-serif;
67+}
68+
69+table {
70+ font-size:inherit;
71+ font:100%;
72+}
73+
74+pre, code, kbd, samp, tt, .src {
75+ font-family:monospace;
76+ *font-size:108%;
77+ line-height: 124%;
78+}
79+
80+.links, .link {
81+ font-size: 85%; /* 11pt */
82+}
83+
84+#module-header .caption {
85+ font-size: 182%; /* 24pt */
86+}
87+
88+.info {
89+ font-size: 85%; /* 11pt */
90+}
91+
92+#table-of-contents, #synopsis {
93+ /* font-size: 85%; /* 11pt */
94+}
95+
96+
97+/* @end */
98+
99+/* @group Common */
100+
101+.caption, h1, h2, h3, h4, h5, h6 {
102+ font-weight: bold;
103+ color: rgb(78,98,114);
104+ margin: 0.8em 0 0.4em;
105+}
106+
107+* + h1, * + h2, * + h3, * + h4, * + h5, * + h6 {
108+ margin-top: 2em;
109+}
110+
111+h1 + h2, h2 + h3, h3 + h4, h4 + h5, h5 + h6 {
112+ margin-top: inherit;
113+}
114+
115+ul.links {
116+ list-style: none;
117+ text-align: left;
118+ float: right;
119+ display: inline-table;
120+ margin: 0 0 0 1em;
121+}
122+
123+ul.links li {
124+ display: inline;
125+ border-left: 1px solid #d5d5d5;
126+ white-space: nowrap;
127+ padding: 0;
128+}
129+
130+ul.links li a {
131+ padding: 0.2em 0.5em;
132+}
133+
134+.hide { display: none; }
135+.show { display: inherit; }
136+.clear { clear: both; }
137+
138+.collapser {
139+ background-image: url(minus.gif);
140+ background-repeat: no-repeat;
141+}
142+.expander {
143+ background-image: url(plus.gif);
144+ background-repeat: no-repeat;
145+}
146+p.caption.collapser,
147+p.caption.expander {
148+ background-position: 0 0.4em;
149+}
150+.collapser, .expander {
151+ padding-left: 14px;
152+ margin-left: -14px;
153+ cursor: pointer;
154+}
155+
156+pre {
157+ padding: 0.25em;
158+ margin: 0.8em 0;
159+ background: rgb(229,237,244);
160+ overflow: auto;
161+ border-bottom: 0.25em solid white;
162+ /* white border adds some space below the box to compensate
163+ for visual extra space that paragraphs have between baseline
164+ and the bounding box */
165+}
166+
167+.src {
168+ background: #f0f0f0;
169+ padding: 0.2em 0.5em;
170+}
171+
172+.keyword { font-weight: normal; }
173+.def { font-weight: bold; }
174+
175+
176+/* @end */
177+
178+/* @group Page Structure */
179+
180+#content {
181+ margin: 0 auto;
182+ padding: 0 2em 6em;
183+}
184+
185+#package-header {
186+ background: rgb(41,56,69);
187+ border-top: 5px solid rgb(78,98,114);
188+ color: #ddd;
189+ padding: 0.2em;
190+ position: relative;
191+ text-align: left;
192+}
193+
194+#package-header .caption {
195+ background: url(hslogo-16.png) no-repeat 0em;
196+ color: white;
197+ margin: 0 2em;
198+ font-weight: normal;
199+ font-style: normal;
200+ padding-left: 2em;
201+}
202+
203+#package-header a:link, #package-header a:visited { color: white; }
204+#package-header a:hover { background: rgb(78,98,114); }
205+
206+#module-header .caption {
207+ color: rgb(78,98,114);
208+ font-weight: bold;
209+ border-bottom: 1px solid #ddd;
210+}
211+
212+table.info {
213+ float: right;
214+ padding: 0.5em 1em;
215+ border: 1px solid #ddd;
216+ color: rgb(78,98,114);
217+ background-color: #fff;
218+ max-width: 40%;
219+ border-spacing: 0;
220+ position: relative;
221+ top: -0.5em;
222+ margin: 0 0 0 2em;
223+}
224+
225+.info th {
226+ padding: 0 1em 0 0;
227+}
228+
229+div#style-menu-holder {
230+ position: relative;
231+ z-index: 2;
232+ display: inline;
233+}
234+
235+#style-menu {
236+ position: absolute;
237+ z-index: 1;
238+ overflow: visible;
239+ background: #374c5e;
240+ margin: 0;
241+ text-align: center;
242+ right: 0;
243+ padding: 0;
244+ top: 1.25em;
245+}
246+
247+#style-menu li {
248+ display: list-item;
249+ border-style: none;
250+ margin: 0;
251+ padding: 0;
252+ color: #000;
253+ list-style-type: none;
254+}
255+
256+#style-menu li + li {
257+ border-top: 1px solid #919191;
258+}
259+
260+#style-menu a {
261+ width: 6em;
262+ padding: 3px;
263+ display: block;
264+}
265+
266+#footer {
267+ background: #ddd;
268+ border-top: 1px solid #aaa;
269+ padding: 0.5em 0;
270+ color: #666;
271+ text-align: center;
272+ position: absolute;
273+ bottom: 0;
274+ width: 100%;
275+ height: 3em;
276+}
277+
278+/* @end */
279+
280+/* @group Front Matter */
281+
282+#table-of-contents {
283+ float: right;
284+ clear: right;
285+ background: #faf9dc;
286+ border: 1px solid #d8d7ad;
287+ padding: 0.5em 1em;
288+ max-width: 20em;
289+ margin: 0.5em 0 1em 1em;
290+}
291+
292+#table-of-contents .caption {
293+ text-align: center;
294+ margin: 0;
295+}
296+
297+#table-of-contents ul {
298+ list-style: none;
299+ margin: 0;
300+}
301+
302+#table-of-contents ul ul {
303+ margin-left: 2em;
304+}
305+
306+#description .caption {
307+ display: none;
308+}
309+
310+#synopsis {
311+ display: none;
312+}
313+
314+.no-frame #synopsis {
315+ display: block;
316+ position: fixed;
317+ right: 0;
318+ height: 80%;
319+ top: 10%;
320+ padding: 0;
321+}
322+
323+#synopsis .caption {
324+ float: left;
325+ width: 29px;
326+ color: rgba(255,255,255,0);
327+ height: 110px;
328+ margin: 0;
329+ font-size: 1px;
330+ padding: 0;
331+}
332+
333+#synopsis p.caption.collapser {
334+ background: url(synopsis.png) no-repeat -64px -8px;
335+}
336+
337+#synopsis p.caption.expander {
338+ background: url(synopsis.png) no-repeat 0px -8px;
339+}
340+
341+#synopsis ul {
342+ height: 100%;
343+ overflow: auto;
344+ padding: 0.5em;
345+ margin: 0;
346+}
347+
348+#synopsis ul ul {
349+ overflow: hidden;
350+}
351+
352+#synopsis ul,
353+#synopsis ul li.src {
354+ background-color: #faf9dc;
355+ white-space: nowrap;
356+ list-style: none;
357+ margin-left: 0;
358+}
359+
360+/* @end */
361+
362+/* @group Main Content */
363+
364+#interface div.top { margin: 2em 0; }
365+#interface h1 + div.top,
366+#interface h2 + div.top,
367+#interface h3 + div.top,
368+#interface h4 + div.top,
369+#interface h5 + div.top {
370+ margin-top: 1em;
371+}
372+#interface p.src .link {
373+ float: right;
374+ color: #919191;
375+ border-left: 1px solid #919191;
376+ background: #f0f0f0;
377+ padding: 0 0.5em 0.2em;
378+ margin: 0 -0.5em 0 0.5em;
379+}
380+
381+#interface span.fixity {
382+ color: #919191;
383+ border-left: 1px solid #919191;
384+ padding: 0.2em 0.5em 0.2em 0.5em;
385+ margin: 0 -1em 0 1em;
386+}
387+
388+#interface span.rightedge {
389+ border-left: 1px solid #919191;
390+ padding: 0.2em 0 0.2em 0;
391+ margin: 0 0 0 1em;
392+}
393+
394+#interface table { border-spacing: 2px; }
395+#interface td {
396+ vertical-align: top;
397+ padding-left: 0.5em;
398+}
399+#interface td.src {
400+ white-space: nowrap;
401+}
402+#interface td.doc p {
403+ margin: 0;
404+}
405+#interface td.doc p + p {
406+ margin-top: 0.8em;
407+}
408+
409+.subs dl {
410+ margin: 0;
411+}
412+
413+.subs dt {
414+ float: left;
415+ clear: left;
416+ display: block;
417+ margin: 1px 0;
418+}
419+
420+.subs dd {
421+ float: right;
422+ width: 90%;
423+ display: block;
424+ padding-left: 0.5em;
425+ margin-bottom: 0.5em;
426+}
427+
428+.subs dd.empty {
429+ display: none;
430+}
431+
432+.subs dd p {
433+ margin: 0;
434+}
435+
436+/* Render short-style data instances */
437+.inst ul {
438+ height: 100%;
439+ padding: 0.5em;
440+ margin: 0;
441+}
442+
443+.inst, .inst li {
444+ list-style: none;
445+ margin-left: 1em;
446+}
447+
448+.top p.src {
449+ border-top: 1px solid #ccc;
450+}
451+
452+.subs, .doc {
453+ /* use this selector for one level of indent */
454+ padding-left: 2em;
455+}
456+
457+.warning {
458+ color: red;
459+}
460+
461+.arguments {
462+ margin-top: -0.4em;
463+}
464+.arguments .caption {
465+ display: none;
466+}
467+
468+.fields { padding-left: 1em; }
469+
470+.fields .caption { display: none; }
471+
472+.fields p { margin: 0 0; }
473+
474+/* this seems bulky to me
475+.methods, .constructors {
476+ background: #f8f8f8;
477+ border: 1px solid #eee;
478+}
479+*/
480+
481+/* @end */
482+
483+/* @group Auxillary Pages */
484+
485+
486+.extension-list {
487+ list-style-type: none;
488+ margin-left: 0;
489+}
490+
491+#mini {
492+ margin: 0 auto;
493+ padding: 0 1em 1em;
494+}
495+
496+#mini > * {
497+ font-size: 93%; /* 12pt */
498+}
499+
500+#mini #module-list .caption,
501+#mini #module-header .caption {
502+ font-size: 125%; /* 15pt */
503+}
504+
505+#mini #interface h1,
506+#mini #interface h2,
507+#mini #interface h3,
508+#mini #interface h4 {
509+ font-size: 109%; /* 13pt */
510+ margin: 1em 0 0;
511+}
512+
513+#mini #interface .top,
514+#mini #interface .src {
515+ margin: 0;
516+}
517+
518+#mini #module-list ul {
519+ list-style: none;
520+ margin: 0;
521+}
522+
523+#alphabet ul {
524+ list-style: none;
525+ padding: 0;
526+ margin: 0.5em 0 0;
527+ text-align: center;
528+}
529+
530+#alphabet li {
531+ display: inline;
532+ margin: 0 0.25em;
533+}
534+
535+#alphabet a {
536+ font-weight: bold;
537+}
538+
539+#index .caption,
540+#module-list .caption { font-size: 131%; /* 17pt */ }
541+
542+#index table {
543+ margin-left: 2em;
544+}
545+
546+#index .src {
547+ font-weight: bold;
548+}
549+#index .alt {
550+ font-size: 77%; /* 10pt */
551+ font-style: italic;
552+ padding-left: 2em;
553+}
554+
555+#index td + td {
556+ padding-left: 1em;
557+}
558+
559+#module-list ul {
560+ list-style: none;
561+ margin: 0 0 0 2em;
562+}
563+
564+#module-list li {
565+ clear: right;
566+}
567+
568+#module-list span.collapser,
569+#module-list span.expander {
570+ background-position: 0 0.3em;
571+}
572+
573+#module-list .package {
574+ float: right;
575+}
576+
577+/* @end */
plus.gifnew file

Binary file not shown.

servant.cabaldeleted−97
@@ -1,97 +0,0 @@
1−name: servant
2−version: 0.2
3−-- synopsis:
4−-- description:
5−license: BSD3
6−license-file: LICENSE
7−author: Alp Mestanogullari, Sönke Hahn, Julian K. Arni
8−maintainer: alpmestan@gmail.com
9−copyright: 2014 Zalora South East Asia Pte Ltd
10−category: Web
11−build-type: Simple
12−cabal-version: >=1.10
13−tested-with: GHC >= 7.8
14−
15−library
16− exposed-modules:
17− Servant
18− Servant.API
19− Servant.API.Alternative
20− Servant.API.Capture
21− Servant.API.Delete
22− Servant.API.Get
23− Servant.API.Post
24− Servant.API.Put
25− Servant.API.QueryParam
26− Servant.API.Raw
27− Servant.API.ReqBody
28− Servant.API.Sub
29− Servant.Common.Text
30− Servant.QQ
31− Servant.Server
32− Servant.Utils.Links
33− Servant.Utils.StaticFiles
34− build-depends:
35− base >=4.7 && <5
36− , aeson
37− , attoparsec
38− , bytestring
39− , either
40− , http-types
41− , network-uri >= 2.6
42− , parsec
43− , safe
44− , split
45− , string-conversions
46− , system-filepath
47− , template-haskell
48− , text
49− , transformers
50− , wai
51− , wai-app-static
52− , warp
53− hs-source-dirs: src
54− default-language: Haskell2010
55− ghc-options: -O0 -Wall
56−
57−executable greet
58− main-is: greet.hs
59− hs-source-dirs: example
60− ghc-options: -O0 -Wall
61− default-language: Haskell2010
62− build-depends:
63− base
64− , servant
65− , aeson
66− , warp
67− , wai
68− , text
69−
70−test-suite spec
71− type: exitcode-stdio-1.0
72− ghc-options:
73− -Wall -fno-warn-name-shadowing -fno-warn-missing-signatures
74− default-language: Haskell2010
75− hs-source-dirs: test
76− main-is: Spec.hs
77− build-depends:
78− base == 4.*
79− , aeson
80− , bytestring
81− , directory
82− , either
83− , exceptions
84− , hspec == 2.*
85− , hspec-wai
86− , http-types
87− , network >= 2.6
88− , QuickCheck
89− , parsec
90− , servant
91− , string-conversions
92− , temporary
93− , text
94− , transformers
95− , wai
96− , wai-extra
97− , warp
servant.haddocknew file

Binary file not shown.

servant.txtnew file+613
@@ -0,0 +1,613 @@
1+-- Hoogle documentation, generated by Haddock
2+-- See Hoogle, http://www.haskell.org/hoogle/
3+
4+
5+-- | A family of combinators for defining webservices APIs and serving them
6+--
7+@package servant
8+@version 0.2
9+
10+module Servant.Common.Text
11+
12+-- | For getting values from url captures and query string parameters
13+class FromText a
14+fromText :: FromText a => Text -> Maybe a
15+
16+-- | For putting values in paths and query string parameters
17+class ToText a
18+toText :: ToText a => a -> Text
19+instance ToText Float
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
31+instance ToText Word8
32+instance FromText Word8
33+instance ToText Word
34+instance FromText Word
35+instance ToText Int64
36+instance FromText Int64
37+instance ToText Int32
38+instance FromText Int32
39+instance ToText Int16
40+instance FromText Int16
41+instance ToText Int8
42+instance FromText Int8
43+instance ToText Int
44+instance FromText Int
45+instance ToText Bool
46+instance FromText Bool
47+instance ToText String
48+instance FromText String
49+instance ToText Text
50+instance FromText Text
51+
52+
53+-- | This module lets you implement <a>Server</a>s for defined APIs. You'll
54+-- most likely just need <a>serve</a>.
55+module Servant.Server
56+
57+-- | <a>serve</a> allows you to implement an API and produce a wai
58+-- <a>Application</a>.
59+--
60+-- Example:
61+--
62+-- <pre>
63+-- type MyApi = "books" :&gt; Get [Book] -- GET /books
64+-- :&lt;|&gt; "books" :&gt; ReqBody Book :&gt; Post Book -- POST /books
65+--
66+-- server :: Server MyApi
67+-- server = listAllBooks :&lt;|&gt; postBook
68+-- where listAllBooks = ...
69+-- postBook book = ...
70+--
71+-- app :: Application
72+-- app = serve myApi server
73+--
74+-- main :: IO ()
75+-- main = Network.Wai.Handler.Warp.run 8080 app
76+-- </pre>
77+serve :: HasServer layout => Proxy layout -> Server layout -> Application
78+toApplication :: RoutingApplication -> Application
79+data RouteMismatch
80+
81+-- | the usual "not found" error
82+NotFound :: RouteMismatch
83+
84+-- | a more informative "you just got the HTTP method wrong" error
85+WrongMethod :: RouteMismatch
86+
87+-- | an even more informative "your json request body wasn't valid" error
88+InvalidBody :: RouteMismatch
89+
90+-- | <pre>
91+-- &gt; mempty = NotFound
92+-- &gt;
93+-- &gt; NotFound <a>mappend</a> x = x
94+-- &gt; WrongMethod <a>mappend</a> InvalidBody = InvalidBody
95+-- &gt; WrongMethod <a>mappend</a> _ = WrongMethod
96+-- &gt; InvalidBody <a>mappend</a> _ = InvalidBody
97+-- </pre>
98+
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
106+
107+-- | If we get a <a>Right</a>, it has precedence over everything else.
108+--
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
120+
121+module Servant.API.Sub
122+
123+-- | The contained API (second argument) can be found under <tt>("/" ++
124+-- path)</tt> (path being the first argument).
125+--
126+-- Example:
127+--
128+-- <pre>
129+-- -- GET /hello/world
130+-- -- returning a JSON encoded World value
131+-- type MyApi = "hello" :&gt; "world" :&gt; Get World
132+-- </pre>
133+data (:>) (path :: k) a
134+(:>) :: Proxy path -> a -> (:>) a
135+
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)
139+
140+module Servant.API.Alternative
141+
142+-- | Union of two APIs, first takes precedence in case of overlap.
143+--
144+-- Example:
145+--
146+-- <pre>
147+-- type MyApi = "books" :&gt; Get [Book] -- GET /books
148+-- :&lt;|&gt; "books" :&gt; ReqBody Book :&gt; Post Book -- POST /books
149+-- </pre>
150+data (:<|>) a b
151+(:<|>) :: a -> b -> (:<|>) a b
152+
153+-- | A server for <tt>a <a>:&lt;|&gt;</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.
156+--
157+-- <pre>
158+-- type MyApi = "books" :&gt; Get [Book] -- GET /books
159+-- :&lt;|&gt; "books" :&gt; ReqBody Book :&gt; Post Book -- POST /books
160+--
161+-- server :: Server MyApi
162+-- server = listAllBooks :&lt;|&gt; postBook
163+-- where listAllBooks = ...
164+-- postBook book = ...
165+-- </pre>
166+instance (HasServer a, HasServer b) => HasServer (a :<|> b)
167+
168+module Servant.API.Capture
169+
170+-- | Capture a value from the request path under a certain type <tt>a</tt>.
171+--
172+-- Example:
173+--
174+-- <pre>
175+-- -- GET /books/:isbn
176+-- type MyApi = "books" :&gt; Capture "isbn" Text :&gt; Get Book
177+-- </pre>
178+data Capture sym a
179+instance (KnownSymbol capture, FromText a, HasServer sublayout) => HasServer (Capture capture a :> sublayout)
180+
181+module Servant.API.QueryParam
182+
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>.
185+--
186+-- Example:
187+--
188+-- <pre>
189+-- -- /books?author=&lt;author name&gt;
190+-- type MyApi = "books" :&gt; QueryParam "author" Text :&gt; Get [Book]
191+-- </pre>
192+data QueryParam sym a
193+
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>.
198+--
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>.
203+--
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.
206+--
207+-- Example:
208+--
209+-- <pre>
210+-- type MyApi = "books" :&gt; QueryParam "author" Text :&gt; Get [Book]
211+--
212+-- server :: Server MyApi
213+-- server = getBooksBy
214+-- where getBooksBy :: Maybe Text -&gt; EitherT (Int, String) IO [Book]
215+-- getBooksBy Nothing = ...return all books...
216+-- getBooksBy (Just author) = ...return books by the given author...
217+-- </pre>
218+
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&amp;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&amp;param=val2</tt>, too.
225+--
226+-- Example:
227+--
228+-- <pre>
229+-- -- /books?authors[]=&lt;author1&gt;&amp;authors[]=&lt;author2&gt;&amp;...
230+-- type MyApi = "books" :&gt; QueryParams "authors" Text :&gt; Get [Book]
231+-- </pre>
232+data QueryParams sym a
233+
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>.
238+--
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.
242+--
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.
246+--
247+-- Example:
248+--
249+-- <pre>
250+-- type MyApi = "books" :&gt; QueryParams "authors" Text :&gt; Get [Book]
251+--
252+-- server :: Server MyApi
253+-- server = getBooksBy
254+-- where getBooksBy :: [Text] -&gt; EitherT (Int, String) IO [Book]
255+-- getBooksBy authors = ...return all books by these authors...
256+-- </pre>
257+
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>.
262+--
263+-- Example:
264+--
265+-- <pre>
266+-- -- /books?published
267+-- type MyApi = "books" :&gt; QueryFlag "published" :&gt; Get [Book]
268+-- </pre>
269+data QueryFlag sym
270+
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>.
274+--
275+-- Example:
276+--
277+-- <pre>
278+-- type MyApi = "books" :&gt; QueryFlag "published" :&gt; Get [Book]
279+--
280+-- server :: Server MyApi
281+-- server = getBooks
282+-- where getBooks :: Bool -&gt; EitherT (Int, String) IO [Book]
283+-- getBooks onlyPublished = ...return all books, or only the ones that are already published, depending on the argument...
284+-- </pre>
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)
288+
289+module Servant.API.ReqBody
290+
291+-- | Extract the request body as a value of type <tt>a</tt>.
292+--
293+-- Example:
294+--
295+-- <pre>
296+-- -- POST /books
297+-- type MyApi = "books" :&gt; ReqBody Book :&gt; Post Book
298+-- </pre>
299+data ReqBody a
300+
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.
306+--
307+-- All it asks is for a <a>FromJSON</a> instance.
308+--
309+-- Example:
310+--
311+-- <pre>
312+-- type MyApi = "books" :&gt; ReqBody Book :&gt; Post Book
313+--
314+-- server :: Server MyApi
315+-- server = postBook
316+-- where postBook :: Book -&gt; EitherT (Int, String) IO Book
317+-- postBook book = ...insert into your db...
318+-- </pre>
319+instance (FromJSON a, HasServer sublayout) => HasServer (ReqBody a :> sublayout)
320+
321+module Servant.API.Get
322+
323+-- | Endpoint for simple GET requests. Serves the result as JSON.
324+--
325+-- Example:
326+--
327+-- <pre>
328+-- type MyApi = "books" :&gt; Get [Book]
329+-- </pre>
330+data Get a
331+
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.
338+--
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)
344+
345+module Servant.API.Post
346+
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).
349+--
350+-- Example:
351+--
352+-- <pre>
353+-- -- POST /books
354+-- -- with a JSON encoded Book as the request body
355+-- -- returning the just-created Book
356+-- type MyApi = "books" :&gt; ReqBody Book :&gt; Post Book
357+-- </pre>
358+data Post a
359+
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.
366+--
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)
372+
373+module Servant.API.Delete
374+
375+-- | Combinator for DELETE requests.
376+--
377+-- Example:
378+--
379+-- <pre>
380+-- -- DELETE /books/:isbn
381+-- type MyApi = "books" :&gt; Capture "isbn" Text :&gt; Delete
382+-- </pre>
383+data Delete
384+
385+-- | If you have a <a>Delete</a> endpoint in your API, the handler for this
386+-- endpoint is meant to delete a resource.
387+--
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
395+
396+module Servant.API.Put
397+
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.
400+--
401+-- Example:
402+--
403+-- <pre>
404+-- -- PUT /books/:isbn
405+-- -- with a Book as request body, returning the updated Book
406+-- type MyApi = "books" :&gt; Capture "isbn" Text :&gt; ReqBody Book :&gt; Put Book
407+-- </pre>
408+data Put a
409+
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.
416+--
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)
422+
423+
424+-- | QuasiQuoting utilities for API types.
425+--
426+-- <a>sitemap</a> allows you to write your type in a very natural way:
427+--
428+-- <pre>
429+-- [sitemap|
430+-- PUT hello String -&gt; ()
431+-- POST hello/p:Int String -&gt; ()
432+-- GET hello/?name:String Int
433+-- |]
434+-- </pre>
435+--
436+-- Will generate:
437+--
438+-- <pre>
439+-- "hello" :&gt; ReqBody String :&gt; Put ()
440+-- :&lt;|&gt; "hello" :&gt; Capture "p" Int :&gt; ReqBody String :&gt; Post ()
441+-- :&lt;|&gt; "hello" :&gt; QueryParam "name" String :&gt; Get Int
442+-- </pre>
443+--
444+-- Note the <tt>/</tt> before a <tt>QueryParam</tt>!
445+module Servant.QQ
446+
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)
466+data Typ
467+Val :: String -> Typ
468+ReqArgVal :: String -> String -> Typ
469+parseTyp :: Parser Typ
470+parseEntry :: ExpSYM repr repr => Parser repr
471+blockComment :: Parser ()
472+inlineComment :: Parser ()
473+eol :: Parser String
474+eols :: Parser ()
475+parseAll :: Parser Type
476+
477+-- | The sitemap QuasiQuoter.
478+--
479+-- <ul>
480+-- <li><tt>...<i><a>var</a>:<a>type</a></i>...</tt> becomes a
481+-- capture</li>
482+-- <li><tt>.../?<a>var</a>:<a>type</a></tt> becomes a query
483+-- parameter</li>
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> -&gt; <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>
489+-- </ul>
490+--
491+-- Comments are allowed, and have the standard Haskell format
492+--
493+-- <ul>
494+-- <li><tt>--</tt> for inline</li>
495+-- <li><tt>{- ... -}</tt> for block</li>
496+-- </ul>
497+sitemap :: QuasiQuoter
498+instance ExpSYM Type Type
499+
500+
501+-- | Type safe internal links.
502+--
503+-- Provides the function <a>mkLink</a>:
504+--
505+-- <pre>
506+-- type API = Proxy ("hello" :&gt; Get Int
507+-- :<a>|</a> "bye" :&gt; QueryParam "name" String :&gt; Post Bool)
508+--
509+-- api :: API
510+-- api = proxy
511+--
512+-- link1 :: Proxy ("hello" :&gt; Get Int)
513+-- link1 = proxy
514+--
515+-- link2 :: Proxy ("hello" :&gt; Delete)
516+-- link2 = proxy
517+--
518+-- mkLink link1 API -- typechecks, returns 'Link "/hello"'
519+--
520+-- mkLink link2 API -- doesn't typecheck
521+-- </pre>
522+--
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.
526+--
527+-- <b>N.B.:</b> <a>mkLink</a> assumes a capture matches any string
528+-- (without slashes).
529+module Servant.Utils.Links
530+
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
535+data Link
536+Link :: String -> Link
537+class VLinkHelper f
538+vlh :: VLinkHelper f => proxy f -> String
539+instance Show Link
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
544+
545+module Servant.API.Raw
546+
547+-- | Endpoint for plugging in your own Wai <a>Application</a>s.
548+--
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>:&gt;</a>.
552+--
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>.
558+data Raw
559+
560+-- | Just pass the request to the underlying application and serve its
561+-- response.
562+--
563+-- Example:
564+--
565+-- <pre>
566+-- type MyApi = "images" :&gt; Raw
567+--
568+-- server :: Server MyApi
569+-- server = serveDirectory "/var/www/images"
570+-- </pre>
571+instance HasServer Raw
572+
573+
574+-- | This module defines a sever-side handler that lets you serve static
575+-- files.
576+--
577+-- <ul>
578+-- <li><a>serveDirectory</a> lets you serve anything that lives under a
579+-- particular directory on your filesystem.</li>
580+-- </ul>
581+module Servant.Utils.StaticFiles
582+
583+-- | Serve anything under the specified directory as a <a>Raw</a> endpoint.
584+--
585+-- <pre>
586+-- type MyApi = "static" :&gt; Raw
587+--
588+-- server :: Server MyApi
589+-- server = serveDirectory "/var/www"
590+-- </pre>
591+--
592+-- would capture any request to <tt>/static/&lt;something&gt;</tt> and
593+-- look for <tt>&lt;something&gt;</tt> under <tt>/var/www</tt>.
594+--
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
597+-- possible.
598+--
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
604+-- order.
605+serveDirectory :: FilePath -> Server Raw
606+
607+module Servant.API
608+
609+module Servant
610+
611+-- | A concrete, poly-kinded proxy type
612+data Proxy (t :: k) :: k -> *
613+Proxy :: Proxy
src/Servant-API-Alternative.htmlnew file+50
@@ -0,0 +1,50 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3+<html>
4+<head>
5+<!-- Generated by HsColour, http://code.haskell.org/~malcolm/hscolour/ -->
6+<title>src/Servant/API/Alternative.hs</title>
7+<link type='text/css' rel='stylesheet' href='hscolour.css' />
8+</head>
9+<body>
10+<pre><a name="line-1"></a><span class='hs-comment'>{-# LANGUAGE TypeFamilies #-}</span>
11+<a name="line-2"></a><span class='hs-comment'>{-# LANGUAGE TypeOperators #-}</span>
12+<a name="line-3"></a><span class='hs-comment'>{-# LANGUAGE ScopedTypeVariables #-}</span>
13+<a name="line-4"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Alternative</span> <span class='hs-keyword'>where</span>
14+<a name="line-5"></a>
15+<a name="line-6"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Monoid</span>
16+<a name="line-7"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Proxy</span>
17+<a name="line-8"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Server</span>
18+<a name="line-9"></a>
19+<a name="line-10"></a><span class='hs-comment'>-- | Union of two APIs, first takes precedence in case of overlap.</span>
20+<a name="line-11"></a><span class='hs-comment'>--</span>
21+<a name="line-12"></a><span class='hs-comment'>-- Example:</span>
22+<a name="line-13"></a><span class='hs-comment'>--</span>
23+<a name="line-14"></a><span class='hs-comment'>-- &gt; type MyApi = "books" :&gt; Get [Book] -- GET /books</span>
24+<a name="line-15"></a><span class='hs-comment'>-- &gt; :&lt;|&gt; "books" :&gt; ReqBody Book :&gt; Post Book -- POST /books</span>
25+<a name="line-16"></a><span class='hs-keyword'>data</span> <span class='hs-varid'>a</span> <span class='hs-conop'>:&lt;|&gt;</span> <span class='hs-varid'>b</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>a</span> <span class='hs-conop'>:&lt;|&gt;</span> <span class='hs-varid'>b</span>
26+<a name="line-17"></a><span class='hs-keyword'>infixr</span> <span class='hs-num'>8</span> <span class='hs-conop'>:&lt;|&gt;</span>
27+<a name="line-18"></a>
28+<a name="line-19"></a><a name="instance%20HasServer%20(a%20:%3c%7c%3e%20b)"></a><span class='hs-comment'>-- | A server for @a ':&lt;|&gt;' b@ first tries to match the request again the route</span>
29+<a name="line-20"></a><a name="instance%20HasServer%20(a%20:%3c%7c%3e%20b)"></a><span class='hs-comment'>-- represented by @a@ and if it fails tries @b@. You must provide a request</span>
30+<a name="line-21"></a><a name="instance%20HasServer%20(a%20:%3c%7c%3e%20b)"></a><span class='hs-comment'>-- handler for each route.</span>
31+<a name="line-22"></a><a name="instance%20HasServer%20(a%20:%3c%7c%3e%20b)"></a><span class='hs-comment'>--</span>
32+<a name="line-23"></a><a name="instance%20HasServer%20(a%20:%3c%7c%3e%20b)"></a><span class='hs-comment'>-- &gt; type MyApi = "books" :&gt; Get [Book] -- GET /books</span>
33+<a name="line-24"></a><a name="instance%20HasServer%20(a%20:%3c%7c%3e%20b)"></a><span class='hs-comment'>-- &gt; :&lt;|&gt; "books" :&gt; ReqBody Book :&gt; Post Book -- POST /books</span>
34+<a name="line-25"></a><a name="instance%20HasServer%20(a%20:%3c%7c%3e%20b)"></a><span class='hs-comment'>-- &gt;</span>
35+<a name="line-26"></a><a name="instance%20HasServer%20(a%20:%3c%7c%3e%20b)"></a><span class='hs-comment'>-- &gt; server :: Server MyApi</span>
36+<a name="line-27"></a><a name="instance%20HasServer%20(a%20:%3c%7c%3e%20b)"></a><span class='hs-comment'>-- &gt; server = listAllBooks :&lt;|&gt; postBook</span>
37+<a name="line-28"></a><a name="instance%20HasServer%20(a%20:%3c%7c%3e%20b)"></a><span class='hs-comment'>-- &gt; where listAllBooks = ...</span>
38+<a name="line-29"></a><a name="instance%20HasServer%20(a%20:%3c%7c%3e%20b)"></a><span class='hs-comment'>-- &gt; postBook book = ...</span>
39+<a name="line-30"></a><a name="instance%20HasServer%20(a%20:%3c%7c%3e%20b)"></a><span class='hs-keyword'>instance</span> <span class='hs-layout'>(</span><span class='hs-conid'>HasServer</span> <span class='hs-varid'>a</span><span class='hs-layout'>,</span> <span class='hs-conid'>HasServer</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>HasServer</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-conop'>:&lt;|&gt;</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
40+<a name="line-31"></a> <span class='hs-keyword'>type</span> <span class='hs-conid'>Server</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-conop'>:&lt;|&gt;</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Server</span> <span class='hs-varid'>a</span> <span class='hs-conop'>:&lt;|&gt;</span> <span class='hs-conid'>Server</span> <span class='hs-varid'>b</span>
41+<a name="line-32"></a> <span class='hs-varid'>route</span> <span class='hs-conid'>Proxy</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-conop'>:&lt;|&gt;</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-varid'>request</span> <span class='hs-varid'>respond</span> <span class='hs-keyglyph'>=</span>
42+<a name="line-33"></a> <span class='hs-varid'>route</span> <span class='hs-varid'>pa</span> <span class='hs-varid'>a</span> <span class='hs-varid'>request</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span> <span class='hs-varid'>mResponse</span> <span class='hs-keyglyph'>-&gt;</span>
43+<a name="line-34"></a> <span class='hs-keyword'>if</span> <span class='hs-varid'>isMismatch</span> <span class='hs-varid'>mResponse</span>
44+<a name="line-35"></a> <span class='hs-keyword'>then</span> <span class='hs-varid'>route</span> <span class='hs-varid'>pb</span> <span class='hs-varid'>b</span> <span class='hs-varid'>request</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>mResponse'</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>respond</span> <span class='hs-layout'>(</span><span class='hs-varid'>mResponse</span> <span class='hs-varop'>&lt;&gt;</span> <span class='hs-varid'>mResponse'</span><span class='hs-layout'>)</span>
45+<a name="line-36"></a> <span class='hs-keyword'>else</span> <span class='hs-varid'>respond</span> <span class='hs-varid'>mResponse</span>
46+<a name="line-37"></a>
47+<a name="line-38"></a> <span class='hs-keyword'>where</span> <span class='hs-varid'>pa</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Proxy</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>a</span>
48+<a name="line-39"></a> <span class='hs-varid'>pb</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Proxy</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>b</span>
49+</pre></body>
50+</html>
src/Servant-API-Capture.htmlnew file+71
@@ -0,0 +1,71 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3+<html>
4+<head>
5+<!-- Generated by HsColour, http://code.haskell.org/~malcolm/hscolour/ -->
6+<title>src/Servant/API/Capture.hs</title>
7+<link type='text/css' rel='stylesheet' href='hscolour.css' />
8+</head>
9+<body>
10+<pre><a name="line-1"></a><span class='hs-comment'>{-# LANGUAGE PolyKinds #-}</span>
11+<a name="line-2"></a><span class='hs-comment'>{-# LANGUAGE TypeFamilies #-}</span>
12+<a name="line-3"></a><span class='hs-comment'>{-# LANGUAGE TypeOperators #-}</span>
13+<a name="line-4"></a><span class='hs-comment'>{-# LANGUAGE FlexibleContexts #-}</span>
14+<a name="line-5"></a><span class='hs-comment'>{-# LANGUAGE FlexibleInstances #-}</span>
15+<a name="line-6"></a><span class='hs-comment'>{-# LANGUAGE ScopedTypeVariables #-}</span>
16+<a name="line-7"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Capture</span> <span class='hs-layout'>(</span><span class='hs-conid'>Capture</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
17+<a name="line-8"></a>
18+<a name="line-9"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Proxy</span>
19+<a name="line-10"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Text</span>
20+<a name="line-11"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>TypeLits</span>
21+<a name="line-12"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Network</span><span class='hs-varop'>.</span><span class='hs-conid'>Wai</span>
22+<a name="line-13"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Sub</span>
23+<a name="line-14"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Common</span><span class='hs-varop'>.</span><span class='hs-conid'>Text</span>
24+<a name="line-15"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Server</span>
25+<a name="line-16"></a>
26+<a name="line-17"></a><span class='hs-comment'>-- | Capture a value from the request path under a certain type @a@.</span>
27+<a name="line-18"></a><span class='hs-comment'>--</span>
28+<a name="line-19"></a><span class='hs-comment'>-- Example:</span>
29+<a name="line-20"></a><span class='hs-comment'>--</span>
30+<a name="line-21"></a><span class='hs-comment'>-- &gt; -- GET /books/:isbn</span>
31+<a name="line-22"></a><span class='hs-comment'>-- &gt; type MyApi = "books" :&gt; Capture "isbn" Text :&gt; Get Book</span>
32+<a name="line-23"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>Capture</span> <span class='hs-varid'>sym</span> <span class='hs-varid'>a</span>
33+<a name="line-24"></a>
34+<a name="line-25"></a><a name="captured"></a><span class='hs-definition'>captured</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>FromText</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-varid'>proxy</span> <span class='hs-layout'>(</span><span class='hs-conid'>Capture</span> <span class='hs-varid'>sym</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Text</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Maybe</span> <span class='hs-varid'>a</span>
35+<a name="line-26"></a><span class='hs-definition'>captured</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>fromText</span>
36+<a name="line-27"></a>
37+<a name="line-28"></a><a name="instance%20HasServer%20(Capture%20capture%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- | If you use 'Capture' in one of the endpoints for your API,</span>
38+<a name="line-29"></a><a name="instance%20HasServer%20(Capture%20capture%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- this automatically requires your server-side handler to be a function</span>
39+<a name="line-30"></a><a name="instance%20HasServer%20(Capture%20capture%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- that takes an argument of the type specified by the 'Capture'.</span>
40+<a name="line-31"></a><a name="instance%20HasServer%20(Capture%20capture%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- This lets servant worry about getting it from the URL and turning</span>
41+<a name="line-32"></a><a name="instance%20HasServer%20(Capture%20capture%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- it into a value of the type you specify.</span>
42+<a name="line-33"></a><a name="instance%20HasServer%20(Capture%20capture%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>--</span>
43+<a name="line-34"></a><a name="instance%20HasServer%20(Capture%20capture%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- You can control how it'll be converted from 'Text' to your type</span>
44+<a name="line-35"></a><a name="instance%20HasServer%20(Capture%20capture%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- by simply providing an instance of 'FromText' for your type.</span>
45+<a name="line-36"></a><a name="instance%20HasServer%20(Capture%20capture%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>--</span>
46+<a name="line-37"></a><a name="instance%20HasServer%20(Capture%20capture%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- Example:</span>
47+<a name="line-38"></a><a name="instance%20HasServer%20(Capture%20capture%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>--</span>
48+<a name="line-39"></a><a name="instance%20HasServer%20(Capture%20capture%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; type MyApi = "books" :&gt; Capture "isbn" Text :&gt; Get Book</span>
49+<a name="line-40"></a><a name="instance%20HasServer%20(Capture%20capture%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt;</span>
50+<a name="line-41"></a><a name="instance%20HasServer%20(Capture%20capture%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; server :: Server MyApi</span>
51+<a name="line-42"></a><a name="instance%20HasServer%20(Capture%20capture%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; server = getBook</span>
52+<a name="line-43"></a><a name="instance%20HasServer%20(Capture%20capture%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; where getBook :: Text -&gt; EitherT (Int, String) IO Book</span>
53+<a name="line-44"></a><a name="instance%20HasServer%20(Capture%20capture%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; getBook isbn = ...</span>
54+<a name="line-45"></a><a name="instance%20HasServer%20(Capture%20capture%20a%20:%3e%20sublayout)"></a><span class='hs-keyword'>instance</span> <span class='hs-layout'>(</span><span class='hs-conid'>KnownSymbol</span> <span class='hs-varid'>capture</span><span class='hs-layout'>,</span> <span class='hs-conid'>FromText</span> <span class='hs-varid'>a</span><span class='hs-layout'>,</span> <span class='hs-conid'>HasServer</span> <span class='hs-varid'>sublayout</span><span class='hs-layout'>)</span>
55+<a name="line-46"></a> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>HasServer</span> <span class='hs-layout'>(</span><span class='hs-conid'>Capture</span> <span class='hs-varid'>capture</span> <span class='hs-varid'>a</span> <span class='hs-conop'>:&gt;</span> <span class='hs-varid'>sublayout</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
56+<a name="line-47"></a>
57+<a name="line-48"></a> <span class='hs-keyword'>type</span> <span class='hs-conid'>Server</span> <span class='hs-layout'>(</span><span class='hs-conid'>Capture</span> <span class='hs-varid'>capture</span> <span class='hs-varid'>a</span> <span class='hs-conop'>:&gt;</span> <span class='hs-varid'>sublayout</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span>
58+<a name="line-49"></a> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Server</span> <span class='hs-varid'>sublayout</span>
59+<a name="line-50"></a>
60+<a name="line-51"></a> <span class='hs-varid'>route</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>subserver</span> <span class='hs-varid'>request</span> <span class='hs-varid'>respond</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>pathInfo</span> <span class='hs-varid'>request</span> <span class='hs-keyword'>of</span>
61+<a name="line-52"></a> <span class='hs-layout'>(</span><span class='hs-varid'>first</span> <span class='hs-conop'>:</span> <span class='hs-varid'>rest</span><span class='hs-layout'>)</span>
62+<a name="line-53"></a> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>captured</span> <span class='hs-varid'>captureProxy</span> <span class='hs-varid'>first</span> <span class='hs-keyword'>of</span>
63+<a name="line-54"></a> <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>respond</span> <span class='hs-varop'>$</span> <span class='hs-varid'>failWith</span> <span class='hs-conid'>NotFound</span>
64+<a name="line-55"></a> <span class='hs-conid'>Just</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>route</span> <span class='hs-layout'>(</span><span class='hs-conid'>Proxy</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>sublayout</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>subserver</span> <span class='hs-varid'>v</span><span class='hs-layout'>)</span> <span class='hs-varid'>request</span><span class='hs-layout'>{</span>
65+<a name="line-56"></a> <span class='hs-varid'>pathInfo</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>rest</span>
66+<a name="line-57"></a> <span class='hs-layout'>}</span> <span class='hs-varid'>respond</span>
67+<a name="line-58"></a> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>respond</span> <span class='hs-varop'>$</span> <span class='hs-varid'>failWith</span> <span class='hs-conid'>NotFound</span>
68+<a name="line-59"></a>
69+<a name="line-60"></a> <span class='hs-keyword'>where</span> <span class='hs-varid'>captureProxy</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Proxy</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Proxy</span> <span class='hs-layout'>(</span><span class='hs-conid'>Capture</span> <span class='hs-varid'>capture</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span>
70+</pre></body>
71+</html>
src/Servant-API-Delete.htmlnew file+59
@@ -0,0 +1,59 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3+<html>
4+<head>
5+<!-- Generated by HsColour, http://code.haskell.org/~malcolm/hscolour/ -->
6+<title>src/Servant/API/Delete.hs</title>
7+<link type='text/css' rel='stylesheet' href='hscolour.css' />
8+</head>
9+<body>
10+<pre><a name="line-1"></a><span class='hs-comment'>{-# LANGUAGE TypeFamilies #-}</span>
11+<a name="line-2"></a><span class='hs-comment'>{-# LANGUAGE OverloadedStrings #-}</span>
12+<a name="line-3"></a><span class='hs-comment'>{-# LANGUAGE ScopedTypeVariables #-}</span>
13+<a name="line-4"></a><span class='hs-comment'>{-# LANGUAGE DeriveDataTypeable #-}</span>
14+<a name="line-5"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Delete</span> <span class='hs-keyword'>where</span>
15+<a name="line-6"></a>
16+<a name="line-7"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Monad</span><span class='hs-varop'>.</span><span class='hs-conid'>Trans</span><span class='hs-varop'>.</span><span class='hs-conid'>Either</span>
17+<a name="line-8"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Proxy</span>
18+<a name="line-9"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>String</span><span class='hs-varop'>.</span><span class='hs-conid'>Conversions</span>
19+<a name="line-10"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Typeable</span>
20+<a name="line-11"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Network</span><span class='hs-varop'>.</span><span class='hs-conid'>HTTP</span><span class='hs-varop'>.</span><span class='hs-conid'>Types</span>
21+<a name="line-12"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Network</span><span class='hs-varop'>.</span><span class='hs-conid'>Wai</span>
22+<a name="line-13"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Server</span>
23+<a name="line-14"></a>
24+<a name="line-15"></a><a name="Delete"></a><span class='hs-comment'>-- | Combinator for DELETE requests.</span>
25+<a name="line-16"></a><a name="Delete"></a><span class='hs-comment'>--</span>
26+<a name="line-17"></a><a name="Delete"></a><span class='hs-comment'>-- Example:</span>
27+<a name="line-18"></a><a name="Delete"></a><span class='hs-comment'>--</span>
28+<a name="line-19"></a><a name="Delete"></a><span class='hs-comment'>-- &gt; -- DELETE /books/:isbn</span>
29+<a name="line-20"></a><a name="Delete"></a><span class='hs-comment'>-- &gt; type MyApi = "books" :&gt; Capture "isbn" Text :&gt; Delete</span>
30+<a name="line-21"></a><a name="Delete"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>Delete</span>
31+<a name="line-22"></a> <span class='hs-keyword'>deriving</span> <span class='hs-conid'>Typeable</span>
32+<a name="line-23"></a>
33+<a name="line-24"></a><a name="instance%20HasServer%20Delete"></a><span class='hs-comment'>-- | If you have a 'Delete' endpoint in your API,</span>
34+<a name="line-25"></a><a name="instance%20HasServer%20Delete"></a><span class='hs-comment'>-- the handler for this endpoint is meant to delete</span>
35+<a name="line-26"></a><a name="instance%20HasServer%20Delete"></a><span class='hs-comment'>-- a resource.</span>
36+<a name="line-27"></a><a name="instance%20HasServer%20Delete"></a><span class='hs-comment'>--</span>
37+<a name="line-28"></a><a name="instance%20HasServer%20Delete"></a><span class='hs-comment'>-- The code of the handler will, just like</span>
38+<a name="line-29"></a><a name="instance%20HasServer%20Delete"></a><span class='hs-comment'>-- for 'Servant.API.Get.Get', 'Servant.API.Post.Post' and</span>
39+<a name="line-30"></a><a name="instance%20HasServer%20Delete"></a><span class='hs-comment'>-- 'Servant.API.Put.Put', run in @EitherT (Int, String) IO ()@.</span>
40+<a name="line-31"></a><a name="instance%20HasServer%20Delete"></a><span class='hs-comment'>-- The 'Int' represents the status code and the 'String' a message</span>
41+<a name="line-32"></a><a name="instance%20HasServer%20Delete"></a><span class='hs-comment'>-- to be returned. You can use 'Control.Monad.Trans.Either.left' to</span>
42+<a name="line-33"></a><a name="instance%20HasServer%20Delete"></a><span class='hs-comment'>-- painlessly error out if the conditions for a successful deletion</span>
43+<a name="line-34"></a><a name="instance%20HasServer%20Delete"></a><span class='hs-comment'>-- are not met.</span>
44+<a name="line-35"></a><a name="instance%20HasServer%20Delete"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>HasServer</span> <span class='hs-conid'>Delete</span> <span class='hs-keyword'>where</span>
45+<a name="line-36"></a> <span class='hs-keyword'>type</span> <span class='hs-conid'>Server</span> <span class='hs-conid'>Delete</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>EitherT</span> <span class='hs-layout'>(</span><span class='hs-conid'>Int</span><span class='hs-layout'>,</span> <span class='hs-conid'>String</span><span class='hs-layout'>)</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span>
46+<a name="line-37"></a>
47+<a name="line-38"></a> <span class='hs-varid'>route</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>action</span> <span class='hs-varid'>request</span> <span class='hs-varid'>respond</span>
48+<a name="line-39"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>null</span> <span class='hs-layout'>(</span><span class='hs-varid'>pathInfo</span> <span class='hs-varid'>request</span><span class='hs-layout'>)</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>requestMethod</span> <span class='hs-varid'>request</span> <span class='hs-varop'>==</span> <span class='hs-varid'>methodDelete</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
49+<a name="line-40"></a> <span class='hs-varid'>e</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>runEitherT</span> <span class='hs-varid'>action</span>
50+<a name="line-41"></a> <span class='hs-varid'>respond</span> <span class='hs-varop'>$</span> <span class='hs-varid'>succeedWith</span> <span class='hs-varop'>$</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>e</span> <span class='hs-keyword'>of</span>
51+<a name="line-42"></a> <span class='hs-conid'>Right</span> <span class='hs-conid'>()</span> <span class='hs-keyglyph'>-&gt;</span>
52+<a name="line-43"></a> <span class='hs-varid'>responseLBS</span> <span class='hs-varid'>status204</span> <span class='hs-conid'>[]</span> <span class='hs-str'>""</span>
53+<a name="line-44"></a> <span class='hs-conid'>Left</span> <span class='hs-layout'>(</span><span class='hs-varid'>status</span><span class='hs-layout'>,</span> <span class='hs-varid'>message</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
54+<a name="line-45"></a> <span class='hs-varid'>responseLBS</span> <span class='hs-layout'>(</span><span class='hs-varid'>mkStatus</span> <span class='hs-varid'>status</span> <span class='hs-layout'>(</span><span class='hs-varid'>cs</span> <span class='hs-varid'>message</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-conid'>[]</span> <span class='hs-layout'>(</span><span class='hs-varid'>cs</span> <span class='hs-varid'>message</span><span class='hs-layout'>)</span>
55+<a name="line-46"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>null</span> <span class='hs-layout'>(</span><span class='hs-varid'>pathInfo</span> <span class='hs-varid'>request</span><span class='hs-layout'>)</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>requestMethod</span> <span class='hs-varid'>request</span> <span class='hs-varop'>/=</span> <span class='hs-varid'>methodDelete</span> <span class='hs-keyglyph'>=</span>
56+<a name="line-47"></a> <span class='hs-varid'>respond</span> <span class='hs-varop'>$</span> <span class='hs-varid'>failWith</span> <span class='hs-conid'>WrongMethod</span>
57+<a name="line-48"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>respond</span> <span class='hs-varop'>$</span> <span class='hs-varid'>failWith</span> <span class='hs-conid'>NotFound</span>
58+</pre></body>
59+</html>
src/Servant-API-Get.htmlnew file+58
@@ -0,0 +1,58 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3+<html>
4+<head>
5+<!-- Generated by HsColour, http://code.haskell.org/~malcolm/hscolour/ -->
6+<title>src/Servant/API/Get.hs</title>
7+<link type='text/css' rel='stylesheet' href='hscolour.css' />
8+</head>
9+<body>
10+<pre><a name="line-1"></a><span class='hs-comment'>{-# LANGUAGE TypeFamilies #-}</span>
11+<a name="line-2"></a><span class='hs-comment'>{-# LANGUAGE OverloadedStrings #-}</span>
12+<a name="line-3"></a><span class='hs-comment'>{-# LANGUAGE ScopedTypeVariables #-}</span>
13+<a name="line-4"></a><span class='hs-comment'>{-# LANGUAGE DeriveDataTypeable #-}</span>
14+<a name="line-5"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Get</span> <span class='hs-keyword'>where</span>
15+<a name="line-6"></a>
16+<a name="line-7"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Monad</span><span class='hs-varop'>.</span><span class='hs-conid'>Trans</span><span class='hs-varop'>.</span><span class='hs-conid'>Either</span>
17+<a name="line-8"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Aeson</span>
18+<a name="line-9"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Proxy</span>
19+<a name="line-10"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>String</span><span class='hs-varop'>.</span><span class='hs-conid'>Conversions</span>
20+<a name="line-11"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Typeable</span>
21+<a name="line-12"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Network</span><span class='hs-varop'>.</span><span class='hs-conid'>HTTP</span><span class='hs-varop'>.</span><span class='hs-conid'>Types</span>
22+<a name="line-13"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Network</span><span class='hs-varop'>.</span><span class='hs-conid'>Wai</span>
23+<a name="line-14"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Server</span>
24+<a name="line-15"></a>
25+<a name="line-16"></a><a name="HasServer"></a><span class='hs-comment'>-- | Endpoint for simple GET requests. Serves the result as JSON.</span>
26+<a name="line-17"></a><a name="HasServer"></a><span class='hs-comment'>--</span>
27+<a name="line-18"></a><a name="HasServer"></a><span class='hs-comment'>-- Example:</span>
28+<a name="line-19"></a><a name="HasServer"></a><span class='hs-comment'>--</span>
29+<a name="line-20"></a><a name="HasServer"></a><span class='hs-comment'>-- &gt; type MyApi = "books" :&gt; Get [Book]</span>
30+<a name="line-21"></a><a name="HasServer"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>Get</span> <span class='hs-varid'>a</span>
31+<a name="line-22"></a> <span class='hs-keyword'>deriving</span> <span class='hs-conid'>Typeable</span>
32+<a name="line-23"></a>
33+<a name="line-24"></a><a name="instance%20HasServer%20(Get%20result)"></a><span class='hs-comment'>-- | When implementing the handler for a 'Get' endpoint,</span>
34+<a name="line-25"></a><a name="instance%20HasServer%20(Get%20result)"></a><span class='hs-comment'>-- just like for 'Servant.API.Delete.Delete', 'Servant.API.Post.Post'</span>
35+<a name="line-26"></a><a name="instance%20HasServer%20(Get%20result)"></a><span class='hs-comment'>-- and 'Servant.API.Put.Put', the handler code runs in the</span>
36+<a name="line-27"></a><a name="instance%20HasServer%20(Get%20result)"></a><span class='hs-comment'>-- @EitherT (Int, String) IO@ monad, where the 'Int' represents</span>
37+<a name="line-28"></a><a name="instance%20HasServer%20(Get%20result)"></a><span class='hs-comment'>-- the status code and the 'String' a message, returned in case of</span>
38+<a name="line-29"></a><a name="instance%20HasServer%20(Get%20result)"></a><span class='hs-comment'>-- failure. You can quite handily use 'Control.Monad.Trans.EitherT.left'</span>
39+<a name="line-30"></a><a name="instance%20HasServer%20(Get%20result)"></a><span class='hs-comment'>-- to quickly fail if some conditions are not met.</span>
40+<a name="line-31"></a><a name="instance%20HasServer%20(Get%20result)"></a><span class='hs-comment'>--</span>
41+<a name="line-32"></a><a name="instance%20HasServer%20(Get%20result)"></a><span class='hs-comment'>-- If successfully returning a value, we just require that its type has</span>
42+<a name="line-33"></a><a name="instance%20HasServer%20(Get%20result)"></a><span class='hs-comment'>-- a 'ToJSON' instance and servant takes care of encoding it for you,</span>
43+<a name="line-34"></a><a name="instance%20HasServer%20(Get%20result)"></a><span class='hs-comment'>-- yielding status code 200 along the way.</span>
44+<a name="line-35"></a><a name="instance%20HasServer%20(Get%20result)"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>ToJSON</span> <span class='hs-varid'>result</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>HasServer</span> <span class='hs-layout'>(</span><span class='hs-conid'>Get</span> <span class='hs-varid'>result</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
45+<a name="line-36"></a> <span class='hs-keyword'>type</span> <span class='hs-conid'>Server</span> <span class='hs-layout'>(</span><span class='hs-conid'>Get</span> <span class='hs-varid'>result</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>EitherT</span> <span class='hs-layout'>(</span><span class='hs-conid'>Int</span><span class='hs-layout'>,</span> <span class='hs-conid'>String</span><span class='hs-layout'>)</span> <span class='hs-conid'>IO</span> <span class='hs-varid'>result</span>
46+<a name="line-37"></a> <span class='hs-varid'>route</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>action</span> <span class='hs-varid'>request</span> <span class='hs-varid'>respond</span>
47+<a name="line-38"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>null</span> <span class='hs-layout'>(</span><span class='hs-varid'>pathInfo</span> <span class='hs-varid'>request</span><span class='hs-layout'>)</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>requestMethod</span> <span class='hs-varid'>request</span> <span class='hs-varop'>==</span> <span class='hs-varid'>methodGet</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
48+<a name="line-39"></a> <span class='hs-varid'>e</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>runEitherT</span> <span class='hs-varid'>action</span>
49+<a name="line-40"></a> <span class='hs-varid'>respond</span> <span class='hs-varop'>.</span> <span class='hs-varid'>succeedWith</span> <span class='hs-varop'>$</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>e</span> <span class='hs-keyword'>of</span>
50+<a name="line-41"></a> <span class='hs-conid'>Right</span> <span class='hs-varid'>output</span> <span class='hs-keyglyph'>-&gt;</span>
51+<a name="line-42"></a> <span class='hs-varid'>responseLBS</span> <span class='hs-varid'>ok200</span> <span class='hs-keyglyph'>[</span><span class='hs-layout'>(</span><span class='hs-str'>"Content-Type"</span><span class='hs-layout'>,</span> <span class='hs-str'>"application/json"</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>]</span> <span class='hs-layout'>(</span><span class='hs-varid'>encode</span> <span class='hs-varid'>output</span><span class='hs-layout'>)</span>
52+<a name="line-43"></a> <span class='hs-conid'>Left</span> <span class='hs-layout'>(</span><span class='hs-varid'>status</span><span class='hs-layout'>,</span> <span class='hs-varid'>message</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
53+<a name="line-44"></a> <span class='hs-varid'>responseLBS</span> <span class='hs-layout'>(</span><span class='hs-varid'>mkStatus</span> <span class='hs-varid'>status</span> <span class='hs-layout'>(</span><span class='hs-varid'>cs</span> <span class='hs-varid'>message</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-conid'>[]</span> <span class='hs-layout'>(</span><span class='hs-varid'>cs</span> <span class='hs-varid'>message</span><span class='hs-layout'>)</span>
54+<a name="line-45"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>null</span> <span class='hs-layout'>(</span><span class='hs-varid'>pathInfo</span> <span class='hs-varid'>request</span><span class='hs-layout'>)</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>requestMethod</span> <span class='hs-varid'>request</span> <span class='hs-varop'>/=</span> <span class='hs-varid'>methodGet</span> <span class='hs-keyglyph'>=</span>
55+<a name="line-46"></a> <span class='hs-varid'>respond</span> <span class='hs-varop'>$</span> <span class='hs-varid'>failWith</span> <span class='hs-conid'>WrongMethod</span>
56+<a name="line-47"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>respond</span> <span class='hs-varop'>$</span> <span class='hs-varid'>failWith</span> <span class='hs-conid'>NotFound</span>
57+</pre></body>
58+</html>
src/Servant-API-Post.htmlnew file+64
@@ -0,0 +1,64 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3+<html>
4+<head>
5+<!-- Generated by HsColour, http://code.haskell.org/~malcolm/hscolour/ -->
6+<title>src/Servant/API/Post.hs</title>
7+<link type='text/css' rel='stylesheet' href='hscolour.css' />
8+</head>
9+<body>
10+<pre><a name="line-1"></a><span class='hs-comment'>{-# LANGUAGE TypeFamilies #-}</span>
11+<a name="line-2"></a><span class='hs-comment'>{-# LANGUAGE OverloadedStrings #-}</span>
12+<a name="line-3"></a><span class='hs-comment'>{-# LANGUAGE ScopedTypeVariables #-}</span>
13+<a name="line-4"></a><span class='hs-comment'>{-# LANGUAGE DeriveDataTypeable #-}</span>
14+<a name="line-5"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Post</span> <span class='hs-keyword'>where</span>
15+<a name="line-6"></a>
16+<a name="line-7"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Monad</span><span class='hs-varop'>.</span><span class='hs-conid'>Trans</span><span class='hs-varop'>.</span><span class='hs-conid'>Either</span>
17+<a name="line-8"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Aeson</span>
18+<a name="line-9"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Proxy</span>
19+<a name="line-10"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>String</span><span class='hs-varop'>.</span><span class='hs-conid'>Conversions</span>
20+<a name="line-11"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Typeable</span>
21+<a name="line-12"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Network</span><span class='hs-varop'>.</span><span class='hs-conid'>HTTP</span><span class='hs-varop'>.</span><span class='hs-conid'>Types</span>
22+<a name="line-13"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Network</span><span class='hs-varop'>.</span><span class='hs-conid'>Wai</span>
23+<a name="line-14"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Server</span>
24+<a name="line-15"></a>
25+<a name="line-16"></a><a name="HasServer"></a><span class='hs-comment'>-- | Endpoint for POST requests. The type variable represents the type of the</span>
26+<a name="line-17"></a><a name="HasServer"></a><span class='hs-comment'>-- response body (not the request body, use 'Servant.API.RQBody.RQBody' for</span>
27+<a name="line-18"></a><a name="HasServer"></a><span class='hs-comment'>-- that).</span>
28+<a name="line-19"></a><a name="HasServer"></a><span class='hs-comment'>--</span>
29+<a name="line-20"></a><a name="HasServer"></a><span class='hs-comment'>-- Example:</span>
30+<a name="line-21"></a><a name="HasServer"></a><span class='hs-comment'>--</span>
31+<a name="line-22"></a><a name="HasServer"></a><span class='hs-comment'>-- &gt; -- POST /books</span>
32+<a name="line-23"></a><a name="HasServer"></a><span class='hs-comment'>-- &gt; -- with a JSON encoded Book as the request body</span>
33+<a name="line-24"></a><a name="HasServer"></a><span class='hs-comment'>-- &gt; -- returning the just-created Book</span>
34+<a name="line-25"></a><a name="HasServer"></a><span class='hs-comment'>-- &gt; type MyApi = "books" :&gt; ReqBody Book :&gt; Post Book</span>
35+<a name="line-26"></a><a name="HasServer"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>Post</span> <span class='hs-varid'>a</span>
36+<a name="line-27"></a> <span class='hs-keyword'>deriving</span> <span class='hs-conid'>Typeable</span>
37+<a name="line-28"></a>
38+<a name="line-29"></a><a name="instance%20HasServer%20(Post%20a)"></a><span class='hs-comment'>-- | When implementing the handler for a 'Post' endpoint,</span>
39+<a name="line-30"></a><a name="instance%20HasServer%20(Post%20a)"></a><span class='hs-comment'>-- just like for 'Servant.API.Delete.Delete', 'Servant.API.Get.Get'</span>
40+<a name="line-31"></a><a name="instance%20HasServer%20(Post%20a)"></a><span class='hs-comment'>-- and 'Servant.API.Put.Put', the handler code runs in the</span>
41+<a name="line-32"></a><a name="instance%20HasServer%20(Post%20a)"></a><span class='hs-comment'>-- @EitherT (Int, String) IO@ monad, where the 'Int' represents</span>
42+<a name="line-33"></a><a name="instance%20HasServer%20(Post%20a)"></a><span class='hs-comment'>-- the status code and the 'String' a message, returned in case of</span>
43+<a name="line-34"></a><a name="instance%20HasServer%20(Post%20a)"></a><span class='hs-comment'>-- failure. You can quite handily use 'Control.Monad.Trans.EitherT.left'</span>
44+<a name="line-35"></a><a name="instance%20HasServer%20(Post%20a)"></a><span class='hs-comment'>-- to quickly fail if some conditions are not met.</span>
45+<a name="line-36"></a><a name="instance%20HasServer%20(Post%20a)"></a><span class='hs-comment'>--</span>
46+<a name="line-37"></a><a name="instance%20HasServer%20(Post%20a)"></a><span class='hs-comment'>-- If successfully returning a value, we just require that its type has</span>
47+<a name="line-38"></a><a name="instance%20HasServer%20(Post%20a)"></a><span class='hs-comment'>-- a 'ToJSON' instance and servant takes care of encoding it for you,</span>
48+<a name="line-39"></a><a name="instance%20HasServer%20(Post%20a)"></a><span class='hs-comment'>-- yielding status code 201 along the way.</span>
49+<a name="line-40"></a><a name="instance%20HasServer%20(Post%20a)"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>ToJSON</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>HasServer</span> <span class='hs-layout'>(</span><span class='hs-conid'>Post</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
50+<a name="line-41"></a> <span class='hs-keyword'>type</span> <span class='hs-conid'>Server</span> <span class='hs-layout'>(</span><span class='hs-conid'>Post</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>EitherT</span> <span class='hs-layout'>(</span><span class='hs-conid'>Int</span><span class='hs-layout'>,</span> <span class='hs-conid'>String</span><span class='hs-layout'>)</span> <span class='hs-conid'>IO</span> <span class='hs-varid'>a</span>
51+<a name="line-42"></a>
52+<a name="line-43"></a> <span class='hs-varid'>route</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>action</span> <span class='hs-varid'>request</span> <span class='hs-varid'>respond</span>
53+<a name="line-44"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>null</span> <span class='hs-layout'>(</span><span class='hs-varid'>pathInfo</span> <span class='hs-varid'>request</span><span class='hs-layout'>)</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>requestMethod</span> <span class='hs-varid'>request</span> <span class='hs-varop'>==</span> <span class='hs-varid'>methodPost</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
54+<a name="line-45"></a> <span class='hs-varid'>e</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>runEitherT</span> <span class='hs-varid'>action</span>
55+<a name="line-46"></a> <span class='hs-varid'>respond</span> <span class='hs-varop'>.</span> <span class='hs-varid'>succeedWith</span> <span class='hs-varop'>$</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>e</span> <span class='hs-keyword'>of</span>
56+<a name="line-47"></a> <span class='hs-conid'>Right</span> <span class='hs-varid'>out</span> <span class='hs-keyglyph'>-&gt;</span>
57+<a name="line-48"></a> <span class='hs-varid'>responseLBS</span> <span class='hs-varid'>status201</span> <span class='hs-keyglyph'>[</span><span class='hs-layout'>(</span><span class='hs-str'>"Content-Type"</span><span class='hs-layout'>,</span> <span class='hs-str'>"application/json"</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>]</span> <span class='hs-layout'>(</span><span class='hs-varid'>encode</span> <span class='hs-varid'>out</span><span class='hs-layout'>)</span>
58+<a name="line-49"></a> <span class='hs-conid'>Left</span> <span class='hs-layout'>(</span><span class='hs-varid'>status</span><span class='hs-layout'>,</span> <span class='hs-varid'>message</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
59+<a name="line-50"></a> <span class='hs-varid'>responseLBS</span> <span class='hs-layout'>(</span><span class='hs-varid'>mkStatus</span> <span class='hs-varid'>status</span> <span class='hs-layout'>(</span><span class='hs-varid'>cs</span> <span class='hs-varid'>message</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-conid'>[]</span> <span class='hs-layout'>(</span><span class='hs-varid'>cs</span> <span class='hs-varid'>message</span><span class='hs-layout'>)</span>
60+<a name="line-51"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>null</span> <span class='hs-layout'>(</span><span class='hs-varid'>pathInfo</span> <span class='hs-varid'>request</span><span class='hs-layout'>)</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>requestMethod</span> <span class='hs-varid'>request</span> <span class='hs-varop'>/=</span> <span class='hs-varid'>methodPost</span> <span class='hs-keyglyph'>=</span>
61+<a name="line-52"></a> <span class='hs-varid'>respond</span> <span class='hs-varop'>$</span> <span class='hs-varid'>failWith</span> <span class='hs-conid'>WrongMethod</span>
62+<a name="line-53"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>respond</span> <span class='hs-varop'>$</span> <span class='hs-varid'>failWith</span> <span class='hs-conid'>NotFound</span>
63+</pre></body>
64+</html>
src/Servant-API-Put.htmlnew file+63
@@ -0,0 +1,63 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3+<html>
4+<head>
5+<!-- Generated by HsColour, http://code.haskell.org/~malcolm/hscolour/ -->
6+<title>src/Servant/API/Put.hs</title>
7+<link type='text/css' rel='stylesheet' href='hscolour.css' />
8+</head>
9+<body>
10+<pre><a name="line-1"></a><span class='hs-comment'>{-# LANGUAGE TypeFamilies #-}</span>
11+<a name="line-2"></a><span class='hs-comment'>{-# LANGUAGE OverloadedStrings #-}</span>
12+<a name="line-3"></a><span class='hs-comment'>{-# LANGUAGE ScopedTypeVariables #-}</span>
13+<a name="line-4"></a><span class='hs-comment'>{-# LANGUAGE DeriveDataTypeable #-}</span>
14+<a name="line-5"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Put</span> <span class='hs-keyword'>where</span>
15+<a name="line-6"></a>
16+<a name="line-7"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Monad</span><span class='hs-varop'>.</span><span class='hs-conid'>Trans</span><span class='hs-varop'>.</span><span class='hs-conid'>Either</span>
17+<a name="line-8"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Aeson</span>
18+<a name="line-9"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Proxy</span>
19+<a name="line-10"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>String</span><span class='hs-varop'>.</span><span class='hs-conid'>Conversions</span>
20+<a name="line-11"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Typeable</span>
21+<a name="line-12"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Network</span><span class='hs-varop'>.</span><span class='hs-conid'>HTTP</span><span class='hs-varop'>.</span><span class='hs-conid'>Types</span>
22+<a name="line-13"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Network</span><span class='hs-varop'>.</span><span class='hs-conid'>Wai</span>
23+<a name="line-14"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Server</span>
24+<a name="line-15"></a>
25+<a name="line-16"></a><a name="HasServer"></a><span class='hs-comment'>-- | Endpoint for PUT requests, usually used to update a ressource.</span>
26+<a name="line-17"></a><a name="HasServer"></a><span class='hs-comment'>-- The type @a@ is the type of the response body that's returned.</span>
27+<a name="line-18"></a><a name="HasServer"></a><span class='hs-comment'>--</span>
28+<a name="line-19"></a><a name="HasServer"></a><span class='hs-comment'>-- Example:</span>
29+<a name="line-20"></a><a name="HasServer"></a><span class='hs-comment'>--</span>
30+<a name="line-21"></a><a name="HasServer"></a><span class='hs-comment'>-- &gt; -- PUT /books/:isbn</span>
31+<a name="line-22"></a><a name="HasServer"></a><span class='hs-comment'>-- &gt; -- with a Book as request body, returning the updated Book</span>
32+<a name="line-23"></a><a name="HasServer"></a><span class='hs-comment'>-- &gt; type MyApi = "books" :&gt; Capture "isbn" Text :&gt; ReqBody Book :&gt; Put Book</span>
33+<a name="line-24"></a><a name="HasServer"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>Put</span> <span class='hs-varid'>a</span>
34+<a name="line-25"></a> <span class='hs-keyword'>deriving</span> <span class='hs-conid'>Typeable</span>
35+<a name="line-26"></a>
36+<a name="line-27"></a><a name="instance%20HasServer%20(Put%20a)"></a><span class='hs-comment'>-- | When implementing the handler for a 'Put' endpoint,</span>
37+<a name="line-28"></a><a name="instance%20HasServer%20(Put%20a)"></a><span class='hs-comment'>-- just like for 'Servant.API.Delete.Delete', 'Servant.API.Get.Get'</span>
38+<a name="line-29"></a><a name="instance%20HasServer%20(Put%20a)"></a><span class='hs-comment'>-- and 'Servant.API.Post.Post', the handler code runs in the</span>
39+<a name="line-30"></a><a name="instance%20HasServer%20(Put%20a)"></a><span class='hs-comment'>-- @EitherT (Int, String) IO@ monad, where the 'Int' represents</span>
40+<a name="line-31"></a><a name="instance%20HasServer%20(Put%20a)"></a><span class='hs-comment'>-- the status code and the 'String' a message, returned in case of</span>
41+<a name="line-32"></a><a name="instance%20HasServer%20(Put%20a)"></a><span class='hs-comment'>-- failure. You can quite handily use 'Control.Monad.Trans.EitherT.left'</span>
42+<a name="line-33"></a><a name="instance%20HasServer%20(Put%20a)"></a><span class='hs-comment'>-- to quickly fail if some conditions are not met.</span>
43+<a name="line-34"></a><a name="instance%20HasServer%20(Put%20a)"></a><span class='hs-comment'>--</span>
44+<a name="line-35"></a><a name="instance%20HasServer%20(Put%20a)"></a><span class='hs-comment'>-- If successfully returning a value, we just require that its type has</span>
45+<a name="line-36"></a><a name="instance%20HasServer%20(Put%20a)"></a><span class='hs-comment'>-- a 'ToJSON' instance and servant takes care of encoding it for you,</span>
46+<a name="line-37"></a><a name="instance%20HasServer%20(Put%20a)"></a><span class='hs-comment'>-- yielding status code 200 along the way.</span>
47+<a name="line-38"></a><a name="instance%20HasServer%20(Put%20a)"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>ToJSON</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>HasServer</span> <span class='hs-layout'>(</span><span class='hs-conid'>Put</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
48+<a name="line-39"></a> <span class='hs-keyword'>type</span> <span class='hs-conid'>Server</span> <span class='hs-layout'>(</span><span class='hs-conid'>Put</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>EitherT</span> <span class='hs-layout'>(</span><span class='hs-conid'>Int</span><span class='hs-layout'>,</span> <span class='hs-conid'>String</span><span class='hs-layout'>)</span> <span class='hs-conid'>IO</span> <span class='hs-varid'>a</span>
49+<a name="line-40"></a>
50+<a name="line-41"></a> <span class='hs-varid'>route</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>action</span> <span class='hs-varid'>request</span> <span class='hs-varid'>respond</span>
51+<a name="line-42"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>null</span> <span class='hs-layout'>(</span><span class='hs-varid'>pathInfo</span> <span class='hs-varid'>request</span><span class='hs-layout'>)</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>requestMethod</span> <span class='hs-varid'>request</span> <span class='hs-varop'>==</span> <span class='hs-varid'>methodPut</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
52+<a name="line-43"></a> <span class='hs-varid'>e</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>runEitherT</span> <span class='hs-varid'>action</span>
53+<a name="line-44"></a> <span class='hs-varid'>respond</span> <span class='hs-varop'>.</span> <span class='hs-varid'>succeedWith</span> <span class='hs-varop'>$</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>e</span> <span class='hs-keyword'>of</span>
54+<a name="line-45"></a> <span class='hs-conid'>Right</span> <span class='hs-varid'>out</span> <span class='hs-keyglyph'>-&gt;</span>
55+<a name="line-46"></a> <span class='hs-varid'>responseLBS</span> <span class='hs-varid'>ok200</span> <span class='hs-keyglyph'>[</span><span class='hs-layout'>(</span><span class='hs-str'>"Content-Type"</span><span class='hs-layout'>,</span> <span class='hs-str'>"application/json"</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>]</span> <span class='hs-layout'>(</span><span class='hs-varid'>encode</span> <span class='hs-varid'>out</span><span class='hs-layout'>)</span>
56+<a name="line-47"></a> <span class='hs-conid'>Left</span> <span class='hs-layout'>(</span><span class='hs-varid'>status</span><span class='hs-layout'>,</span> <span class='hs-varid'>message</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
57+<a name="line-48"></a> <span class='hs-varid'>responseLBS</span> <span class='hs-layout'>(</span><span class='hs-varid'>mkStatus</span> <span class='hs-varid'>status</span> <span class='hs-layout'>(</span><span class='hs-varid'>cs</span> <span class='hs-varid'>message</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-conid'>[]</span> <span class='hs-layout'>(</span><span class='hs-varid'>cs</span> <span class='hs-varid'>message</span><span class='hs-layout'>)</span>
58+<a name="line-49"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>null</span> <span class='hs-layout'>(</span><span class='hs-varid'>pathInfo</span> <span class='hs-varid'>request</span><span class='hs-layout'>)</span> <span class='hs-varop'>&amp;&amp;</span> <span class='hs-varid'>requestMethod</span> <span class='hs-varid'>request</span> <span class='hs-varop'>/=</span> <span class='hs-varid'>methodPut</span> <span class='hs-keyglyph'>=</span>
59+<a name="line-50"></a> <span class='hs-varid'>respond</span> <span class='hs-varop'>$</span> <span class='hs-varid'>failWith</span> <span class='hs-conid'>WrongMethod</span>
60+<a name="line-51"></a>
61+<a name="line-52"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>respond</span> <span class='hs-varop'>$</span> <span class='hs-varid'>failWith</span> <span class='hs-conid'>NotFound</span>
62+</pre></body>
63+</html>
src/Servant-API-QueryParam.htmlnew file+173
@@ -0,0 +1,173 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3+<html>
4+<head>
5+<!-- Generated by HsColour, http://code.haskell.org/~malcolm/hscolour/ -->
6+<title>src/Servant/API/QueryParam.hs</title>
7+<link type='text/css' rel='stylesheet' href='hscolour.css' />
8+</head>
9+<body>
10+<pre><a name="line-1"></a><span class='hs-comment'>{-# LANGUAGE PolyKinds #-}</span>
11+<a name="line-2"></a><span class='hs-comment'>{-# LANGUAGE TypeFamilies #-}</span>
12+<a name="line-3"></a><span class='hs-comment'>{-# LANGUAGE TypeOperators #-}</span>
13+<a name="line-4"></a><span class='hs-comment'>{-# LANGUAGE FlexibleContexts #-}</span>
14+<a name="line-5"></a><span class='hs-comment'>{-# LANGUAGE FlexibleInstances #-}</span>
15+<a name="line-6"></a><span class='hs-comment'>{-# LANGUAGE OverloadedStrings #-}</span>
16+<a name="line-7"></a><span class='hs-comment'>{-# LANGUAGE ScopedTypeVariables #-}</span>
17+<a name="line-8"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>QueryParam</span> <span class='hs-keyword'>where</span>
18+<a name="line-9"></a>
19+<a name="line-10"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Maybe</span>
20+<a name="line-11"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Proxy</span>
21+<a name="line-12"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>String</span><span class='hs-varop'>.</span><span class='hs-conid'>Conversions</span>
22+<a name="line-13"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>TypeLits</span>
23+<a name="line-14"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Network</span><span class='hs-varop'>.</span><span class='hs-conid'>HTTP</span><span class='hs-varop'>.</span><span class='hs-conid'>Types</span>
24+<a name="line-15"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Network</span><span class='hs-varop'>.</span><span class='hs-conid'>Wai</span>
25+<a name="line-16"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Sub</span>
26+<a name="line-17"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Common</span><span class='hs-varop'>.</span><span class='hs-conid'>Text</span>
27+<a name="line-18"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Server</span>
28+<a name="line-19"></a>
29+<a name="line-20"></a><a name="HasServer"></a><span class='hs-comment'>-- | Lookup the value associated to the @sym@ query string parameter</span>
30+<a name="line-21"></a><a name="HasServer"></a><span class='hs-comment'>-- and try to extract it as a value of type @a@.</span>
31+<a name="line-22"></a><a name="HasServer"></a><span class='hs-comment'>--</span>
32+<a name="line-23"></a><a name="HasServer"></a><span class='hs-comment'>-- Example:</span>
33+<a name="line-24"></a><a name="HasServer"></a><span class='hs-comment'>--</span>
34+<a name="line-25"></a><a name="HasServer"></a><span class='hs-comment'>-- &gt; -- /books?author=&lt;author name&gt;</span>
35+<a name="line-26"></a><a name="HasServer"></a><span class='hs-comment'>-- &gt; type MyApi = "books" :&gt; QueryParam "author" Text :&gt; Get [Book]</span>
36+<a name="line-27"></a><a name="HasServer"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>QueryParam</span> <span class='hs-varid'>sym</span> <span class='hs-varid'>a</span>
37+<a name="line-28"></a>
38+<a name="line-29"></a><a name="instance%20HasServer%20(QueryParam%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- | If you use @'QueryParam' "author" Text@ in one of the endpoints for your API,</span>
39+<a name="line-30"></a><a name="instance%20HasServer%20(QueryParam%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- this automatically requires your server-side handler to be a function</span>
40+<a name="line-31"></a><a name="instance%20HasServer%20(QueryParam%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- that takes an argument of type @'Maybe' 'Text'@.</span>
41+<a name="line-32"></a><a name="instance%20HasServer%20(QueryParam%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>--</span>
42+<a name="line-33"></a><a name="instance%20HasServer%20(QueryParam%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- This lets servant worry about looking it up in the query string</span>
43+<a name="line-34"></a><a name="instance%20HasServer%20(QueryParam%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- and turning it into a value of the type you specify, enclosed</span>
44+<a name="line-35"></a><a name="instance%20HasServer%20(QueryParam%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- in 'Maybe', because it may not be there and servant would then</span>
45+<a name="line-36"></a><a name="instance%20HasServer%20(QueryParam%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- hand you 'Nothing'.</span>
46+<a name="line-37"></a><a name="instance%20HasServer%20(QueryParam%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>--</span>
47+<a name="line-38"></a><a name="instance%20HasServer%20(QueryParam%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- You can control how it'll be converted from 'Text' to your type</span>
48+<a name="line-39"></a><a name="instance%20HasServer%20(QueryParam%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- by simply providing an instance of 'FromText' for your type.</span>
49+<a name="line-40"></a><a name="instance%20HasServer%20(QueryParam%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>--</span>
50+<a name="line-41"></a><a name="instance%20HasServer%20(QueryParam%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- Example:</span>
51+<a name="line-42"></a><a name="instance%20HasServer%20(QueryParam%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>--</span>
52+<a name="line-43"></a><a name="instance%20HasServer%20(QueryParam%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; type MyApi = "books" :&gt; QueryParam "author" Text :&gt; Get [Book]</span>
53+<a name="line-44"></a><a name="instance%20HasServer%20(QueryParam%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt;</span>
54+<a name="line-45"></a><a name="instance%20HasServer%20(QueryParam%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; server :: Server MyApi</span>
55+<a name="line-46"></a><a name="instance%20HasServer%20(QueryParam%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; server = getBooksBy</span>
56+<a name="line-47"></a><a name="instance%20HasServer%20(QueryParam%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; where getBooksBy :: Maybe Text -&gt; EitherT (Int, String) IO [Book]</span>
57+<a name="line-48"></a><a name="instance%20HasServer%20(QueryParam%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; getBooksBy Nothing = ...return all books...</span>
58+<a name="line-49"></a><a name="instance%20HasServer%20(QueryParam%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; getBooksBy (Just author) = ...return books by the given author...</span>
59+<a name="line-50"></a><a name="instance%20HasServer%20(QueryParam%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-keyword'>instance</span> <span class='hs-layout'>(</span><span class='hs-conid'>KnownSymbol</span> <span class='hs-varid'>sym</span><span class='hs-layout'>,</span> <span class='hs-conid'>FromText</span> <span class='hs-varid'>a</span><span class='hs-layout'>,</span> <span class='hs-conid'>HasServer</span> <span class='hs-varid'>sublayout</span><span class='hs-layout'>)</span>
60+<a name="line-51"></a> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>HasServer</span> <span class='hs-layout'>(</span><span class='hs-conid'>QueryParam</span> <span class='hs-varid'>sym</span> <span class='hs-varid'>a</span> <span class='hs-conop'>:&gt;</span> <span class='hs-varid'>sublayout</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
61+<a name="line-52"></a>
62+<a name="line-53"></a> <span class='hs-keyword'>type</span> <span class='hs-conid'>Server</span> <span class='hs-layout'>(</span><span class='hs-conid'>QueryParam</span> <span class='hs-varid'>sym</span> <span class='hs-varid'>a</span> <span class='hs-conop'>:&gt;</span> <span class='hs-varid'>sublayout</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span>
63+<a name="line-54"></a> <span class='hs-conid'>Maybe</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Server</span> <span class='hs-varid'>sublayout</span>
64+<a name="line-55"></a>
65+<a name="line-56"></a> <span class='hs-varid'>route</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>subserver</span> <span class='hs-varid'>request</span> <span class='hs-varid'>respond</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
66+<a name="line-57"></a> <span class='hs-keyword'>let</span> <span class='hs-varid'>querytext</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>parseQueryText</span> <span class='hs-varop'>$</span> <span class='hs-varid'>rawQueryString</span> <span class='hs-varid'>request</span>
67+<a name="line-58"></a> <span class='hs-varid'>param</span> <span class='hs-keyglyph'>=</span>
68+<a name="line-59"></a> <span class='hs-keyword'>case</span> <span class='hs-varid'>lookup</span> <span class='hs-varid'>paramname</span> <span class='hs-varid'>querytext</span> <span class='hs-keyword'>of</span>
69+<a name="line-60"></a> <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Nothing</span> <span class='hs-comment'>-- param absent from the query string</span>
70+<a name="line-61"></a> <span class='hs-conid'>Just</span> <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Nothing</span> <span class='hs-comment'>-- param present with no value -&gt; Nothing</span>
71+<a name="line-62"></a> <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-conid'>Just</span> <span class='hs-varid'>v</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>fromText</span> <span class='hs-varid'>v</span> <span class='hs-comment'>-- if present, we try to convert to</span>
72+<a name="line-63"></a> <span class='hs-comment'>-- the right type</span>
73+<a name="line-64"></a>
74+<a name="line-65"></a> <span class='hs-varid'>route</span> <span class='hs-layout'>(</span><span class='hs-conid'>Proxy</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>sublayout</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>subserver</span> <span class='hs-varid'>param</span><span class='hs-layout'>)</span> <span class='hs-varid'>request</span> <span class='hs-varid'>respond</span>
75+<a name="line-66"></a>
76+<a name="line-67"></a> <span class='hs-keyword'>where</span> <span class='hs-varid'>paramname</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>cs</span> <span class='hs-varop'>$</span> <span class='hs-varid'>symbolVal</span> <span class='hs-layout'>(</span><span class='hs-conid'>Proxy</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>sym</span><span class='hs-layout'>)</span>
77+<a name="line-68"></a>
78+<a name="line-69"></a><a name="HasServer"></a><span class='hs-comment'>-- | Lookup the values associated to the @sym@ query string parameter</span>
79+<a name="line-70"></a><a name="HasServer"></a><span class='hs-comment'>-- and try to extract it as a value of type @[a]@. This is typically</span>
80+<a name="line-71"></a><a name="HasServer"></a><span class='hs-comment'>-- meant to support query string parameters of the form</span>
81+<a name="line-72"></a><a name="HasServer"></a><span class='hs-comment'>-- @param[]=val1&amp;param[]=val2@ and so on. Note that servant doesn't actually</span>
82+<a name="line-73"></a><a name="HasServer"></a><span class='hs-comment'>-- require the @[]@s and will fetch the values just fine with</span>
83+<a name="line-74"></a><a name="HasServer"></a><span class='hs-comment'>-- @param=val1&amp;param=val2@, too.</span>
84+<a name="line-75"></a><a name="HasServer"></a><span class='hs-comment'>--</span>
85+<a name="line-76"></a><a name="HasServer"></a><span class='hs-comment'>-- Example:</span>
86+<a name="line-77"></a><a name="HasServer"></a><span class='hs-comment'>--</span>
87+<a name="line-78"></a><a name="HasServer"></a><span class='hs-comment'>-- &gt; -- /books?authors[]=&lt;author1&gt;&amp;authors[]=&lt;author2&gt;&amp;...</span>
88+<a name="line-79"></a><a name="HasServer"></a><span class='hs-comment'>-- &gt; type MyApi = "books" :&gt; QueryParams "authors" Text :&gt; Get [Book]</span>
89+<a name="line-80"></a><a name="HasServer"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>QueryParams</span> <span class='hs-varid'>sym</span> <span class='hs-varid'>a</span>
90+<a name="line-81"></a>
91+<a name="line-82"></a><a name="instance%20HasServer%20(QueryParams%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- | If you use @'QueryParams' "authors" Text@ in one of the endpoints for your API,</span>
92+<a name="line-83"></a><a name="instance%20HasServer%20(QueryParams%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- this automatically requires your server-side handler to be a function</span>
93+<a name="line-84"></a><a name="instance%20HasServer%20(QueryParams%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- that takes an argument of type @['Text']@.</span>
94+<a name="line-85"></a><a name="instance%20HasServer%20(QueryParams%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>--</span>
95+<a name="line-86"></a><a name="instance%20HasServer%20(QueryParams%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- This lets servant worry about looking up 0 or more values in the query string</span>
96+<a name="line-87"></a><a name="instance%20HasServer%20(QueryParams%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- associated to @authors@ and turning each of them into a value of</span>
97+<a name="line-88"></a><a name="instance%20HasServer%20(QueryParams%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- the type you specify.</span>
98+<a name="line-89"></a><a name="instance%20HasServer%20(QueryParams%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>--</span>
99+<a name="line-90"></a><a name="instance%20HasServer%20(QueryParams%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- You can control how the individual values are converted from 'Text' to your type</span>
100+<a name="line-91"></a><a name="instance%20HasServer%20(QueryParams%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- by simply providing an instance of 'FromText' for your type.</span>
101+<a name="line-92"></a><a name="instance%20HasServer%20(QueryParams%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>--</span>
102+<a name="line-93"></a><a name="instance%20HasServer%20(QueryParams%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- Example:</span>
103+<a name="line-94"></a><a name="instance%20HasServer%20(QueryParams%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>--</span>
104+<a name="line-95"></a><a name="instance%20HasServer%20(QueryParams%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; type MyApi = "books" :&gt; QueryParams "authors" Text :&gt; Get [Book]</span>
105+<a name="line-96"></a><a name="instance%20HasServer%20(QueryParams%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt;</span>
106+<a name="line-97"></a><a name="instance%20HasServer%20(QueryParams%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; server :: Server MyApi</span>
107+<a name="line-98"></a><a name="instance%20HasServer%20(QueryParams%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; server = getBooksBy</span>
108+<a name="line-99"></a><a name="instance%20HasServer%20(QueryParams%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; where getBooksBy :: [Text] -&gt; EitherT (Int, String) IO [Book]</span>
109+<a name="line-100"></a><a name="instance%20HasServer%20(QueryParams%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; getBooksBy authors = ...return all books by these authors...</span>
110+<a name="line-101"></a><a name="instance%20HasServer%20(QueryParams%20sym%20a%20:%3e%20sublayout)"></a><span class='hs-keyword'>instance</span> <span class='hs-layout'>(</span><span class='hs-conid'>KnownSymbol</span> <span class='hs-varid'>sym</span><span class='hs-layout'>,</span> <span class='hs-conid'>FromText</span> <span class='hs-varid'>a</span><span class='hs-layout'>,</span> <span class='hs-conid'>HasServer</span> <span class='hs-varid'>sublayout</span><span class='hs-layout'>)</span>
111+<a name="line-102"></a> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>HasServer</span> <span class='hs-layout'>(</span><span class='hs-conid'>QueryParams</span> <span class='hs-varid'>sym</span> <span class='hs-varid'>a</span> <span class='hs-conop'>:&gt;</span> <span class='hs-varid'>sublayout</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
112+<a name="line-103"></a>
113+<a name="line-104"></a> <span class='hs-keyword'>type</span> <span class='hs-conid'>Server</span> <span class='hs-layout'>(</span><span class='hs-conid'>QueryParams</span> <span class='hs-varid'>sym</span> <span class='hs-varid'>a</span> <span class='hs-conop'>:&gt;</span> <span class='hs-varid'>sublayout</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span>
114+<a name="line-105"></a> <span class='hs-keyglyph'>[</span><span class='hs-varid'>a</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Server</span> <span class='hs-varid'>sublayout</span>
115+<a name="line-106"></a>
116+<a name="line-107"></a> <span class='hs-varid'>route</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>subserver</span> <span class='hs-varid'>request</span> <span class='hs-varid'>respond</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
117+<a name="line-108"></a> <span class='hs-keyword'>let</span> <span class='hs-varid'>querytext</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>parseQueryText</span> <span class='hs-varop'>$</span> <span class='hs-varid'>rawQueryString</span> <span class='hs-varid'>request</span>
118+<a name="line-109"></a> <span class='hs-comment'>-- if sym is "foo", we look for query string parameters</span>
119+<a name="line-110"></a> <span class='hs-comment'>-- named "foo" or "foo[]" and call fromText on the</span>
120+<a name="line-111"></a> <span class='hs-comment'>-- corresponding values</span>
121+<a name="line-112"></a> <span class='hs-varid'>parameters</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>filter</span> <span class='hs-varid'>looksLikeParam</span> <span class='hs-varid'>querytext</span>
122+<a name="line-113"></a> <span class='hs-varid'>values</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>catMaybes</span> <span class='hs-varop'>$</span> <span class='hs-varid'>map</span> <span class='hs-layout'>(</span><span class='hs-varid'>convert</span> <span class='hs-varop'>.</span> <span class='hs-varid'>snd</span><span class='hs-layout'>)</span> <span class='hs-varid'>parameters</span>
123+<a name="line-114"></a>
124+<a name="line-115"></a> <span class='hs-varid'>route</span> <span class='hs-layout'>(</span><span class='hs-conid'>Proxy</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>sublayout</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>subserver</span> <span class='hs-varid'>values</span><span class='hs-layout'>)</span> <span class='hs-varid'>request</span> <span class='hs-varid'>respond</span>
125+<a name="line-116"></a>
126+<a name="line-117"></a> <span class='hs-keyword'>where</span> <span class='hs-varid'>paramname</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>cs</span> <span class='hs-varop'>$</span> <span class='hs-varid'>symbolVal</span> <span class='hs-layout'>(</span><span class='hs-conid'>Proxy</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>sym</span><span class='hs-layout'>)</span>
127+<a name="line-118"></a> <span class='hs-varid'>looksLikeParam</span> <span class='hs-layout'>(</span><span class='hs-varid'>name</span><span class='hs-layout'>,</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>name</span> <span class='hs-varop'>==</span> <span class='hs-varid'>paramname</span> <span class='hs-varop'>||</span> <span class='hs-varid'>name</span> <span class='hs-varop'>==</span> <span class='hs-layout'>(</span><span class='hs-varid'>paramname</span> <span class='hs-varop'>&lt;&gt;</span> <span class='hs-str'>"[]"</span><span class='hs-layout'>)</span>
128+<a name="line-119"></a> <span class='hs-varid'>convert</span> <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Nothing</span>
129+<a name="line-120"></a> <span class='hs-varid'>convert</span> <span class='hs-layout'>(</span><span class='hs-conid'>Just</span> <span class='hs-varid'>v</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>fromText</span> <span class='hs-varid'>v</span>
130+<a name="line-121"></a>
131+<a name="line-122"></a><a name="HasServer"></a><span class='hs-comment'>-- | Lookup a potentially value-less query string parameter</span>
132+<a name="line-123"></a><a name="HasServer"></a><span class='hs-comment'>-- with boolean semantics. If the param @sym@ is there without any value,</span>
133+<a name="line-124"></a><a name="HasServer"></a><span class='hs-comment'>-- or if it's there with value "true" or "1", it's interpreted as 'True'.</span>
134+<a name="line-125"></a><a name="HasServer"></a><span class='hs-comment'>-- Otherwise, it's interpreted as 'False'.</span>
135+<a name="line-126"></a><a name="HasServer"></a><span class='hs-comment'>--</span>
136+<a name="line-127"></a><a name="HasServer"></a><span class='hs-comment'>-- Example:</span>
137+<a name="line-128"></a><a name="HasServer"></a><span class='hs-comment'>--</span>
138+<a name="line-129"></a><a name="HasServer"></a><span class='hs-comment'>-- &gt; -- /books?published</span>
139+<a name="line-130"></a><a name="HasServer"></a><span class='hs-comment'>-- &gt; type MyApi = "books" :&gt; QueryFlag "published" :&gt; Get [Book]</span>
140+<a name="line-131"></a><a name="HasServer"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>QueryFlag</span> <span class='hs-varid'>sym</span>
141+<a name="line-132"></a>
142+<a name="line-133"></a><a name="instance%20HasServer%20(QueryFlag%20sym%20:%3e%20sublayout)"></a><span class='hs-comment'>-- | If you use @'QueryFlag' "published"@ in one of the endpoints for your API,</span>
143+<a name="line-134"></a><a name="instance%20HasServer%20(QueryFlag%20sym%20:%3e%20sublayout)"></a><span class='hs-comment'>-- this automatically requires your server-side handler to be a function</span>
144+<a name="line-135"></a><a name="instance%20HasServer%20(QueryFlag%20sym%20:%3e%20sublayout)"></a><span class='hs-comment'>-- that takes an argument of type 'Bool'.</span>
145+<a name="line-136"></a><a name="instance%20HasServer%20(QueryFlag%20sym%20:%3e%20sublayout)"></a><span class='hs-comment'>--</span>
146+<a name="line-137"></a><a name="instance%20HasServer%20(QueryFlag%20sym%20:%3e%20sublayout)"></a><span class='hs-comment'>-- Example:</span>
147+<a name="line-138"></a><a name="instance%20HasServer%20(QueryFlag%20sym%20:%3e%20sublayout)"></a><span class='hs-comment'>--</span>
148+<a name="line-139"></a><a name="instance%20HasServer%20(QueryFlag%20sym%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; type MyApi = "books" :&gt; QueryFlag "published" :&gt; Get [Book]</span>
149+<a name="line-140"></a><a name="instance%20HasServer%20(QueryFlag%20sym%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt;</span>
150+<a name="line-141"></a><a name="instance%20HasServer%20(QueryFlag%20sym%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; server :: Server MyApi</span>
151+<a name="line-142"></a><a name="instance%20HasServer%20(QueryFlag%20sym%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; server = getBooks</span>
152+<a name="line-143"></a><a name="instance%20HasServer%20(QueryFlag%20sym%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; where getBooks :: Bool -&gt; EitherT (Int, String) IO [Book]</span>
153+<a name="line-144"></a><a name="instance%20HasServer%20(QueryFlag%20sym%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; getBooks onlyPublished = ...return all books, or only the ones that are already published, depending on the argument...</span>
154+<a name="line-145"></a><a name="instance%20HasServer%20(QueryFlag%20sym%20:%3e%20sublayout)"></a><span class='hs-keyword'>instance</span> <span class='hs-layout'>(</span><span class='hs-conid'>KnownSymbol</span> <span class='hs-varid'>sym</span><span class='hs-layout'>,</span> <span class='hs-conid'>HasServer</span> <span class='hs-varid'>sublayout</span><span class='hs-layout'>)</span>
155+<a name="line-146"></a> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>HasServer</span> <span class='hs-layout'>(</span><span class='hs-conid'>QueryFlag</span> <span class='hs-varid'>sym</span> <span class='hs-conop'>:&gt;</span> <span class='hs-varid'>sublayout</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
156+<a name="line-147"></a>
157+<a name="line-148"></a> <span class='hs-keyword'>type</span> <span class='hs-conid'>Server</span> <span class='hs-layout'>(</span><span class='hs-conid'>QueryFlag</span> <span class='hs-varid'>sym</span> <span class='hs-conop'>:&gt;</span> <span class='hs-varid'>sublayout</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span>
158+<a name="line-149"></a> <span class='hs-conid'>Bool</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Server</span> <span class='hs-varid'>sublayout</span>
159+<a name="line-150"></a>
160+<a name="line-151"></a> <span class='hs-varid'>route</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>subserver</span> <span class='hs-varid'>request</span> <span class='hs-varid'>respond</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
161+<a name="line-152"></a> <span class='hs-keyword'>let</span> <span class='hs-varid'>querytext</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>parseQueryText</span> <span class='hs-varop'>$</span> <span class='hs-varid'>rawQueryString</span> <span class='hs-varid'>request</span>
162+<a name="line-153"></a> <span class='hs-varid'>param</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>lookup</span> <span class='hs-varid'>paramname</span> <span class='hs-varid'>querytext</span> <span class='hs-keyword'>of</span>
163+<a name="line-154"></a> <span class='hs-conid'>Just</span> <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>True</span> <span class='hs-comment'>-- param is there, with no value</span>
164+<a name="line-155"></a> <span class='hs-conid'>Just</span> <span class='hs-layout'>(</span><span class='hs-conid'>Just</span> <span class='hs-varid'>v</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>examine</span> <span class='hs-varid'>v</span> <span class='hs-comment'>-- param with a value</span>
165+<a name="line-156"></a> <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>False</span> <span class='hs-comment'>-- param not in the query string</span>
166+<a name="line-157"></a>
167+<a name="line-158"></a> <span class='hs-varid'>route</span> <span class='hs-layout'>(</span><span class='hs-conid'>Proxy</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>sublayout</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>subserver</span> <span class='hs-varid'>param</span><span class='hs-layout'>)</span> <span class='hs-varid'>request</span> <span class='hs-varid'>respond</span>
168+<a name="line-159"></a>
169+<a name="line-160"></a> <span class='hs-keyword'>where</span> <span class='hs-varid'>paramname</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>cs</span> <span class='hs-varop'>$</span> <span class='hs-varid'>symbolVal</span> <span class='hs-layout'>(</span><span class='hs-conid'>Proxy</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>sym</span><span class='hs-layout'>)</span>
170+<a name="line-161"></a> <span class='hs-varid'>examine</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>v</span> <span class='hs-varop'>==</span> <span class='hs-str'>"true"</span> <span class='hs-varop'>||</span> <span class='hs-varid'>v</span> <span class='hs-varop'>==</span> <span class='hs-str'>"1"</span> <span class='hs-varop'>||</span> <span class='hs-varid'>v</span> <span class='hs-varop'>==</span> <span class='hs-str'>""</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>True</span>
171+<a name="line-162"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>False</span>
172+</pre></body>
173+</html>
src/Servant-API-Raw.htmlnew file+43
@@ -0,0 +1,43 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3+<html>
4+<head>
5+<!-- Generated by HsColour, http://code.haskell.org/~malcolm/hscolour/ -->
6+<title>src/Servant/API/Raw.hs</title>
7+<link type='text/css' rel='stylesheet' href='hscolour.css' />
8+</head>
9+<body>
10+<pre><a name="line-1"></a><span class='hs-comment'>{-# LANGUAGE InstanceSigs #-}</span>
11+<a name="line-2"></a><span class='hs-comment'>{-# LANGUAGE OverloadedStrings #-}</span>
12+<a name="line-3"></a><span class='hs-comment'>{-# LANGUAGE TypeFamilies #-}</span>
13+<a name="line-4"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Raw</span> <span class='hs-keyword'>where</span>
14+<a name="line-5"></a>
15+<a name="line-6"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Proxy</span>
16+<a name="line-7"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Network</span><span class='hs-varop'>.</span><span class='hs-conid'>Wai</span>
17+<a name="line-8"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Server</span>
18+<a name="line-9"></a>
19+<a name="line-10"></a><a name="Raw"></a><span class='hs-comment'>-- | Endpoint for plugging in your own Wai 'Application's.</span>
20+<a name="line-11"></a><a name="Raw"></a><span class='hs-comment'>--</span>
21+<a name="line-12"></a><a name="Raw"></a><span class='hs-comment'>-- The given 'Application' will get the request as received by the server, potentially with</span>
22+<a name="line-13"></a><a name="Raw"></a><span class='hs-comment'>-- a modified (stripped) 'pathInfo' if the 'Application' is being routed with 'Servant.API.Sub.:&gt;'.</span>
23+<a name="line-14"></a><a name="Raw"></a><span class='hs-comment'>--</span>
24+<a name="line-15"></a><a name="Raw"></a><span class='hs-comment'>-- In addition to just letting you plug in your existing WAI 'Application's,</span>
25+<a name="line-16"></a><a name="Raw"></a><span class='hs-comment'>-- this can also be used with 'Servant.Utils.StaticFiles.serveDirectory' to serve</span>
26+<a name="line-17"></a><a name="Raw"></a><span class='hs-comment'>-- static files stored in a particular directory on your filesystem, or to serve</span>
27+<a name="line-18"></a><a name="Raw"></a><span class='hs-comment'>-- your API's documentation with 'Servant.Utils.StaticFiles.serveDocumentation'.</span>
28+<a name="line-19"></a><a name="Raw"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>Raw</span>
29+<a name="line-20"></a>
30+<a name="line-21"></a><a name="instance%20HasServer%20Raw"></a><span class='hs-comment'>-- | Just pass the request to the underlying application and serve its response.</span>
31+<a name="line-22"></a><a name="instance%20HasServer%20Raw"></a><span class='hs-comment'>--</span>
32+<a name="line-23"></a><a name="instance%20HasServer%20Raw"></a><span class='hs-comment'>-- Example:</span>
33+<a name="line-24"></a><a name="instance%20HasServer%20Raw"></a><span class='hs-comment'>--</span>
34+<a name="line-25"></a><a name="instance%20HasServer%20Raw"></a><span class='hs-comment'>-- &gt; type MyApi = "images" :&gt; Raw</span>
35+<a name="line-26"></a><a name="instance%20HasServer%20Raw"></a><span class='hs-comment'>-- &gt;</span>
36+<a name="line-27"></a><a name="instance%20HasServer%20Raw"></a><span class='hs-comment'>-- &gt; server :: Server MyApi</span>
37+<a name="line-28"></a><a name="instance%20HasServer%20Raw"></a><span class='hs-comment'>-- &gt; server = serveDirectory "/var/www/images"</span>
38+<a name="line-29"></a><a name="instance%20HasServer%20Raw"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>HasServer</span> <span class='hs-conid'>Raw</span> <span class='hs-keyword'>where</span>
39+<a name="line-30"></a> <span class='hs-keyword'>type</span> <span class='hs-conid'>Server</span> <span class='hs-conid'>Raw</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Application</span>
40+<a name="line-31"></a> <span class='hs-varid'>route</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>rawApplication</span> <span class='hs-varid'>request</span> <span class='hs-varid'>respond</span> <span class='hs-keyglyph'>=</span>
41+<a name="line-32"></a> <span class='hs-varid'>rawApplication</span> <span class='hs-varid'>request</span> <span class='hs-layout'>(</span><span class='hs-varid'>respond</span> <span class='hs-varop'>.</span> <span class='hs-varid'>succeedWith</span><span class='hs-layout'>)</span>
42+</pre></body>
43+</html>
src/Servant-API-ReqBody.htmlnew file+60
@@ -0,0 +1,60 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3+<html>
4+<head>
5+<!-- Generated by HsColour, http://code.haskell.org/~malcolm/hscolour/ -->
6+<title>src/Servant/API/ReqBody.hs</title>
7+<link type='text/css' rel='stylesheet' href='hscolour.css' />
8+</head>
9+<body>
10+<pre><a name="line-1"></a><span class='hs-comment'>{-# LANGUAGE PolyKinds #-}</span>
11+<a name="line-2"></a><span class='hs-comment'>{-# LANGUAGE TypeFamilies #-}</span>
12+<a name="line-3"></a><span class='hs-comment'>{-# LANGUAGE TypeOperators #-}</span>
13+<a name="line-4"></a><span class='hs-comment'>{-# LANGUAGE FlexibleInstances #-}</span>
14+<a name="line-5"></a><span class='hs-comment'>{-# LANGUAGE ScopedTypeVariables #-}</span>
15+<a name="line-6"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>ReqBody</span> <span class='hs-keyword'>where</span>
16+<a name="line-7"></a>
17+<a name="line-8"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Applicative</span>
18+<a name="line-9"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Aeson</span>
19+<a name="line-10"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Proxy</span>
20+<a name="line-11"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Network</span><span class='hs-varop'>.</span><span class='hs-conid'>Wai</span>
21+<a name="line-12"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Sub</span>
22+<a name="line-13"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Server</span>
23+<a name="line-14"></a>
24+<a name="line-15"></a><a name="HasServer"></a><span class='hs-comment'>-- | Extract the request body as a value of type @a@.</span>
25+<a name="line-16"></a><a name="HasServer"></a><span class='hs-comment'>--</span>
26+<a name="line-17"></a><a name="HasServer"></a><span class='hs-comment'>-- Example:</span>
27+<a name="line-18"></a><a name="HasServer"></a><span class='hs-comment'>--</span>
28+<a name="line-19"></a><a name="HasServer"></a><span class='hs-comment'>-- &gt; -- POST /books</span>
29+<a name="line-20"></a><a name="HasServer"></a><span class='hs-comment'>-- &gt; type MyApi = "books" :&gt; ReqBody Book :&gt; Post Book</span>
30+<a name="line-21"></a><a name="HasServer"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>ReqBody</span> <span class='hs-varid'>a</span>
31+<a name="line-22"></a>
32+<a name="line-23"></a><a name="instance%20HasServer%20(ReqBody%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- | If you use 'ReqBody' in one of the endpoints for your API,</span>
33+<a name="line-24"></a><a name="instance%20HasServer%20(ReqBody%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- this automatically requires your server-side handler to be a function</span>
34+<a name="line-25"></a><a name="instance%20HasServer%20(ReqBody%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- that takes an argument of the type specified by 'ReqBody'.</span>
35+<a name="line-26"></a><a name="instance%20HasServer%20(ReqBody%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- This lets servant worry about extracting it from the request and turning</span>
36+<a name="line-27"></a><a name="instance%20HasServer%20(ReqBody%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- it into a value of the type you specify.</span>
37+<a name="line-28"></a><a name="instance%20HasServer%20(ReqBody%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>--</span>
38+<a name="line-29"></a><a name="instance%20HasServer%20(ReqBody%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- All it asks is for a 'FromJSON' instance.</span>
39+<a name="line-30"></a><a name="instance%20HasServer%20(ReqBody%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>--</span>
40+<a name="line-31"></a><a name="instance%20HasServer%20(ReqBody%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- Example:</span>
41+<a name="line-32"></a><a name="instance%20HasServer%20(ReqBody%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>--</span>
42+<a name="line-33"></a><a name="instance%20HasServer%20(ReqBody%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; type MyApi = "books" :&gt; ReqBody Book :&gt; Post Book</span>
43+<a name="line-34"></a><a name="instance%20HasServer%20(ReqBody%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt;</span>
44+<a name="line-35"></a><a name="instance%20HasServer%20(ReqBody%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; server :: Server MyApi</span>
45+<a name="line-36"></a><a name="instance%20HasServer%20(ReqBody%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; server = postBook</span>
46+<a name="line-37"></a><a name="instance%20HasServer%20(ReqBody%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; where postBook :: Book -&gt; EitherT (Int, String) IO Book</span>
47+<a name="line-38"></a><a name="instance%20HasServer%20(ReqBody%20a%20:%3e%20sublayout)"></a><span class='hs-comment'>-- &gt; postBook book = ...insert into your db...</span>
48+<a name="line-39"></a><a name="instance%20HasServer%20(ReqBody%20a%20:%3e%20sublayout)"></a><span class='hs-keyword'>instance</span> <span class='hs-layout'>(</span><span class='hs-conid'>FromJSON</span> <span class='hs-varid'>a</span><span class='hs-layout'>,</span> <span class='hs-conid'>HasServer</span> <span class='hs-varid'>sublayout</span><span class='hs-layout'>)</span>
49+<a name="line-40"></a> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>HasServer</span> <span class='hs-layout'>(</span><span class='hs-conid'>ReqBody</span> <span class='hs-varid'>a</span> <span class='hs-conop'>:&gt;</span> <span class='hs-varid'>sublayout</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
50+<a name="line-41"></a>
51+<a name="line-42"></a> <span class='hs-keyword'>type</span> <span class='hs-conid'>Server</span> <span class='hs-layout'>(</span><span class='hs-conid'>ReqBody</span> <span class='hs-varid'>a</span> <span class='hs-conop'>:&gt;</span> <span class='hs-varid'>sublayout</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span>
52+<a name="line-43"></a> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Server</span> <span class='hs-varid'>sublayout</span>
53+<a name="line-44"></a>
54+<a name="line-45"></a> <span class='hs-varid'>route</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>subserver</span> <span class='hs-varid'>request</span> <span class='hs-varid'>respond</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
55+<a name="line-46"></a> <span class='hs-varid'>mrqbody</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>decode'</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>lazyRequestBody</span> <span class='hs-varid'>request</span>
56+<a name="line-47"></a> <span class='hs-keyword'>case</span> <span class='hs-varid'>mrqbody</span> <span class='hs-keyword'>of</span>
57+<a name="line-48"></a> <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>respond</span> <span class='hs-varop'>$</span> <span class='hs-varid'>failWith</span> <span class='hs-conid'>InvalidBody</span>
58+<a name="line-49"></a> <span class='hs-conid'>Just</span> <span class='hs-varid'>v</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>route</span> <span class='hs-layout'>(</span><span class='hs-conid'>Proxy</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>sublayout</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>subserver</span> <span class='hs-varid'>v</span><span class='hs-layout'>)</span> <span class='hs-varid'>request</span> <span class='hs-varid'>respond</span>
59+</pre></body>
60+</html>
src/Servant-API-Sub.htmlnew file+47
@@ -0,0 +1,47 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3+<html>
4+<head>
5+<!-- Generated by HsColour, http://code.haskell.org/~malcolm/hscolour/ -->
6+<title>src/Servant/API/Sub.hs</title>
7+<link type='text/css' rel='stylesheet' href='hscolour.css' />
8+</head>
9+<body>
10+<pre><a name="line-1"></a><span class='hs-comment'>{-# LANGUAGE PolyKinds #-}</span>
11+<a name="line-2"></a><span class='hs-comment'>{-# LANGUAGE TypeFamilies #-}</span>
12+<a name="line-3"></a><span class='hs-comment'>{-# LANGUAGE TypeOperators #-}</span>
13+<a name="line-4"></a><span class='hs-comment'>{-# LANGUAGE ScopedTypeVariables #-}</span>
14+<a name="line-5"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Sub</span> <span class='hs-keyword'>where</span>
15+<a name="line-6"></a>
16+<a name="line-7"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Proxy</span>
17+<a name="line-8"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>String</span><span class='hs-varop'>.</span><span class='hs-conid'>Conversions</span>
18+<a name="line-9"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>TypeLits</span>
19+<a name="line-10"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Network</span><span class='hs-varop'>.</span><span class='hs-conid'>Wai</span>
20+<a name="line-11"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Server</span>
21+<a name="line-12"></a>
22+<a name="line-13"></a><span class='hs-comment'>-- | The contained API (second argument) can be found under @("/" ++ path)@</span>
23+<a name="line-14"></a><span class='hs-comment'>-- (path being the first argument).</span>
24+<a name="line-15"></a><span class='hs-comment'>--</span>
25+<a name="line-16"></a><span class='hs-comment'>-- Example:</span>
26+<a name="line-17"></a><span class='hs-comment'>--</span>
27+<a name="line-18"></a><span class='hs-comment'>-- &gt; -- GET /hello/world</span>
28+<a name="line-19"></a><span class='hs-comment'>-- &gt; -- returning a JSON encoded World value</span>
29+<a name="line-20"></a><span class='hs-comment'>-- &gt; type MyApi = "hello" :&gt; "world" :&gt; Get World</span>
30+<a name="line-21"></a><span class='hs-keyword'>data</span> <span class='hs-layout'>(</span><span class='hs-varid'>path</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>k</span><span class='hs-layout'>)</span> <span class='hs-conop'>:&gt;</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>path</span> <span class='hs-conop'>:&gt;</span> <span class='hs-varid'>a</span>
31+<a name="line-22"></a><span class='hs-keyword'>infixr</span> <span class='hs-num'>9</span> <span class='hs-conop'>:&gt;</span>
32+<a name="line-23"></a>
33+<a name="line-24"></a><a name="instance%20HasServer%20(path%20:%3e%20sublayout)"></a><span class='hs-comment'>-- | Make sure the incoming request starts with @"/path"@, strip it and</span>
34+<a name="line-25"></a><a name="instance%20HasServer%20(path%20:%3e%20sublayout)"></a><span class='hs-comment'>-- pass the rest of the request path to @sublayout@.</span>
35+<a name="line-26"></a><a name="instance%20HasServer%20(path%20:%3e%20sublayout)"></a><span class='hs-keyword'>instance</span> <span class='hs-layout'>(</span><span class='hs-conid'>KnownSymbol</span> <span class='hs-varid'>path</span><span class='hs-layout'>,</span> <span class='hs-conid'>HasServer</span> <span class='hs-varid'>sublayout</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>HasServer</span> <span class='hs-layout'>(</span><span class='hs-varid'>path</span> <span class='hs-conop'>:&gt;</span> <span class='hs-varid'>sublayout</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
36+<a name="line-27"></a> <span class='hs-keyword'>type</span> <span class='hs-conid'>Server</span> <span class='hs-layout'>(</span><span class='hs-varid'>path</span> <span class='hs-conop'>:&gt;</span> <span class='hs-varid'>sublayout</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Server</span> <span class='hs-varid'>sublayout</span>
37+<a name="line-28"></a> <span class='hs-varid'>route</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>subserver</span> <span class='hs-varid'>request</span> <span class='hs-varid'>respond</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>pathInfo</span> <span class='hs-varid'>request</span> <span class='hs-keyword'>of</span>
38+<a name="line-29"></a> <span class='hs-layout'>(</span><span class='hs-varid'>first</span> <span class='hs-conop'>:</span> <span class='hs-varid'>rest</span><span class='hs-layout'>)</span>
39+<a name="line-30"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>first</span> <span class='hs-varop'>==</span> <span class='hs-varid'>cs</span> <span class='hs-layout'>(</span><span class='hs-varid'>symbolVal</span> <span class='hs-varid'>proxyPath</span><span class='hs-layout'>)</span>
40+<a name="line-31"></a> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>route</span> <span class='hs-layout'>(</span><span class='hs-conid'>Proxy</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>sublayout</span><span class='hs-layout'>)</span> <span class='hs-varid'>subserver</span> <span class='hs-varid'>request</span><span class='hs-layout'>{</span>
41+<a name="line-32"></a> <span class='hs-varid'>pathInfo</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>rest</span>
42+<a name="line-33"></a> <span class='hs-layout'>}</span> <span class='hs-varid'>respond</span>
43+<a name="line-34"></a> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>respond</span> <span class='hs-varop'>$</span> <span class='hs-varid'>failWith</span> <span class='hs-conid'>NotFound</span>
44+<a name="line-35"></a>
45+<a name="line-36"></a> <span class='hs-keyword'>where</span> <span class='hs-varid'>proxyPath</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Proxy</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>path</span>
46+</pre></body>
47+</html>
src/Servant-API.htmlnew file+62
@@ -0,0 +1,62 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3+<html>
4+<head>
5+<!-- Generated by HsColour, http://code.haskell.org/~malcolm/hscolour/ -->
6+<title>src/Servant/API.hs</title>
7+<link type='text/css' rel='stylesheet' href='hscolour.css' />
8+</head>
9+<body>
10+<pre><a name="line-1"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span> <span class='hs-layout'>(</span>
11+<a name="line-2"></a>
12+<a name="line-3"></a> <span class='hs-comment'>-- * Combinators</span>
13+<a name="line-4"></a> <span class='hs-comment'>-- | Type-level combinator for expressing subrouting: @':&gt;'@</span>
14+<a name="line-5"></a> <span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Sub</span><span class='hs-layout'>,</span>
15+<a name="line-6"></a> <span class='hs-comment'>-- | Type-level combinator for alternative endpoints: @':&lt;|&gt;'@</span>
16+<a name="line-7"></a> <span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Alternative</span><span class='hs-layout'>,</span>
17+<a name="line-8"></a>
18+<a name="line-9"></a> <span class='hs-comment'>-- * Accessing information from the request</span>
19+<a name="line-10"></a> <span class='hs-comment'>-- | Capturing parts of the url path as parsed values: @'Capture'@</span>
20+<a name="line-11"></a> <span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Capture</span><span class='hs-layout'>,</span>
21+<a name="line-12"></a> <span class='hs-comment'>-- | Retrieving parameters from the query string of the 'URI': @'QueryParam'@</span>
22+<a name="line-13"></a> <span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>QueryParam</span><span class='hs-layout'>,</span>
23+<a name="line-14"></a> <span class='hs-comment'>-- | Accessing the request body as a JSON-encoded type: @'ReqBody'@</span>
24+<a name="line-15"></a> <span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>ReqBody</span><span class='hs-layout'>,</span>
25+<a name="line-16"></a>
26+<a name="line-17"></a> <span class='hs-comment'>-- * Actual endpoints, distinguished by HTTP method</span>
27+<a name="line-18"></a> <span class='hs-comment'>-- | GET requests</span>
28+<a name="line-19"></a> <span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Get</span><span class='hs-layout'>,</span>
29+<a name="line-20"></a> <span class='hs-comment'>-- | POST requests</span>
30+<a name="line-21"></a> <span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Post</span><span class='hs-layout'>,</span>
31+<a name="line-22"></a> <span class='hs-comment'>-- | DELETE requests</span>
32+<a name="line-23"></a> <span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Delete</span><span class='hs-layout'>,</span>
33+<a name="line-24"></a> <span class='hs-comment'>-- | PUT requests</span>
34+<a name="line-25"></a> <span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Put</span><span class='hs-layout'>,</span>
35+<a name="line-26"></a>
36+<a name="line-27"></a> <span class='hs-comment'>-- * Untyped endpoints</span>
37+<a name="line-28"></a> <span class='hs-comment'>-- | Plugging in a wai 'Network.Wai.Application', serving directories</span>
38+<a name="line-29"></a> <span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Raw</span><span class='hs-layout'>,</span>
39+<a name="line-30"></a> <span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Utils</span><span class='hs-varop'>.</span><span class='hs-conid'>StaticFiles</span><span class='hs-layout'>,</span>
40+<a name="line-31"></a>
41+<a name="line-32"></a> <span class='hs-comment'>-- * Utilities</span>
42+<a name="line-33"></a> <span class='hs-comment'>-- | QuasiQuotes for endpoints</span>
43+<a name="line-34"></a> <span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>QQ</span><span class='hs-layout'>,</span>
44+<a name="line-35"></a> <span class='hs-comment'>-- | Type-safe internal URLs</span>
45+<a name="line-36"></a> <span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Utils</span><span class='hs-varop'>.</span><span class='hs-conid'>Links</span><span class='hs-layout'>,</span>
46+<a name="line-37"></a> <span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
47+<a name="line-38"></a>
48+<a name="line-39"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Alternative</span>
49+<a name="line-40"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Capture</span>
50+<a name="line-41"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Delete</span>
51+<a name="line-42"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Get</span>
52+<a name="line-43"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Post</span>
53+<a name="line-44"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Put</span>
54+<a name="line-45"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>QueryParam</span>
55+<a name="line-46"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Raw</span>
56+<a name="line-47"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>ReqBody</span>
57+<a name="line-48"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Sub</span>
58+<a name="line-49"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>QQ</span> <span class='hs-layout'>(</span><span class='hs-varid'>sitemap</span><span class='hs-layout'>)</span>
59+<a name="line-50"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Utils</span><span class='hs-varop'>.</span><span class='hs-conid'>Links</span> <span class='hs-layout'>(</span><span class='hs-varid'>mkLink</span><span class='hs-layout'>)</span>
60+<a name="line-51"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Utils</span><span class='hs-varop'>.</span><span class='hs-conid'>StaticFiles</span>
61+</pre></body>
62+</html>
src/Servant-Common-Text.htmlnew file+141
@@ -0,0 +1,141 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3+<html>
4+<head>
5+<!-- Generated by HsColour, http://code.haskell.org/~malcolm/hscolour/ -->
6+<title>src/Servant/Common/Text.hs</title>
7+<link type='text/css' rel='stylesheet' href='hscolour.css' />
8+</head>
9+<body>
10+<pre><a name="line-1"></a><span class='hs-comment'>{-# LANGUAGE FlexibleInstances #-}</span>
11+<a name="line-2"></a><span class='hs-comment'>{-# LANGUAGE OverloadedStrings #-}</span>
12+<a name="line-3"></a><span class='hs-comment'>{-# LANGUAGE TypeSynonymInstances #-}</span>
13+<a name="line-4"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Common</span><span class='hs-varop'>.</span><span class='hs-conid'>Text</span>
14+<a name="line-5"></a> <span class='hs-layout'>(</span> <span class='hs-conid'>FromText</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span>
15+<a name="line-6"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>ToText</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span>
16+<a name="line-7"></a> <span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
17+<a name="line-8"></a>
18+<a name="line-9"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>String</span><span class='hs-varop'>.</span><span class='hs-conid'>Conversions</span>
19+<a name="line-10"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Int</span>
20+<a name="line-11"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Text</span>
21+<a name="line-12"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Text</span><span class='hs-varop'>.</span><span class='hs-conid'>Read</span>
22+<a name="line-13"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Word</span>
23+<a name="line-14"></a>
24+<a name="line-15"></a><a name="FromText"></a><span class='hs-comment'>-- | For getting values from url captures and query string parameters</span>
25+<a name="line-16"></a><a name="FromText"></a><span class='hs-keyword'>class</span> <span class='hs-conid'>FromText</span> <span class='hs-varid'>a</span> <span class='hs-keyword'>where</span>
26+<a name="line-17"></a> <span class='hs-varid'>fromText</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Text</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Maybe</span> <span class='hs-varid'>a</span>
27+<a name="line-18"></a>
28+<a name="line-19"></a><a name="ToText"></a><span class='hs-comment'>-- | For putting values in paths and query string parameters</span>
29+<a name="line-20"></a><a name="ToText"></a><span class='hs-keyword'>class</span> <span class='hs-conid'>ToText</span> <span class='hs-varid'>a</span> <span class='hs-keyword'>where</span>
30+<a name="line-21"></a> <span class='hs-varid'>toText</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Text</span>
31+<a name="line-22"></a>
32+<a name="line-23"></a><a name="instance%20FromText%20Text"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>FromText</span> <span class='hs-conid'>Text</span> <span class='hs-keyword'>where</span>
33+<a name="line-24"></a> <span class='hs-varid'>fromText</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Just</span>
34+<a name="line-25"></a>
35+<a name="line-26"></a><a name="instance%20ToText%20Text"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>ToText</span> <span class='hs-conid'>Text</span> <span class='hs-keyword'>where</span>
36+<a name="line-27"></a> <span class='hs-varid'>toText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>id</span>
37+<a name="line-28"></a>
38+<a name="line-29"></a><a name="instance%20FromText%20String"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>FromText</span> <span class='hs-conid'>String</span> <span class='hs-keyword'>where</span>
39+<a name="line-30"></a> <span class='hs-varid'>fromText</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Just</span> <span class='hs-varop'>.</span> <span class='hs-varid'>cs</span>
40+<a name="line-31"></a>
41+<a name="line-32"></a><a name="instance%20ToText%20String"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>ToText</span> <span class='hs-conid'>String</span> <span class='hs-keyword'>where</span>
42+<a name="line-33"></a> <span class='hs-varid'>toText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>cs</span>
43+<a name="line-34"></a>
44+<a name="line-35"></a><a name="instance%20FromText%20Bool"></a><span class='hs-comment'>-- |</span>
45+<a name="line-36"></a><a name="instance%20FromText%20Bool"></a><span class='hs-comment'>-- &gt; fromText "true" = Just True</span>
46+<a name="line-37"></a><a name="instance%20FromText%20Bool"></a><span class='hs-comment'>-- &gt; fromText "false" = Just False</span>
47+<a name="line-38"></a><a name="instance%20FromText%20Bool"></a><span class='hs-comment'>-- &gt; fromText _ = Nothing</span>
48+<a name="line-39"></a><a name="instance%20FromText%20Bool"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>FromText</span> <span class='hs-conid'>Bool</span> <span class='hs-keyword'>where</span>
49+<a name="line-40"></a> <span class='hs-varid'>fromText</span> <span class='hs-str'>"true"</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Just</span> <span class='hs-conid'>True</span>
50+<a name="line-41"></a> <span class='hs-varid'>fromText</span> <span class='hs-str'>"false"</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Just</span> <span class='hs-conid'>False</span>
51+<a name="line-42"></a> <span class='hs-varid'>fromText</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Nothing</span>
52+<a name="line-43"></a>
53+<a name="line-44"></a><a name="instance%20ToText%20Bool"></a><span class='hs-comment'>-- |</span>
54+<a name="line-45"></a><a name="instance%20ToText%20Bool"></a><span class='hs-comment'>-- &gt; toText True = "true"</span>
55+<a name="line-46"></a><a name="instance%20ToText%20Bool"></a><span class='hs-comment'>-- &gt; toText False = "false"</span>
56+<a name="line-47"></a><a name="instance%20ToText%20Bool"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>ToText</span> <span class='hs-conid'>Bool</span> <span class='hs-keyword'>where</span>
57+<a name="line-48"></a> <span class='hs-varid'>toText</span> <span class='hs-conid'>True</span> <span class='hs-keyglyph'>=</span> <span class='hs-str'>"true"</span>
58+<a name="line-49"></a> <span class='hs-varid'>toText</span> <span class='hs-conid'>False</span> <span class='hs-keyglyph'>=</span> <span class='hs-str'>"false"</span>
59+<a name="line-50"></a>
60+<a name="line-51"></a><a name="instance%20FromText%20Int"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>FromText</span> <span class='hs-conid'>Int</span> <span class='hs-keyword'>where</span>
61+<a name="line-52"></a> <span class='hs-varid'>fromText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>runReader</span> <span class='hs-layout'>(</span><span class='hs-varid'>signed</span> <span class='hs-varid'>decimal</span><span class='hs-layout'>)</span>
62+<a name="line-53"></a>
63+<a name="line-54"></a><a name="instance%20ToText%20Int"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>ToText</span> <span class='hs-conid'>Int</span> <span class='hs-keyword'>where</span>
64+<a name="line-55"></a> <span class='hs-varid'>toText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>cs</span> <span class='hs-varop'>.</span> <span class='hs-varid'>show</span>
65+<a name="line-56"></a>
66+<a name="line-57"></a><a name="instance%20FromText%20Int8"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>FromText</span> <span class='hs-conid'>Int8</span> <span class='hs-keyword'>where</span>
67+<a name="line-58"></a> <span class='hs-varid'>fromText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>runReader</span> <span class='hs-layout'>(</span><span class='hs-varid'>signed</span> <span class='hs-varid'>decimal</span><span class='hs-layout'>)</span>
68+<a name="line-59"></a>
69+<a name="line-60"></a><a name="instance%20ToText%20Int8"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>ToText</span> <span class='hs-conid'>Int8</span> <span class='hs-keyword'>where</span>
70+<a name="line-61"></a> <span class='hs-varid'>toText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>cs</span> <span class='hs-varop'>.</span> <span class='hs-varid'>show</span>
71+<a name="line-62"></a>
72+<a name="line-63"></a><a name="instance%20FromText%20Int16"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>FromText</span> <span class='hs-conid'>Int16</span> <span class='hs-keyword'>where</span>
73+<a name="line-64"></a> <span class='hs-varid'>fromText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>runReader</span> <span class='hs-layout'>(</span><span class='hs-varid'>signed</span> <span class='hs-varid'>decimal</span><span class='hs-layout'>)</span>
74+<a name="line-65"></a>
75+<a name="line-66"></a><a name="instance%20ToText%20Int16"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>ToText</span> <span class='hs-conid'>Int16</span> <span class='hs-keyword'>where</span>
76+<a name="line-67"></a> <span class='hs-varid'>toText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>cs</span> <span class='hs-varop'>.</span> <span class='hs-varid'>show</span>
77+<a name="line-68"></a>
78+<a name="line-69"></a><a name="instance%20FromText%20Int32"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>FromText</span> <span class='hs-conid'>Int32</span> <span class='hs-keyword'>where</span>
79+<a name="line-70"></a> <span class='hs-varid'>fromText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>runReader</span> <span class='hs-layout'>(</span><span class='hs-varid'>signed</span> <span class='hs-varid'>decimal</span><span class='hs-layout'>)</span>
80+<a name="line-71"></a>
81+<a name="line-72"></a><a name="instance%20ToText%20Int32"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>ToText</span> <span class='hs-conid'>Int32</span> <span class='hs-keyword'>where</span>
82+<a name="line-73"></a> <span class='hs-varid'>toText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>cs</span> <span class='hs-varop'>.</span> <span class='hs-varid'>show</span>
83+<a name="line-74"></a>
84+<a name="line-75"></a><a name="instance%20FromText%20Int64"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>FromText</span> <span class='hs-conid'>Int64</span> <span class='hs-keyword'>where</span>
85+<a name="line-76"></a> <span class='hs-varid'>fromText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>runReader</span> <span class='hs-layout'>(</span><span class='hs-varid'>signed</span> <span class='hs-varid'>decimal</span><span class='hs-layout'>)</span>
86+<a name="line-77"></a>
87+<a name="line-78"></a><a name="instance%20ToText%20Int64"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>ToText</span> <span class='hs-conid'>Int64</span> <span class='hs-keyword'>where</span>
88+<a name="line-79"></a> <span class='hs-varid'>toText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>cs</span> <span class='hs-varop'>.</span> <span class='hs-varid'>show</span>
89+<a name="line-80"></a>
90+<a name="line-81"></a><a name="instance%20FromText%20Word"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>FromText</span> <span class='hs-conid'>Word</span> <span class='hs-keyword'>where</span>
91+<a name="line-82"></a> <span class='hs-varid'>fromText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>runReader</span> <span class='hs-varid'>decimal</span>
92+<a name="line-83"></a>
93+<a name="line-84"></a><a name="instance%20ToText%20Word"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>ToText</span> <span class='hs-conid'>Word</span> <span class='hs-keyword'>where</span>
94+<a name="line-85"></a> <span class='hs-varid'>toText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>cs</span> <span class='hs-varop'>.</span> <span class='hs-varid'>show</span>
95+<a name="line-86"></a>
96+<a name="line-87"></a><a name="instance%20FromText%20Word8"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>FromText</span> <span class='hs-conid'>Word8</span> <span class='hs-keyword'>where</span>
97+<a name="line-88"></a> <span class='hs-varid'>fromText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>runReader</span> <span class='hs-varid'>decimal</span>
98+<a name="line-89"></a>
99+<a name="line-90"></a><a name="instance%20ToText%20Word8"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>ToText</span> <span class='hs-conid'>Word8</span> <span class='hs-keyword'>where</span>
100+<a name="line-91"></a> <span class='hs-varid'>toText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>cs</span> <span class='hs-varop'>.</span> <span class='hs-varid'>show</span>
101+<a name="line-92"></a>
102+<a name="line-93"></a><a name="instance%20FromText%20Word16"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>FromText</span> <span class='hs-conid'>Word16</span> <span class='hs-keyword'>where</span>
103+<a name="line-94"></a> <span class='hs-varid'>fromText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>runReader</span> <span class='hs-varid'>decimal</span>
104+<a name="line-95"></a>
105+<a name="line-96"></a><a name="instance%20ToText%20Word16"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>ToText</span> <span class='hs-conid'>Word16</span> <span class='hs-keyword'>where</span>
106+<a name="line-97"></a> <span class='hs-varid'>toText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>cs</span> <span class='hs-varop'>.</span> <span class='hs-varid'>show</span>
107+<a name="line-98"></a>
108+<a name="line-99"></a><a name="instance%20FromText%20Word32"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>FromText</span> <span class='hs-conid'>Word32</span> <span class='hs-keyword'>where</span>
109+<a name="line-100"></a> <span class='hs-varid'>fromText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>runReader</span> <span class='hs-varid'>decimal</span>
110+<a name="line-101"></a>
111+<a name="line-102"></a><a name="instance%20ToText%20Word32"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>ToText</span> <span class='hs-conid'>Word32</span> <span class='hs-keyword'>where</span>
112+<a name="line-103"></a> <span class='hs-varid'>toText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>cs</span> <span class='hs-varop'>.</span> <span class='hs-varid'>show</span>
113+<a name="line-104"></a>
114+<a name="line-105"></a><a name="instance%20FromText%20Word64"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>FromText</span> <span class='hs-conid'>Word64</span> <span class='hs-keyword'>where</span>
115+<a name="line-106"></a> <span class='hs-varid'>fromText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>runReader</span> <span class='hs-varid'>decimal</span>
116+<a name="line-107"></a>
117+<a name="line-108"></a><a name="instance%20ToText%20Word64"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>ToText</span> <span class='hs-conid'>Word64</span> <span class='hs-keyword'>where</span>
118+<a name="line-109"></a> <span class='hs-varid'>toText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>cs</span> <span class='hs-varop'>.</span> <span class='hs-varid'>show</span>
119+<a name="line-110"></a>
120+<a name="line-111"></a><a name="instance%20FromText%20Integer"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>FromText</span> <span class='hs-conid'>Integer</span> <span class='hs-keyword'>where</span>
121+<a name="line-112"></a> <span class='hs-varid'>fromText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>runReader</span> <span class='hs-varid'>decimal</span>
122+<a name="line-113"></a>
123+<a name="line-114"></a><a name="instance%20ToText%20Integer"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>ToText</span> <span class='hs-conid'>Integer</span> <span class='hs-keyword'>where</span>
124+<a name="line-115"></a> <span class='hs-varid'>toText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>cs</span> <span class='hs-varop'>.</span> <span class='hs-varid'>show</span>
125+<a name="line-116"></a>
126+<a name="line-117"></a><a name="instance%20FromText%20Double"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>FromText</span> <span class='hs-conid'>Double</span> <span class='hs-keyword'>where</span>
127+<a name="line-118"></a> <span class='hs-varid'>fromText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>runReader</span> <span class='hs-varid'>rational</span>
128+<a name="line-119"></a>
129+<a name="line-120"></a><a name="instance%20ToText%20Double"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>ToText</span> <span class='hs-conid'>Double</span> <span class='hs-keyword'>where</span>
130+<a name="line-121"></a> <span class='hs-varid'>toText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>cs</span> <span class='hs-varop'>.</span> <span class='hs-varid'>show</span>
131+<a name="line-122"></a>
132+<a name="line-123"></a><a name="instance%20FromText%20Float"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>FromText</span> <span class='hs-conid'>Float</span> <span class='hs-keyword'>where</span>
133+<a name="line-124"></a> <span class='hs-varid'>fromText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>runReader</span> <span class='hs-varid'>rational</span>
134+<a name="line-125"></a>
135+<a name="line-126"></a><a name="instance%20ToText%20Float"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>ToText</span> <span class='hs-conid'>Float</span> <span class='hs-keyword'>where</span>
136+<a name="line-127"></a> <span class='hs-varid'>toText</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>cs</span> <span class='hs-varop'>.</span> <span class='hs-varid'>show</span>
137+<a name="line-128"></a>
138+<a name="line-129"></a><a name="runReader"></a><span class='hs-definition'>runReader</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Reader</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Text</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Maybe</span> <span class='hs-varid'>a</span>
139+<a name="line-130"></a><span class='hs-definition'>runReader</span> <span class='hs-varid'>reader</span> <span class='hs-varid'>t</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>either</span> <span class='hs-layout'>(</span><span class='hs-varid'>const</span> <span class='hs-conid'>Nothing</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>Just</span> <span class='hs-varop'>.</span> <span class='hs-varid'>fst</span><span class='hs-layout'>)</span> <span class='hs-varop'>$</span> <span class='hs-varid'>reader</span> <span class='hs-varid'>t</span>
140+</pre></body>
141+</html>
src/Servant-QQ.htmlnew file+209
@@ -0,0 +1,209 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3+<html>
4+<head>
5+<!-- Generated by HsColour, http://code.haskell.org/~malcolm/hscolour/ -->
6+<title>src/Servant/QQ.hs</title>
7+<link type='text/css' rel='stylesheet' href='hscolour.css' />
8+</head>
9+<body>
10+<pre><a name="line-1"></a><span class='hs-comment'>{-# LANGUAGE MultiParamTypeClasses #-}</span>
11+<a name="line-2"></a><span class='hs-comment'>{-# LANGUAGE FunctionalDependencies #-}</span>
12+<a name="line-3"></a><span class='hs-comment'>{-# LANGUAGE DataKinds #-}</span>
13+<a name="line-4"></a><span class='hs-comment'>{-# LANGUAGE FlexibleInstances #-}</span>
14+<a name="line-5"></a><span class='hs-comment'>{-# LANGUAGE ScopedTypeVariables #-}</span>
15+<a name="line-6"></a><span class='hs-comment'>{-# LANGUAGE TemplateHaskell #-}</span>
16+<a name="line-7"></a><span class='hs-comment'>{-# OPTIONS_GHC -fno-warn-unused-do-bind #-}</span>
17+<a name="line-8"></a><span class='hs-comment'>-- | QuasiQuoting utilities for API types.</span>
18+<a name="line-9"></a><span class='hs-comment'>--</span>
19+<a name="line-10"></a><span class='hs-comment'>-- 'sitemap' allows you to write your type in a very natural way:</span>
20+<a name="line-11"></a><span class='hs-comment'>--</span>
21+<a name="line-12"></a><span class='hs-comment'>-- @</span>
22+<a name="line-13"></a><span class='hs-comment'>-- [sitemap|</span>
23+<a name="line-14"></a><span class='hs-comment'>-- PUT hello String -&gt; ()</span>
24+<a name="line-15"></a><span class='hs-comment'>-- POST hello/p:Int String -&gt; ()</span>
25+<a name="line-16"></a><span class='hs-comment'>-- GET hello/?name:String Int</span>
26+<a name="line-17"></a><span class='hs-comment'>-- |]</span>
27+<a name="line-18"></a><span class='hs-comment'>-- @</span>
28+<a name="line-19"></a><span class='hs-comment'>--</span>
29+<a name="line-20"></a><span class='hs-comment'>-- Will generate:</span>
30+<a name="line-21"></a><span class='hs-comment'>--</span>
31+<a name="line-22"></a><span class='hs-comment'>-- @</span>
32+<a name="line-23"></a><span class='hs-comment'>-- "hello" :&gt; ReqBody String :&gt; Put ()</span>
33+<a name="line-24"></a><span class='hs-comment'>-- :\&lt;|&gt; "hello" :&gt; Capture "p" Int :&gt; ReqBody String :&gt; Post ()</span>
34+<a name="line-25"></a><span class='hs-comment'>-- :\&lt;|&gt; "hello" :&gt; QueryParam "name" String :&gt; Get Int</span>
35+<a name="line-26"></a><span class='hs-comment'>-- @</span>
36+<a name="line-27"></a><span class='hs-comment'>--</span>
37+<a name="line-28"></a><span class='hs-comment'>-- Note the @/@ before a @QueryParam@!</span>
38+<a name="line-29"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>QQ</span> <span class='hs-keyword'>where</span>
39+<a name="line-30"></a>
40+<a name="line-31"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Monad</span> <span class='hs-layout'>(</span><span class='hs-varid'>void</span><span class='hs-layout'>)</span>
41+<a name="line-32"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Applicative</span> <span class='hs-varid'>hiding</span> <span class='hs-layout'>(</span><span class='hs-varid'>many</span><span class='hs-layout'>,</span> <span class='hs-layout'>(</span><span class='hs-varop'>&lt;|&gt;</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span> <span class='hs-varid'>optional</span><span class='hs-layout'>)</span>
42+<a name="line-33"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Language</span><span class='hs-varop'>.</span><span class='hs-conid'>Haskell</span><span class='hs-varop'>.</span><span class='hs-conid'>TH</span><span class='hs-varop'>.</span><span class='hs-conid'>Quote</span>
43+<a name="line-34"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Language</span><span class='hs-varop'>.</span><span class='hs-conid'>Haskell</span><span class='hs-varop'>.</span><span class='hs-conid'>TH</span>
44+<a name="line-35"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Text</span><span class='hs-varop'>.</span><span class='hs-conid'>ParserCombinators</span><span class='hs-varop'>.</span><span class='hs-conid'>Parsec</span>
45+<a name="line-36"></a>
46+<a name="line-37"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Capture</span>
47+<a name="line-38"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Get</span>
48+<a name="line-39"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Post</span>
49+<a name="line-40"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Put</span>
50+<a name="line-41"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Delete</span>
51+<a name="line-42"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>QueryParam</span>
52+<a name="line-43"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>ReqBody</span>
53+<a name="line-44"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Sub</span>
54+<a name="line-45"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Alternative</span>
55+<a name="line-46"></a>
56+<a name="line-47"></a><a name="ExpSYM"></a><span class='hs-comment'>-- | Finally-tagless encoding for our DSL.</span>
57+<a name="line-48"></a><a name="ExpSYM"></a><span class='hs-comment'>-- Keeping 'repr'' and 'repr' distinct when writing functions with an</span>
58+<a name="line-49"></a><a name="ExpSYM"></a><span class='hs-comment'>-- @ExpSYM@ context ensures certain invariants (for instance, that there is</span>
59+<a name="line-50"></a><a name="ExpSYM"></a><span class='hs-comment'>-- only one of 'get', 'post', 'put', and 'delete' in a value), but</span>
60+<a name="line-51"></a><a name="ExpSYM"></a><span class='hs-comment'>-- sometimes requires a little more work.</span>
61+<a name="line-52"></a><a name="ExpSYM"></a><span class='hs-keyword'>class</span> <span class='hs-conid'>ExpSYM</span> <span class='hs-varid'>repr'</span> <span class='hs-varid'>repr</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>repr</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>repr'</span><span class='hs-layout'>,</span> <span class='hs-varid'>repr'</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>repr</span> <span class='hs-keyword'>where</span>
62+<a name="line-53"></a> <span class='hs-varid'>lit</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>repr'</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>repr</span>
63+<a name="line-54"></a> <span class='hs-varid'>capture</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>repr</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>repr</span>
64+<a name="line-55"></a> <span class='hs-varid'>reqBody</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>repr</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>repr</span>
65+<a name="line-56"></a> <span class='hs-varid'>queryParam</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>repr</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>repr</span>
66+<a name="line-57"></a> <span class='hs-varid'>conj</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>repr'</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>repr</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>repr</span>
67+<a name="line-58"></a> <span class='hs-varid'>get</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>repr</span>
68+<a name="line-59"></a> <span class='hs-varid'>post</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>repr</span>
69+<a name="line-60"></a> <span class='hs-varid'>put</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>repr</span>
70+<a name="line-61"></a> <span class='hs-varid'>delete</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>String</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>repr</span>
71+<a name="line-62"></a>
72+<a name="line-63"></a>
73+<a name="line-64"></a><span class='hs-keyword'>infixr</span> <span class='hs-num'>6</span> <span class='hs-varop'>&gt;:</span>
74+<a name="line-65"></a>
75+<a name="line-66"></a><a name="%3e:"></a><span class='hs-layout'>(</span><span class='hs-varop'>&gt;:</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Type</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Type</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Type</span>
76+<a name="line-67"></a><span class='hs-layout'>(</span><span class='hs-varop'>&gt;:</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>conj</span>
77+<a name="line-68"></a>
78+<a name="line-69"></a>
79+<a name="line-70"></a><a name="instance%20ExpSYM%20Type%20Type"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>ExpSYM</span> <span class='hs-conid'>Type</span> <span class='hs-conid'>Type</span> <span class='hs-keyword'>where</span>
80+<a name="line-71"></a> <span class='hs-varid'>lit</span> <span class='hs-varid'>name</span> <span class='hs-varid'>r</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>LitT</span> <span class='hs-layout'>(</span><span class='hs-conid'>StrTyLit</span> <span class='hs-varid'>name</span><span class='hs-layout'>)</span> <span class='hs-varop'>&gt;:</span> <span class='hs-varid'>r</span>
81+<a name="line-72"></a> <span class='hs-varid'>capture</span> <span class='hs-varid'>name</span> <span class='hs-varid'>typ</span> <span class='hs-varid'>r</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>AppT</span> <span class='hs-layout'>(</span><span class='hs-conid'>AppT</span> <span class='hs-layout'>(</span><span class='hs-conid'>ConT</span> <span class='hs-chr'>'</span><span class='hs-chr'>'</span><span class='hs-conid'>Capture</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>LitT</span> <span class='hs-layout'>(</span><span class='hs-conid'>StrTyLit</span> <span class='hs-varid'>name</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
82+<a name="line-73"></a> <span class='hs-layout'>(</span><span class='hs-conid'>ConT</span> <span class='hs-varop'>$</span> <span class='hs-varid'>mkName</span> <span class='hs-varid'>typ</span><span class='hs-layout'>)</span> <span class='hs-varop'>&gt;:</span> <span class='hs-varid'>r</span>
83+<a name="line-74"></a> <span class='hs-varid'>reqBody</span> <span class='hs-varid'>typ</span> <span class='hs-varid'>r</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>AppT</span> <span class='hs-layout'>(</span><span class='hs-conid'>ConT</span> <span class='hs-chr'>'</span><span class='hs-chr'>'</span><span class='hs-conid'>ReqBody</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>ConT</span> <span class='hs-varop'>$</span> <span class='hs-varid'>mkName</span> <span class='hs-varid'>typ</span><span class='hs-layout'>)</span> <span class='hs-varop'>&gt;:</span> <span class='hs-varid'>r</span>
84+<a name="line-75"></a> <span class='hs-varid'>queryParam</span> <span class='hs-varid'>name</span> <span class='hs-varid'>typ</span> <span class='hs-varid'>r</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>AppT</span> <span class='hs-layout'>(</span><span class='hs-conid'>AppT</span> <span class='hs-layout'>(</span><span class='hs-conid'>ConT</span> <span class='hs-chr'>'</span><span class='hs-chr'>'</span><span class='hs-conid'>QueryParam</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>LitT</span> <span class='hs-layout'>(</span><span class='hs-conid'>StrTyLit</span> <span class='hs-varid'>name</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
85+<a name="line-76"></a> <span class='hs-layout'>(</span><span class='hs-conid'>ConT</span> <span class='hs-varop'>$</span> <span class='hs-varid'>mkName</span> <span class='hs-varid'>typ</span><span class='hs-layout'>)</span> <span class='hs-varop'>&gt;:</span> <span class='hs-varid'>r</span>
86+<a name="line-77"></a> <span class='hs-varid'>conj</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>AppT</span> <span class='hs-layout'>(</span><span class='hs-conid'>AppT</span> <span class='hs-layout'>(</span><span class='hs-conid'>ConT</span> <span class='hs-chr'>'</span><span class='hs-chr'>'</span><span class='hs-layout'>(</span><span class='hs-conop'>:&gt;</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span>
87+<a name="line-78"></a> <span class='hs-varid'>get</span> <span class='hs-varid'>typ</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>AppT</span> <span class='hs-layout'>(</span><span class='hs-conid'>ConT</span> <span class='hs-chr'>'</span><span class='hs-chr'>'</span><span class='hs-conid'>Get</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>ConT</span> <span class='hs-varop'>$</span> <span class='hs-varid'>mkName</span> <span class='hs-varid'>typ</span><span class='hs-layout'>)</span>
88+<a name="line-79"></a> <span class='hs-varid'>post</span> <span class='hs-varid'>typ</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>AppT</span> <span class='hs-layout'>(</span><span class='hs-conid'>ConT</span> <span class='hs-chr'>'</span><span class='hs-chr'>'</span><span class='hs-conid'>Post</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>ConT</span> <span class='hs-varop'>$</span> <span class='hs-varid'>mkName</span> <span class='hs-varid'>typ</span><span class='hs-layout'>)</span>
89+<a name="line-80"></a> <span class='hs-varid'>put</span> <span class='hs-varid'>typ</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>AppT</span> <span class='hs-layout'>(</span><span class='hs-conid'>ConT</span> <span class='hs-chr'>'</span><span class='hs-chr'>'</span><span class='hs-conid'>Put</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>ConT</span> <span class='hs-varop'>$</span> <span class='hs-varid'>mkName</span> <span class='hs-varid'>typ</span><span class='hs-layout'>)</span>
90+<a name="line-81"></a> <span class='hs-varid'>delete</span> <span class='hs-str'>"()"</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>ConT</span> <span class='hs-chr'>'</span><span class='hs-chr'>'</span><span class='hs-conid'>Delete</span>
91+<a name="line-82"></a> <span class='hs-varid'>delete</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>error</span> <span class='hs-str'>"Delete does not return a request body"</span>
92+<a name="line-83"></a>
93+<a name="line-84"></a><a name="parseMethod"></a><span class='hs-definition'>parseMethod</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ExpSYM</span> <span class='hs-varid'>repr'</span> <span class='hs-varid'>repr</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>Parser</span> <span class='hs-layout'>(</span><span class='hs-conid'>String</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>repr</span><span class='hs-layout'>)</span>
94+<a name="line-85"></a><span class='hs-definition'>parseMethod</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>try</span> <span class='hs-layout'>(</span><span class='hs-varid'>string</span> <span class='hs-str'>"GET"</span> <span class='hs-varop'>&gt;&gt;</span> <span class='hs-varid'>return</span> <span class='hs-varid'>get</span><span class='hs-layout'>)</span>
95+<a name="line-86"></a> <span class='hs-varop'>&lt;|&gt;</span> <span class='hs-varid'>try</span> <span class='hs-layout'>(</span><span class='hs-varid'>string</span> <span class='hs-str'>"POST"</span> <span class='hs-varop'>&gt;&gt;</span> <span class='hs-varid'>return</span> <span class='hs-varid'>post</span><span class='hs-layout'>)</span>
96+<a name="line-87"></a> <span class='hs-varop'>&lt;|&gt;</span> <span class='hs-varid'>try</span> <span class='hs-layout'>(</span><span class='hs-varid'>string</span> <span class='hs-str'>"PUT"</span> <span class='hs-varop'>&gt;&gt;</span> <span class='hs-varid'>return</span> <span class='hs-varid'>put</span><span class='hs-layout'>)</span>
97+<a name="line-88"></a> <span class='hs-varop'>&lt;|&gt;</span> <span class='hs-varid'>try</span> <span class='hs-layout'>(</span><span class='hs-varid'>string</span> <span class='hs-str'>"DELETE"</span> <span class='hs-varop'>&gt;&gt;</span> <span class='hs-varid'>return</span> <span class='hs-varid'>delete</span><span class='hs-layout'>)</span>
98+<a name="line-89"></a>
99+<a name="line-90"></a><a name="parseUrlSegment"></a><span class='hs-definition'>parseUrlSegment</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ExpSYM</span> <span class='hs-varid'>repr</span> <span class='hs-varid'>repr</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>Parser</span> <span class='hs-layout'>(</span><span class='hs-varid'>repr</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>repr</span><span class='hs-layout'>)</span>
100+<a name="line-91"></a><span class='hs-definition'>parseUrlSegment</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>try</span> <span class='hs-varid'>parseCapture</span>
101+<a name="line-92"></a> <span class='hs-varop'>&lt;|&gt;</span> <span class='hs-varid'>try</span> <span class='hs-varid'>parseQueryParam</span>
102+<a name="line-93"></a> <span class='hs-varop'>&lt;|&gt;</span> <span class='hs-varid'>try</span> <span class='hs-varid'>parseLit</span>
103+<a name="line-94"></a> <span class='hs-keyword'>where</span>
104+<a name="line-95"></a> <span class='hs-varid'>parseCapture</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
105+<a name="line-96"></a> <span class='hs-varid'>cname</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>many</span> <span class='hs-layout'>(</span><span class='hs-varid'>noneOf</span> <span class='hs-str'>" ?/:"</span><span class='hs-layout'>)</span>
106+<a name="line-97"></a> <span class='hs-varid'>char</span> <span class='hs-chr'>':'</span>
107+<a name="line-98"></a> <span class='hs-varid'>ctyp</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>many</span> <span class='hs-layout'>(</span><span class='hs-varid'>noneOf</span> <span class='hs-str'>" ?/:"</span><span class='hs-layout'>)</span>
108+<a name="line-99"></a> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-varid'>capture</span> <span class='hs-varid'>cname</span> <span class='hs-varid'>ctyp</span>
109+<a name="line-100"></a> <span class='hs-varid'>parseQueryParam</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
110+<a name="line-101"></a> <span class='hs-varid'>char</span> <span class='hs-chr'>'?'</span>
111+<a name="line-102"></a> <span class='hs-varid'>cname</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>many</span> <span class='hs-layout'>(</span><span class='hs-varid'>noneOf</span> <span class='hs-str'>" ?/:"</span><span class='hs-layout'>)</span>
112+<a name="line-103"></a> <span class='hs-varid'>char</span> <span class='hs-chr'>':'</span>
113+<a name="line-104"></a> <span class='hs-varid'>ctyp</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>many</span> <span class='hs-layout'>(</span><span class='hs-varid'>noneOf</span> <span class='hs-str'>" ?/:"</span><span class='hs-layout'>)</span>
114+<a name="line-105"></a> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-varid'>queryParam</span> <span class='hs-varid'>cname</span> <span class='hs-varid'>ctyp</span>
115+<a name="line-106"></a> <span class='hs-varid'>parseLit</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>lit</span> <span class='hs-varop'>&lt;$&gt;</span> <span class='hs-varid'>many</span> <span class='hs-layout'>(</span><span class='hs-varid'>noneOf</span> <span class='hs-str'>" ?/:"</span><span class='hs-layout'>)</span>
116+<a name="line-107"></a>
117+<a name="line-108"></a><a name="parseUrl"></a><span class='hs-definition'>parseUrl</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ExpSYM</span> <span class='hs-varid'>repr</span> <span class='hs-varid'>repr</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>Parser</span> <span class='hs-layout'>(</span><span class='hs-varid'>repr</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>repr</span><span class='hs-layout'>)</span>
118+<a name="line-109"></a><span class='hs-definition'>parseUrl</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
119+<a name="line-110"></a> <span class='hs-varid'>optional</span> <span class='hs-varop'>$</span> <span class='hs-varid'>char</span> <span class='hs-chr'>'/'</span>
120+<a name="line-111"></a> <span class='hs-varid'>url</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>parseUrlSegment</span> <span class='hs-varop'>`sepBy1`</span> <span class='hs-varid'>char</span> <span class='hs-chr'>'/'</span>
121+<a name="line-112"></a> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-varid'>foldr1</span> <span class='hs-layout'>(</span><span class='hs-varop'>.</span><span class='hs-layout'>)</span> <span class='hs-varid'>url</span>
122+<a name="line-113"></a>
123+<a name="line-114"></a><a name="Typ"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>Typ</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Val</span> <span class='hs-conid'>String</span>
124+<a name="line-115"></a> <span class='hs-keyglyph'>|</span> <span class='hs-conid'>ReqArgVal</span> <span class='hs-conid'>String</span> <span class='hs-conid'>String</span>
125+<a name="line-116"></a>
126+<a name="line-117"></a><a name="parseTyp"></a><span class='hs-definition'>parseTyp</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Parser</span> <span class='hs-conid'>Typ</span>
127+<a name="line-118"></a><span class='hs-definition'>parseTyp</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
128+<a name="line-119"></a> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>many</span> <span class='hs-layout'>(</span><span class='hs-varid'>noneOf</span> <span class='hs-str'>"-{\n\r"</span><span class='hs-layout'>)</span>
129+<a name="line-120"></a> <span class='hs-varid'>spaces</span>
130+<a name="line-121"></a> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>optionMaybe</span> <span class='hs-layout'>(</span><span class='hs-varid'>try</span> <span class='hs-varid'>parseRet</span><span class='hs-layout'>)</span>
131+<a name="line-122"></a> <span class='hs-varid'>try</span> <span class='hs-varop'>$</span> <span class='hs-varid'>optional</span> <span class='hs-varid'>inlineComment</span>
132+<a name="line-123"></a> <span class='hs-varid'>try</span> <span class='hs-varop'>$</span> <span class='hs-varid'>optional</span> <span class='hs-varid'>blockComment</span>
133+<a name="line-124"></a> <span class='hs-keyword'>case</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>of</span>
134+<a name="line-125"></a> <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Val</span> <span class='hs-layout'>(</span><span class='hs-varid'>stripTr</span> <span class='hs-varid'>f</span><span class='hs-layout'>)</span>
135+<a name="line-126"></a> <span class='hs-conid'>Just</span> <span class='hs-varid'>s'</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-conid'>ReqArgVal</span> <span class='hs-layout'>(</span><span class='hs-varid'>stripTr</span> <span class='hs-varid'>f</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>stripTr</span> <span class='hs-varid'>s'</span><span class='hs-layout'>)</span>
136+<a name="line-127"></a> <span class='hs-keyword'>where</span>
137+<a name="line-128"></a> <span class='hs-varid'>parseRet</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Parser</span> <span class='hs-conid'>String</span>
138+<a name="line-129"></a> <span class='hs-varid'>parseRet</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
139+<a name="line-130"></a> <span class='hs-varid'>string</span> <span class='hs-str'>"-&gt;"</span>
140+<a name="line-131"></a> <span class='hs-varid'>spaces</span>
141+<a name="line-132"></a> <span class='hs-varid'>many</span> <span class='hs-layout'>(</span><span class='hs-varid'>noneOf</span> <span class='hs-str'>"-{\n\r"</span><span class='hs-layout'>)</span>
142+<a name="line-133"></a> <span class='hs-varid'>stripTr</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>reverse</span> <span class='hs-varop'>.</span> <span class='hs-varid'>dropWhile</span> <span class='hs-layout'>(</span><span class='hs-varop'>==</span> <span class='hs-chr'>' '</span><span class='hs-layout'>)</span> <span class='hs-varop'>.</span> <span class='hs-varid'>reverse</span>
143+<a name="line-134"></a>
144+<a name="line-135"></a>
145+<a name="line-136"></a><a name="parseEntry"></a><span class='hs-definition'>parseEntry</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>ExpSYM</span> <span class='hs-varid'>repr</span> <span class='hs-varid'>repr</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>Parser</span> <span class='hs-varid'>repr</span>
146+<a name="line-137"></a><span class='hs-definition'>parseEntry</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
147+<a name="line-138"></a> <span class='hs-varid'>met</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>parseMethod</span>
148+<a name="line-139"></a> <span class='hs-varid'>spaces</span>
149+<a name="line-140"></a> <span class='hs-varid'>url</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>parseUrl</span>
150+<a name="line-141"></a> <span class='hs-varid'>spaces</span>
151+<a name="line-142"></a> <span class='hs-varid'>typ</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>parseTyp</span>
152+<a name="line-143"></a> <span class='hs-keyword'>case</span> <span class='hs-varid'>typ</span> <span class='hs-keyword'>of</span>
153+<a name="line-144"></a> <span class='hs-conid'>Val</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-varid'>url</span> <span class='hs-layout'>(</span><span class='hs-varid'>met</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span>
154+<a name="line-145"></a> <span class='hs-conid'>ReqArgVal</span> <span class='hs-varid'>i</span> <span class='hs-varid'>o</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-varid'>url</span> <span class='hs-varop'>$</span> <span class='hs-varid'>reqBody</span> <span class='hs-varid'>i</span> <span class='hs-layout'>(</span><span class='hs-varid'>met</span> <span class='hs-varid'>o</span><span class='hs-layout'>)</span>
155+<a name="line-146"></a>
156+<a name="line-147"></a><a name="blockComment"></a><span class='hs-definition'>blockComment</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Parser</span> <span class='hs-conid'>()</span>
157+<a name="line-148"></a><span class='hs-definition'>blockComment</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
158+<a name="line-149"></a> <span class='hs-varid'>string</span> <span class='hs-str'>"{-"</span>
159+<a name="line-150"></a> <span class='hs-varid'>manyTill</span> <span class='hs-varid'>anyChar</span> <span class='hs-layout'>(</span><span class='hs-varid'>try</span> <span class='hs-varop'>$</span> <span class='hs-varid'>string</span> <span class='hs-str'>"-}"</span><span class='hs-layout'>)</span>
160+<a name="line-151"></a> <span class='hs-varid'>return</span> <span class='hs-conid'>()</span>
161+<a name="line-152"></a>
162+<a name="line-153"></a><a name="inlineComment"></a><span class='hs-definition'>inlineComment</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Parser</span> <span class='hs-conid'>()</span>
163+<a name="line-154"></a><span class='hs-definition'>inlineComment</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
164+<a name="line-155"></a> <span class='hs-varid'>string</span> <span class='hs-str'>"--"</span>
165+<a name="line-156"></a> <span class='hs-varid'>manyTill</span> <span class='hs-varid'>anyChar</span> <span class='hs-layout'>(</span><span class='hs-varid'>try</span> <span class='hs-varop'>$</span> <span class='hs-varid'>lookAhead</span> <span class='hs-varid'>eol</span><span class='hs-layout'>)</span>
166+<a name="line-157"></a> <span class='hs-varid'>return</span> <span class='hs-conid'>()</span>
167+<a name="line-158"></a>
168+<a name="line-159"></a><a name="eol"></a><span class='hs-definition'>eol</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Parser</span> <span class='hs-conid'>String</span>
169+<a name="line-160"></a><span class='hs-definition'>eol</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>try</span> <span class='hs-layout'>(</span><span class='hs-varid'>string</span> <span class='hs-str'>"\n\r"</span><span class='hs-layout'>)</span>
170+<a name="line-161"></a> <span class='hs-varop'>&lt;|&gt;</span> <span class='hs-varid'>try</span> <span class='hs-layout'>(</span><span class='hs-varid'>string</span> <span class='hs-str'>"\r\n"</span><span class='hs-layout'>)</span>
171+<a name="line-162"></a> <span class='hs-varop'>&lt;|&gt;</span> <span class='hs-varid'>string</span> <span class='hs-str'>"\n"</span>
172+<a name="line-163"></a> <span class='hs-varop'>&lt;|&gt;</span> <span class='hs-varid'>string</span> <span class='hs-str'>"\r"</span>
173+<a name="line-164"></a> <span class='hs-varop'>&lt;?&gt;</span> <span class='hs-str'>"end of line"</span>
174+<a name="line-165"></a>
175+<a name="line-166"></a><a name="eols"></a><span class='hs-definition'>eols</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Parser</span> <span class='hs-conid'>()</span>
176+<a name="line-167"></a><span class='hs-definition'>eols</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>skipMany</span> <span class='hs-varop'>$</span> <span class='hs-varid'>void</span> <span class='hs-varid'>eol</span> <span class='hs-varop'>&lt;|&gt;</span> <span class='hs-varid'>blockComment</span> <span class='hs-varop'>&lt;|&gt;</span> <span class='hs-varid'>inlineComment</span>
177+<a name="line-168"></a>
178+<a name="line-169"></a><a name="parseAll"></a><span class='hs-definition'>parseAll</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Parser</span> <span class='hs-conid'>Type</span>
179+<a name="line-170"></a><span class='hs-definition'>parseAll</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
180+<a name="line-171"></a> <span class='hs-varid'>eols</span>
181+<a name="line-172"></a> <span class='hs-varid'>entries</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>parseEntry</span> <span class='hs-varop'>`endBy`</span> <span class='hs-varid'>eols</span>
182+<a name="line-173"></a> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-varid'>foldr1</span> <span class='hs-varid'>union</span> <span class='hs-varid'>entries</span>
183+<a name="line-174"></a> <span class='hs-keyword'>where</span> <span class='hs-varid'>union</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Type</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Type</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Type</span>
184+<a name="line-175"></a> <span class='hs-varid'>union</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>AppT</span> <span class='hs-layout'>(</span><span class='hs-conid'>AppT</span> <span class='hs-layout'>(</span><span class='hs-conid'>ConT</span> <span class='hs-chr'>'</span><span class='hs-chr'>'</span><span class='hs-layout'>(</span><span class='hs-conop'>:&lt;|&gt;</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span>
185+<a name="line-176"></a>
186+<a name="line-177"></a><a name="sitemap"></a><span class='hs-comment'>-- | The sitemap QuasiQuoter.</span>
187+<a name="line-178"></a><span class='hs-comment'>--</span>
188+<a name="line-179"></a><span class='hs-comment'>-- * @.../&lt;var&gt;:&lt;type&gt;/...@ becomes a capture</span>
189+<a name="line-180"></a><span class='hs-comment'>-- * @.../?&lt;var&gt;:&lt;type&gt;@ becomes a query parameter</span>
190+<a name="line-181"></a><span class='hs-comment'>-- * @&lt;method&gt; ... &lt;typ&gt;@ becomes a method returning @&lt;typ&gt;@</span>
191+<a name="line-182"></a><span class='hs-comment'>-- * @&lt;method&gt; ... &lt;typ1&gt; -&gt; &lt;typ2&gt;@ becomes a method with request</span>
192+<a name="line-183"></a><span class='hs-comment'>-- body of @&lt;typ1&gt;@ and returning @&lt;typ2&gt;@</span>
193+<a name="line-184"></a><span class='hs-comment'>--</span>
194+<a name="line-185"></a><span class='hs-comment'>-- Comments are allowed, and have the standard Haskell format</span>
195+<a name="line-186"></a><span class='hs-comment'>--</span>
196+<a name="line-187"></a><span class='hs-comment'>-- * @--@ for inline</span>
197+<a name="line-188"></a><span class='hs-comment'>-- * @{- ... -}@ for block</span>
198+<a name="line-189"></a><span class='hs-comment'>--</span>
199+<a name="line-190"></a><span class='hs-definition'>sitemap</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>QuasiQuoter</span>
200+<a name="line-191"></a><span class='hs-definition'>sitemap</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>QuasiQuoter</span> <span class='hs-layout'>{</span> <span class='hs-varid'>quoteExp</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>undefined</span>
201+<a name="line-192"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>quotePat</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>undefined</span>
202+<a name="line-193"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>quoteType</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>x</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>parse</span> <span class='hs-varid'>parseAll</span> <span class='hs-str'>""</span> <span class='hs-varid'>x</span> <span class='hs-keyword'>of</span>
203+<a name="line-194"></a> <span class='hs-conid'>Left</span> <span class='hs-varid'>err</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>error</span> <span class='hs-varop'>$</span> <span class='hs-varid'>show</span> <span class='hs-varid'>err</span>
204+<a name="line-195"></a> <span class='hs-conid'>Right</span> <span class='hs-varid'>st</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>return</span> <span class='hs-varid'>st</span>
205+<a name="line-196"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>quoteDec</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>undefined</span>
206+<a name="line-197"></a> <span class='hs-layout'>}</span>
207+<a name="line-198"></a>
208+</pre></body>
209+</html>
src/Servant-Server.htmlnew file+116
@@ -0,0 +1,116 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3+<html>
4+<head>
5+<!-- Generated by HsColour, http://code.haskell.org/~malcolm/hscolour/ -->
6+<title>src/Servant/Server.hs</title>
7+<link type='text/css' rel='stylesheet' href='hscolour.css' />
8+</head>
9+<body>
10+<pre><a name="line-1"></a><span class='hs-comment'>{-# LANGUAGE TypeFamilies #-}</span>
11+<a name="line-2"></a><span class='hs-comment'>{-# LANGUAGE OverloadedStrings #-}</span>
12+<a name="line-3"></a>
13+<a name="line-4"></a><span class='hs-comment'>-- | This module lets you implement 'Server's for defined APIs. You'll</span>
14+<a name="line-5"></a><span class='hs-comment'>-- most likely just need 'serve'.</span>
15+<a name="line-6"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Server</span> <span class='hs-keyword'>where</span>
16+<a name="line-7"></a>
17+<a name="line-8"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Monoid</span>
18+<a name="line-9"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Proxy</span>
19+<a name="line-10"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Network</span><span class='hs-varop'>.</span><span class='hs-conid'>HTTP</span><span class='hs-varop'>.</span><span class='hs-conid'>Types</span>
20+<a name="line-11"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Network</span><span class='hs-varop'>.</span><span class='hs-conid'>Wai</span>
21+<a name="line-12"></a>
22+<a name="line-13"></a><span class='hs-comment'>-- * Implementing Servers</span>
23+<a name="line-14"></a>
24+<a name="line-15"></a><a name="serve"></a><span class='hs-comment'>-- | 'serve' allows you to implement an API and produce a wai 'Application'.</span>
25+<a name="line-16"></a><span class='hs-comment'>--</span>
26+<a name="line-17"></a><span class='hs-comment'>-- Example:</span>
27+<a name="line-18"></a><span class='hs-comment'>--</span>
28+<a name="line-19"></a><span class='hs-comment'>-- &gt; type MyApi = "books" :&gt; Get [Book] -- GET /books</span>
29+<a name="line-20"></a><span class='hs-comment'>-- &gt; :&lt;|&gt; "books" :&gt; ReqBody Book :&gt; Post Book -- POST /books</span>
30+<a name="line-21"></a><span class='hs-comment'>-- &gt;</span>
31+<a name="line-22"></a><span class='hs-comment'>-- &gt; server :: Server MyApi</span>
32+<a name="line-23"></a><span class='hs-comment'>-- &gt; server = listAllBooks :&lt;|&gt; postBook</span>
33+<a name="line-24"></a><span class='hs-comment'>-- &gt; where listAllBooks = ...</span>
34+<a name="line-25"></a><span class='hs-comment'>-- &gt; postBook book = ...</span>
35+<a name="line-26"></a><span class='hs-comment'>-- &gt;</span>
36+<a name="line-27"></a><span class='hs-comment'>-- &gt; app :: Application</span>
37+<a name="line-28"></a><span class='hs-comment'>-- &gt; app = serve myApi server</span>
38+<a name="line-29"></a><span class='hs-comment'>-- &gt;</span>
39+<a name="line-30"></a><span class='hs-comment'>-- &gt; main :: IO ()</span>
40+<a name="line-31"></a><span class='hs-comment'>-- &gt; main = Network.Wai.Handler.Warp.run 8080 app</span>
41+<a name="line-32"></a><span class='hs-definition'>serve</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>HasServer</span> <span class='hs-varid'>layout</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>layout</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Server</span> <span class='hs-varid'>layout</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Application</span>
42+<a name="line-33"></a><span class='hs-definition'>serve</span> <span class='hs-varid'>p</span> <span class='hs-varid'>server</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>toApplication</span> <span class='hs-layout'>(</span><span class='hs-varid'>route</span> <span class='hs-varid'>p</span> <span class='hs-varid'>server</span><span class='hs-layout'>)</span>
43+<a name="line-34"></a>
44+<a name="line-35"></a><a name="toApplication"></a><span class='hs-definition'>toApplication</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>RoutingApplication</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Application</span>
45+<a name="line-36"></a><span class='hs-definition'>toApplication</span> <span class='hs-varid'>ra</span> <span class='hs-varid'>request</span> <span class='hs-varid'>respond</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
46+<a name="line-37"></a> <span class='hs-varid'>ra</span> <span class='hs-varid'>request</span> <span class='hs-layout'>(</span><span class='hs-varid'>routingRespond</span> <span class='hs-varop'>.</span> <span class='hs-varid'>routeResult</span><span class='hs-layout'>)</span>
47+<a name="line-38"></a> <span class='hs-keyword'>where</span>
48+<a name="line-39"></a> <span class='hs-varid'>routingRespond</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Either</span> <span class='hs-conid'>RouteMismatch</span> <span class='hs-conid'>Response</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>ResponseReceived</span>
49+<a name="line-40"></a> <span class='hs-varid'>routingRespond</span> <span class='hs-layout'>(</span><span class='hs-conid'>Left</span> <span class='hs-conid'>NotFound</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span>
50+<a name="line-41"></a> <span class='hs-varid'>respond</span> <span class='hs-varop'>$</span> <span class='hs-varid'>responseLBS</span> <span class='hs-varid'>notFound404</span> <span class='hs-conid'>[]</span> <span class='hs-str'>"not found"</span>
51+<a name="line-42"></a> <span class='hs-varid'>routingRespond</span> <span class='hs-layout'>(</span><span class='hs-conid'>Left</span> <span class='hs-conid'>WrongMethod</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span>
52+<a name="line-43"></a> <span class='hs-varid'>respond</span> <span class='hs-varop'>$</span> <span class='hs-varid'>responseLBS</span> <span class='hs-varid'>methodNotAllowed405</span> <span class='hs-conid'>[]</span> <span class='hs-str'>"method not allowed"</span>
53+<a name="line-44"></a> <span class='hs-varid'>routingRespond</span> <span class='hs-layout'>(</span><span class='hs-conid'>Left</span> <span class='hs-conid'>InvalidBody</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span>
54+<a name="line-45"></a> <span class='hs-varid'>respond</span> <span class='hs-varop'>$</span> <span class='hs-varid'>responseLBS</span> <span class='hs-varid'>badRequest400</span> <span class='hs-conid'>[]</span> <span class='hs-str'>"Invalid JSON in request body"</span>
55+<a name="line-46"></a> <span class='hs-varid'>routingRespond</span> <span class='hs-layout'>(</span><span class='hs-conid'>Right</span> <span class='hs-varid'>response</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span>
56+<a name="line-47"></a> <span class='hs-varid'>respond</span> <span class='hs-varid'>response</span>
57+<a name="line-48"></a>
58+<a name="line-49"></a><a name="RouteMismatch"></a><span class='hs-comment'>-- * Route mismatch</span>
59+<a name="line-50"></a><a name="RouteMismatch"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>RouteMismatch</span> <span class='hs-keyglyph'>=</span>
60+<a name="line-51"></a> <span class='hs-conid'>NotFound</span> <span class='hs-comment'>-- ^ the usual "not found" error</span>
61+<a name="line-52"></a> <span class='hs-keyglyph'>|</span> <span class='hs-conid'>WrongMethod</span> <span class='hs-comment'>-- ^ a more informative "you just got the HTTP method wrong" error</span>
62+<a name="line-53"></a> <span class='hs-keyglyph'>|</span> <span class='hs-conid'>InvalidBody</span> <span class='hs-comment'>-- ^ an even more informative "your json request body wasn't valid" error</span>
63+<a name="line-54"></a> <span class='hs-keyword'>deriving</span> <span class='hs-layout'>(</span><span class='hs-conid'>Eq</span><span class='hs-layout'>,</span> <span class='hs-conid'>Show</span><span class='hs-layout'>)</span>
64+<a name="line-55"></a>
65+<a name="line-56"></a><a name="instance%20Monoid%20RouteMismatch"></a><span class='hs-comment'>-- | </span>
66+<a name="line-57"></a><a name="instance%20Monoid%20RouteMismatch"></a><span class='hs-comment'>-- @</span>
67+<a name="line-58"></a><a name="instance%20Monoid%20RouteMismatch"></a><span class='hs-comment'>-- &gt; mempty = NotFound</span>
68+<a name="line-59"></a><a name="instance%20Monoid%20RouteMismatch"></a><span class='hs-comment'>-- &gt;</span>
69+<a name="line-60"></a><a name="instance%20Monoid%20RouteMismatch"></a><span class='hs-comment'>-- &gt; NotFound `mappend` x = x</span>
70+<a name="line-61"></a><a name="instance%20Monoid%20RouteMismatch"></a><span class='hs-comment'>-- &gt; WrongMethod `mappend` InvalidBody = InvalidBody</span>
71+<a name="line-62"></a><a name="instance%20Monoid%20RouteMismatch"></a><span class='hs-comment'>-- &gt; WrongMethod `mappend` _ = WrongMethod</span>
72+<a name="line-63"></a><a name="instance%20Monoid%20RouteMismatch"></a><span class='hs-comment'>-- &gt; InvalidBody `mappend` _ = InvalidBody</span>
73+<a name="line-64"></a><a name="instance%20Monoid%20RouteMismatch"></a><span class='hs-comment'>-- @</span>
74+<a name="line-65"></a><a name="instance%20Monoid%20RouteMismatch"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>Monoid</span> <span class='hs-conid'>RouteMismatch</span> <span class='hs-keyword'>where</span>
75+<a name="line-66"></a> <span class='hs-varid'>mempty</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>NotFound</span>
76+<a name="line-67"></a>
77+<a name="line-68"></a> <span class='hs-conid'>NotFound</span> <span class='hs-varop'>`mappend`</span> <span class='hs-varid'>x</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>x</span>
78+<a name="line-69"></a> <span class='hs-conid'>WrongMethod</span> <span class='hs-varop'>`mappend`</span> <span class='hs-conid'>InvalidBody</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>InvalidBody</span>
79+<a name="line-70"></a> <span class='hs-conid'>WrongMethod</span> <span class='hs-varop'>`mappend`</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>WrongMethod</span>
80+<a name="line-71"></a> <span class='hs-conid'>InvalidBody</span> <span class='hs-varop'>`mappend`</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>InvalidBody</span>
81+<a name="line-72"></a>
82+<a name="line-73"></a><a name="RouteResult"></a><span class='hs-comment'>-- | A wrapper around @'Either' 'RouteMismatch' a@.</span>
83+<a name="line-74"></a><a name="RouteResult"></a><span class='hs-keyword'>newtype</span> <span class='hs-conid'>RouteResult</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span>
84+<a name="line-75"></a> <span class='hs-conid'>RR</span> <span class='hs-layout'>{</span> <span class='hs-varid'>routeResult</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Either</span> <span class='hs-conid'>RouteMismatch</span> <span class='hs-varid'>a</span> <span class='hs-layout'>}</span>
85+<a name="line-76"></a> <span class='hs-keyword'>deriving</span> <span class='hs-layout'>(</span><span class='hs-conid'>Eq</span><span class='hs-layout'>,</span> <span class='hs-conid'>Show</span><span class='hs-layout'>)</span>
86+<a name="line-77"></a>
87+<a name="line-78"></a><a name="failWith"></a><span class='hs-definition'>failWith</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>RouteMismatch</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>RouteResult</span> <span class='hs-varid'>a</span>
88+<a name="line-79"></a><span class='hs-definition'>failWith</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>RR</span> <span class='hs-varop'>.</span> <span class='hs-conid'>Left</span>
89+<a name="line-80"></a>
90+<a name="line-81"></a><a name="succeedWith"></a><span class='hs-definition'>succeedWith</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>RouteResult</span> <span class='hs-varid'>a</span>
91+<a name="line-82"></a><span class='hs-definition'>succeedWith</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>RR</span> <span class='hs-varop'>.</span> <span class='hs-conid'>Right</span>
92+<a name="line-83"></a>
93+<a name="line-84"></a><a name="isMismatch"></a><span class='hs-definition'>isMismatch</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>RouteResult</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Bool</span>
94+<a name="line-85"></a><span class='hs-definition'>isMismatch</span> <span class='hs-layout'>(</span><span class='hs-conid'>RR</span> <span class='hs-layout'>(</span><span class='hs-conid'>Left</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>True</span>
95+<a name="line-86"></a><span class='hs-definition'>isMismatch</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>False</span>
96+<a name="line-87"></a>
97+<a name="line-88"></a><a name="instance%20Monoid%20(RouteResult%20a)"></a><span class='hs-comment'>-- | If we get a `Right`, it has precedence over everything else.</span>
98+<a name="line-89"></a><a name="instance%20Monoid%20(RouteResult%20a)"></a><span class='hs-comment'>--</span>
99+<a name="line-90"></a><a name="instance%20Monoid%20(RouteResult%20a)"></a><span class='hs-comment'>-- This in particular means that if we could get several 'Right's,</span>
100+<a name="line-91"></a><a name="instance%20Monoid%20(RouteResult%20a)"></a><span class='hs-comment'>-- only the first we encounter would be taken into account.</span>
101+<a name="line-92"></a><a name="instance%20Monoid%20(RouteResult%20a)"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>Monoid</span> <span class='hs-layout'>(</span><span class='hs-conid'>RouteResult</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
102+<a name="line-93"></a> <span class='hs-varid'>mempty</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>RR</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Left</span> <span class='hs-varid'>mempty</span>
103+<a name="line-94"></a>
104+<a name="line-95"></a> <span class='hs-conid'>RR</span> <span class='hs-layout'>(</span><span class='hs-conid'>Left</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span> <span class='hs-varop'>`mappend`</span> <span class='hs-conid'>RR</span> <span class='hs-layout'>(</span><span class='hs-conid'>Left</span> <span class='hs-varid'>y</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>RR</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Left</span> <span class='hs-layout'>(</span><span class='hs-varid'>x</span> <span class='hs-varop'>&lt;&gt;</span> <span class='hs-varid'>y</span><span class='hs-layout'>)</span>
105+<a name="line-96"></a> <span class='hs-conid'>RR</span> <span class='hs-layout'>(</span><span class='hs-conid'>Left</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-varop'>`mappend`</span> <span class='hs-conid'>RR</span> <span class='hs-layout'>(</span><span class='hs-conid'>Right</span> <span class='hs-varid'>y</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>RR</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Right</span> <span class='hs-varid'>y</span>
106+<a name="line-97"></a> <span class='hs-varid'>r</span> <span class='hs-varop'>`mappend`</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>r</span>
107+<a name="line-98"></a>
108+<a name="line-99"></a><a name="RoutingApplication"></a><span class='hs-keyword'>type</span> <span class='hs-conid'>RoutingApplication</span> <span class='hs-keyglyph'>=</span>
109+<a name="line-100"></a> <span class='hs-conid'>Request</span> <span class='hs-comment'>-- ^ the request, the field 'pathInfo' may be modified by url routing</span>
110+<a name="line-101"></a> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>RouteResult</span> <span class='hs-conid'>Response</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>ResponseReceived</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-conid'>ResponseReceived</span>
111+<a name="line-102"></a>
112+<a name="line-103"></a><span class='hs-keyword'>class</span> <span class='hs-conid'>HasServer</span> <span class='hs-varid'>layout</span> <span class='hs-keyword'>where</span>
113+<a name="line-104"></a> <span class='hs-keyword'>type</span> <span class='hs-conid'>Server</span> <span class='hs-varid'>layout</span> <span class='hs-keyglyph'>::</span> <span class='hs-varop'>*</span>
114+<a name="line-105"></a> <span class='hs-varid'>route</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>layout</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Server</span> <span class='hs-varid'>layout</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>RoutingApplication</span>
115+</pre></body>
116+</html>
src/Servant-Utils-Links.htmlnew file+121
@@ -0,0 +1,121 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3+<html>
4+<head>
5+<!-- Generated by HsColour, http://code.haskell.org/~malcolm/hscolour/ -->
6+<title>src/Servant/Utils/Links.hs</title>
7+<link type='text/css' rel='stylesheet' href='hscolour.css' />
8+</head>
9+<body>
10+<pre><a name="line-1"></a><span class='hs-comment'>{-# LANGUAGE PolyKinds #-}</span>
11+<a name="line-2"></a><span class='hs-comment'>{-# LANGUAGE DataKinds #-}</span>
12+<a name="line-3"></a><span class='hs-comment'>{-# LANGUAGE FlexibleInstances #-}</span>
13+<a name="line-4"></a><span class='hs-comment'>{-# LANGUAGE TypeFamilies #-}</span>
14+<a name="line-5"></a><span class='hs-comment'>{-# LANGUAGE TypeOperators #-}</span>
15+<a name="line-6"></a><span class='hs-comment'>{-# LANGUAGE FunctionalDependencies #-}</span>
16+<a name="line-7"></a><span class='hs-comment'>{-# LANGUAGE ScopedTypeVariables #-}</span>
17+<a name="line-8"></a><span class='hs-comment'>{-# LANGUAGE UndecidableInstances #-}</span>
18+<a name="line-9"></a><span class='hs-comment'>-- | Type safe internal links.</span>
19+<a name="line-10"></a><span class='hs-comment'>--</span>
20+<a name="line-11"></a><span class='hs-comment'>-- Provides the function 'mkLink':</span>
21+<a name="line-12"></a><span class='hs-comment'>--</span>
22+<a name="line-13"></a><span class='hs-comment'>-- @</span>
23+<a name="line-14"></a><span class='hs-comment'>-- type API = Proxy ("hello" :&gt; Get Int</span>
24+<a name="line-15"></a><span class='hs-comment'>-- :&lt;|&gt; "bye" :&gt; QueryParam "name" String :&gt; Post Bool)</span>
25+<a name="line-16"></a><span class='hs-comment'>--</span>
26+<a name="line-17"></a><span class='hs-comment'>-- api :: API</span>
27+<a name="line-18"></a><span class='hs-comment'>-- api = proxy</span>
28+<a name="line-19"></a><span class='hs-comment'>--</span>
29+<a name="line-20"></a><span class='hs-comment'>-- link1 :: Proxy ("hello" :&gt; Get Int)</span>
30+<a name="line-21"></a><span class='hs-comment'>-- link1 = proxy</span>
31+<a name="line-22"></a><span class='hs-comment'>--</span>
32+<a name="line-23"></a><span class='hs-comment'>-- link2 :: Proxy ("hello" :&gt; Delete)</span>
33+<a name="line-24"></a><span class='hs-comment'>-- link2 = proxy</span>
34+<a name="line-25"></a><span class='hs-comment'>--</span>
35+<a name="line-26"></a><span class='hs-comment'>-- mkLink link1 API -- typechecks, returns 'Link "/hello"'</span>
36+<a name="line-27"></a><span class='hs-comment'>--</span>
37+<a name="line-28"></a><span class='hs-comment'>-- mkLink link2 API -- doesn't typecheck</span>
38+<a name="line-29"></a><span class='hs-comment'>-- @</span>
39+<a name="line-30"></a><span class='hs-comment'>--</span>
40+<a name="line-31"></a><span class='hs-comment'>-- That is, 'mkLink' takes two arguments, a link proxy and a sitemap, and</span>
41+<a name="line-32"></a><span class='hs-comment'>-- returns a 'Link', but only typechecks if the link proxy is a valid link,</span>
42+<a name="line-33"></a><span class='hs-comment'>-- and part of the sitemap.</span>
43+<a name="line-34"></a><span class='hs-comment'>--</span>
44+<a name="line-35"></a><span class='hs-comment'>-- __N.B.:__ 'mkLink' assumes a capture matches any string (without slashes).</span>
45+<a name="line-36"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Utils</span><span class='hs-varop'>.</span><span class='hs-conid'>Links</span> <span class='hs-keyword'>where</span>
46+<a name="line-37"></a>
47+<a name="line-38"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Proxy</span>
48+<a name="line-39"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>GHC</span><span class='hs-varop'>.</span><span class='hs-conid'>TypeLits</span>
49+<a name="line-40"></a>
50+<a name="line-41"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Capture</span>
51+<a name="line-42"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>ReqBody</span>
52+<a name="line-43"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>QueryParam</span>
53+<a name="line-44"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Get</span>
54+<a name="line-45"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Post</span>
55+<a name="line-46"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Put</span>
56+<a name="line-47"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Delete</span>
57+<a name="line-48"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Sub</span>
58+<a name="line-49"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Alternative</span>
59+<a name="line-50"></a>
60+<a name="line-51"></a>
61+<a name="line-52"></a><span class='hs-keyword'>type</span> <span class='hs-varid'>family</span> <span class='hs-conid'>Or</span> <span class='hs-varid'>a</span> <span class='hs-varid'>b</span> <span class='hs-keyword'>where</span>
62+<a name="line-53"></a> <span class='hs-conid'>Or</span> <span class='hs-chr'>'</span><span class='hs-conid'>False</span> <span class='hs-chr'>'</span><span class='hs-conid'>False</span> <span class='hs-keyglyph'>=</span> <span class='hs-chr'>'</span><span class='hs-conid'>False</span>
63+<a name="line-54"></a> <span class='hs-conid'>Or</span> <span class='hs-chr'>'</span><span class='hs-conid'>True</span> <span class='hs-varid'>b</span> <span class='hs-keyglyph'>=</span> <span class='hs-chr'>'</span><span class='hs-conid'>True</span>
64+<a name="line-55"></a> <span class='hs-conid'>Or</span> <span class='hs-varid'>a</span> <span class='hs-chr'>'</span><span class='hs-conid'>True</span> <span class='hs-keyglyph'>=</span> <span class='hs-chr'>'</span><span class='hs-conid'>True</span>
65+<a name="line-56"></a>
66+<a name="line-57"></a><span class='hs-keyword'>type</span> <span class='hs-varid'>family</span> <span class='hs-conid'>And</span> <span class='hs-varid'>a</span> <span class='hs-varid'>b</span> <span class='hs-keyword'>where</span>
67+<a name="line-58"></a> <span class='hs-conid'>And</span> <span class='hs-chr'>'</span><span class='hs-conid'>True</span> <span class='hs-chr'>'</span><span class='hs-conid'>True</span> <span class='hs-keyglyph'>=</span> <span class='hs-chr'>'</span><span class='hs-conid'>True</span>
68+<a name="line-59"></a> <span class='hs-conid'>And</span> <span class='hs-varid'>a</span> <span class='hs-chr'>'</span><span class='hs-conid'>False</span> <span class='hs-keyglyph'>=</span> <span class='hs-chr'>'</span><span class='hs-conid'>False</span>
69+<a name="line-60"></a> <span class='hs-conid'>And</span> <span class='hs-chr'>'</span><span class='hs-conid'>False</span> <span class='hs-varid'>b</span> <span class='hs-keyglyph'>=</span> <span class='hs-chr'>'</span><span class='hs-conid'>False</span>
70+<a name="line-61"></a>
71+<a name="line-62"></a><span class='hs-keyword'>type</span> <span class='hs-varid'>family</span> <span class='hs-conid'>IsElem</span> <span class='hs-varid'>a</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>where</span>
72+<a name="line-63"></a> <span class='hs-conid'>IsElem</span> <span class='hs-varid'>e</span> <span class='hs-layout'>(</span><span class='hs-varid'>sa</span> <span class='hs-conop'>:&lt;|&gt;</span> <span class='hs-varid'>sb</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Or</span> <span class='hs-layout'>(</span><span class='hs-conid'>IsElem</span> <span class='hs-varid'>e</span> <span class='hs-varid'>sa</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>IsElem</span> <span class='hs-varid'>e</span> <span class='hs-varid'>sb</span><span class='hs-layout'>)</span>
73+<a name="line-64"></a> <span class='hs-conid'>IsElem</span> <span class='hs-layout'>(</span><span class='hs-varid'>e</span> <span class='hs-conop'>:&gt;</span> <span class='hs-varid'>sa</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>e</span> <span class='hs-conop'>:&gt;</span> <span class='hs-varid'>sb</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IsElem</span> <span class='hs-varid'>sa</span> <span class='hs-varid'>sb</span>
74+<a name="line-65"></a> <span class='hs-conid'>IsElem</span> <span class='hs-layout'>(</span><span class='hs-varid'>e</span> <span class='hs-conop'>:&gt;</span> <span class='hs-varid'>sa</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>Capture</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-conop'>:&gt;</span> <span class='hs-varid'>sb</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IsElem</span> <span class='hs-varid'>sa</span> <span class='hs-varid'>sb</span>
75+<a name="line-66"></a> <span class='hs-conid'>IsElem</span> <span class='hs-varid'>sa</span> <span class='hs-layout'>(</span><span class='hs-conid'>ReqBody</span> <span class='hs-varid'>x</span> <span class='hs-conop'>:&gt;</span> <span class='hs-varid'>sb</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IsElem</span> <span class='hs-varid'>sa</span> <span class='hs-varid'>sb</span>
76+<a name="line-67"></a> <span class='hs-conid'>IsElem</span> <span class='hs-varid'>sa</span> <span class='hs-layout'>(</span><span class='hs-conid'>QueryParam</span> <span class='hs-varid'>x</span> <span class='hs-varid'>y</span> <span class='hs-conop'>:&gt;</span> <span class='hs-varid'>sb</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IsElem</span> <span class='hs-varid'>sa</span> <span class='hs-varid'>sb</span>
77+<a name="line-68"></a> <span class='hs-conid'>IsElem</span> <span class='hs-varid'>e</span> <span class='hs-varid'>e</span> <span class='hs-keyglyph'>=</span> <span class='hs-chr'>'</span><span class='hs-conid'>True</span>
78+<a name="line-69"></a> <span class='hs-conid'>IsElem</span> <span class='hs-varid'>e</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span> <span class='hs-chr'>'</span><span class='hs-conid'>False</span>
79+<a name="line-70"></a>
80+<a name="line-71"></a><span class='hs-keyword'>type</span> <span class='hs-varid'>family</span> <span class='hs-conid'>IsLink''</span> <span class='hs-varid'>l</span> <span class='hs-keyword'>where</span>
81+<a name="line-72"></a> <span class='hs-conid'>IsLink''</span> <span class='hs-layout'>(</span><span class='hs-varid'>e</span> <span class='hs-conop'>:&gt;</span> <span class='hs-conid'>Get</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IsLink'</span> <span class='hs-varid'>e</span>
82+<a name="line-73"></a> <span class='hs-conid'>IsLink''</span> <span class='hs-layout'>(</span><span class='hs-varid'>e</span> <span class='hs-conop'>:&gt;</span> <span class='hs-conid'>Post</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IsLink'</span> <span class='hs-varid'>e</span>
83+<a name="line-74"></a> <span class='hs-conid'>IsLink''</span> <span class='hs-layout'>(</span><span class='hs-varid'>e</span> <span class='hs-conop'>:&gt;</span> <span class='hs-conid'>Put</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IsLink'</span> <span class='hs-varid'>e</span>
84+<a name="line-75"></a> <span class='hs-conid'>IsLink''</span> <span class='hs-layout'>(</span><span class='hs-varid'>e</span> <span class='hs-conop'>:&gt;</span> <span class='hs-conid'>Delete</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>IsLink'</span> <span class='hs-varid'>e</span>
85+<a name="line-76"></a> <span class='hs-conid'>IsLink''</span> <span class='hs-varid'>a</span> <span class='hs-keyglyph'>=</span> <span class='hs-chr'>'</span><span class='hs-conid'>False</span>
86+<a name="line-77"></a>
87+<a name="line-78"></a><span class='hs-keyword'>type</span> <span class='hs-varid'>family</span> <span class='hs-conid'>IsLink'</span> <span class='hs-varid'>e</span> <span class='hs-keyword'>where</span>
88+<a name="line-79"></a> <span class='hs-conid'>IsLink'</span> <span class='hs-layout'>(</span><span class='hs-varid'>f</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Symbol</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-chr'>'</span><span class='hs-conid'>True</span>
89+<a name="line-80"></a>
90+<a name="line-81"></a><span class='hs-keyword'>type</span> <span class='hs-varid'>family</span> <span class='hs-conid'>IsLink</span> <span class='hs-varid'>e</span> <span class='hs-keyword'>where</span>
91+<a name="line-82"></a> <span class='hs-conid'>IsLink</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-conop'>:&gt;</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Or</span> <span class='hs-layout'>(</span><span class='hs-conid'>And</span> <span class='hs-layout'>(</span><span class='hs-conid'>IsLink'</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>IsLink''</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
92+<a name="line-83"></a> <span class='hs-layout'>(</span><span class='hs-conid'>IsLink''</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-conop'>:&gt;</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
93+<a name="line-84"></a>
94+<a name="line-85"></a>
95+<a name="line-86"></a><a name="ValidLinkIn"></a><span class='hs-comment'>-- | The 'ValidLinkIn f s' constraint holds when 's' is an API that</span>
96+<a name="line-87"></a><a name="ValidLinkIn"></a><span class='hs-comment'>-- contains 'f', and 'f' is a link.</span>
97+<a name="line-88"></a><a name="ValidLinkIn"></a><span class='hs-keyword'>class</span> <span class='hs-conid'>ValidLinkIn</span> <span class='hs-varid'>f</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>where</span>
98+<a name="line-89"></a> <span class='hs-varid'>mkLink</span> <span class='hs-keyglyph'>::</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Link</span> <span class='hs-comment'>-- ^ This function will only typecheck if `f`</span>
99+<a name="line-90"></a> <span class='hs-comment'>-- is an URI within `s`</span>
100+<a name="line-91"></a>
101+<a name="line-92"></a><a name="instance%20ValidLinkIn%20f%20s"></a><span class='hs-keyword'>instance</span> <span class='hs-layout'>(</span> <span class='hs-conid'>IsElem</span> <span class='hs-varid'>f</span> <span class='hs-varid'>s</span> <span class='hs-keyglyph'>~</span> <span class='hs-chr'>'</span><span class='hs-conid'>True</span>
102+<a name="line-93"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>IsLink</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>~</span> <span class='hs-chr'>'</span><span class='hs-conid'>True</span>
103+<a name="line-94"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>VLinkHelper</span> <span class='hs-varid'>f</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>ValidLinkIn</span> <span class='hs-varid'>f</span> <span class='hs-varid'>s</span> <span class='hs-keyword'>where</span>
104+<a name="line-95"></a> <span class='hs-varid'>mkLink</span> <span class='hs-keyword'>_</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Link</span> <span class='hs-layout'>(</span><span class='hs-varid'>vlh</span> <span class='hs-layout'>(</span><span class='hs-conid'>Proxy</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>f</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
105+<a name="line-96"></a>
106+<a name="line-97"></a><a name="Link"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>Link</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Link</span> <span class='hs-conid'>String</span> <span class='hs-keyword'>deriving</span> <span class='hs-conid'>Show</span>
107+<a name="line-98"></a>
108+<a name="line-99"></a><a name="VLinkHelper"></a><span class='hs-keyword'>class</span> <span class='hs-conid'>VLinkHelper</span> <span class='hs-varid'>f</span> <span class='hs-keyword'>where</span>
109+<a name="line-100"></a> <span class='hs-varid'>vlh</span> <span class='hs-keyglyph'>::</span> <span class='hs-keyword'>forall</span> <span class='hs-varid'>proxy</span><span class='hs-varop'>.</span> <span class='hs-varid'>proxy</span> <span class='hs-varid'>f</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>String</span>
110+<a name="line-101"></a>
111+<a name="line-102"></a><a name="instance%20VLinkHelper%20(s%20:%3e%20e)"></a><span class='hs-keyword'>instance</span> <span class='hs-layout'>(</span><span class='hs-conid'>KnownSymbol</span> <span class='hs-varid'>s</span><span class='hs-layout'>,</span> <span class='hs-conid'>VLinkHelper</span> <span class='hs-varid'>e</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=&gt;</span> <span class='hs-conid'>VLinkHelper</span> <span class='hs-layout'>(</span><span class='hs-varid'>s</span> <span class='hs-conop'>:&gt;</span> <span class='hs-varid'>e</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
112+<a name="line-103"></a> <span class='hs-varid'>vlh</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>=</span> <span class='hs-str'>"/"</span> <span class='hs-varop'>++</span> <span class='hs-varid'>symbolVal</span> <span class='hs-layout'>(</span><span class='hs-conid'>Proxy</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>s</span><span class='hs-layout'>)</span> <span class='hs-varop'>++</span> <span class='hs-varid'>vlh</span> <span class='hs-layout'>(</span><span class='hs-conid'>Proxy</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Proxy</span> <span class='hs-varid'>e</span><span class='hs-layout'>)</span>
113+<a name="line-104"></a>
114+<a name="line-105"></a><a name="instance%20VLinkHelper%20(Get%20x)"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>VLinkHelper</span> <span class='hs-layout'>(</span><span class='hs-conid'>Get</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
115+<a name="line-106"></a> <span class='hs-varid'>vlh</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>=</span> <span class='hs-str'>""</span>
116+<a name="line-107"></a>
117+<a name="line-108"></a><a name="instance%20VLinkHelper%20(Post%20x)"></a><span class='hs-keyword'>instance</span> <span class='hs-conid'>VLinkHelper</span> <span class='hs-layout'>(</span><span class='hs-conid'>Post</span> <span class='hs-varid'>x</span><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
118+<a name="line-109"></a> <span class='hs-varid'>vlh</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>=</span> <span class='hs-str'>""</span>
119+<a name="line-110"></a>
120+</pre></body>
121+</html>
src/Servant-Utils-StaticFiles.htmlnew file+47
@@ -0,0 +1,47 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3+<html>
4+<head>
5+<!-- Generated by HsColour, http://code.haskell.org/~malcolm/hscolour/ -->
6+<title>src/Servant/Utils/StaticFiles.hs</title>
7+<link type='text/css' rel='stylesheet' href='hscolour.css' />
8+</head>
9+<body>
10+<pre><a name="line-1"></a><span class='hs-comment'>-- | This module defines a sever-side handler that lets you serve static files.</span>
11+<a name="line-2"></a><span class='hs-comment'>--</span>
12+<a name="line-3"></a><span class='hs-comment'>-- - 'serveDirectory' lets you serve anything that lives under a particular</span>
13+<a name="line-4"></a><span class='hs-comment'>-- directory on your filesystem.</span>
14+<a name="line-5"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Utils</span><span class='hs-varop'>.</span><span class='hs-conid'>StaticFiles</span> <span class='hs-layout'>(</span>
15+<a name="line-6"></a> <span class='hs-varid'>serveDirectory</span><span class='hs-layout'>,</span>
16+<a name="line-7"></a> <span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
17+<a name="line-8"></a>
18+<a name="line-9"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Filesystem</span><span class='hs-varop'>.</span><span class='hs-conid'>Path</span><span class='hs-varop'>.</span><span class='hs-conid'>CurrentOS</span> <span class='hs-layout'>(</span><span class='hs-varid'>decodeString</span><span class='hs-layout'>)</span>
19+<a name="line-10"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Network</span><span class='hs-varop'>.</span><span class='hs-conid'>Wai</span><span class='hs-varop'>.</span><span class='hs-conid'>Application</span><span class='hs-varop'>.</span><span class='hs-conid'>Static</span>
20+<a name="line-11"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-varop'>.</span><span class='hs-conid'>Raw</span>
21+<a name="line-12"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Server</span>
22+<a name="line-13"></a>
23+<a name="line-14"></a><a name="serveDirectory"></a><span class='hs-comment'>-- | Serve anything under the specified directory as a 'Raw' endpoint.</span>
24+<a name="line-15"></a><span class='hs-comment'>--</span>
25+<a name="line-16"></a><span class='hs-comment'>-- @</span>
26+<a name="line-17"></a><span class='hs-comment'>-- type MyApi = "static" :&gt; Raw</span>
27+<a name="line-18"></a><span class='hs-comment'>--</span>
28+<a name="line-19"></a><span class='hs-comment'>-- server :: Server MyApi</span>
29+<a name="line-20"></a><span class='hs-comment'>-- server = serveDirectory "\/var\/www"</span>
30+<a name="line-21"></a><span class='hs-comment'>-- @</span>
31+<a name="line-22"></a><span class='hs-comment'>--</span>
32+<a name="line-23"></a><span class='hs-comment'>-- would capture any request to @\/static\/\&lt;something&gt;@ and look for</span>
33+<a name="line-24"></a><span class='hs-comment'>-- @\&lt;something&gt;@ under @\/var\/www@.</span>
34+<a name="line-25"></a><span class='hs-comment'>--</span>
35+<a name="line-26"></a><span class='hs-comment'>-- It will do its best to guess the MIME type for that file, based on the extension,</span>
36+<a name="line-27"></a><span class='hs-comment'>-- and send an appropriate /Content-Type/ header if possible.</span>
37+<a name="line-28"></a><span class='hs-comment'>--</span>
38+<a name="line-29"></a><span class='hs-comment'>-- If your goal is to serve HTML, CSS and Javascript files that use the rest of the API</span>
39+<a name="line-30"></a><span class='hs-comment'>-- as a webapp backend, you will most likely not want the static files to be hidden</span>
40+<a name="line-31"></a><span class='hs-comment'>-- behind a /\/static\// prefix. In that case, remember to put the 'serveDirectory'</span>
41+<a name="line-32"></a><span class='hs-comment'>-- handler in the last position, because /servant/ will try to match the handlers</span>
42+<a name="line-33"></a><span class='hs-comment'>-- in order.</span>
43+<a name="line-34"></a><span class='hs-definition'>serveDirectory</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>FilePath</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Server</span> <span class='hs-conid'>Raw</span>
44+<a name="line-35"></a><span class='hs-definition'>serveDirectory</span> <span class='hs-varid'>documentRoot</span> <span class='hs-keyglyph'>=</span>
45+<a name="line-36"></a> <span class='hs-varid'>staticApp</span> <span class='hs-layout'>(</span><span class='hs-varid'>defaultFileServerSettings</span> <span class='hs-layout'>(</span><span class='hs-varid'>decodeString</span> <span class='hs-layout'>(</span><span class='hs-varid'>documentRoot</span> <span class='hs-varop'>++</span> <span class='hs-str'>"/"</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
46+</pre></body>
47+</html>
src/Servant.hsdeleted−24
@@ -1,24 +0,0 @@
1−module Servant (
2− -- | This module and its submodules can be used to define servant APIs. Note
3− -- that these API definitions don't directly implement a server (or anything
4− -- else).
5− module Servant.API,
6− -- | For implementing servers for servant APIs.
7− module Servant.Server,
8− -- | Using your types in request paths and query string parameters
9− module Servant.Common.Text,
10− -- | Utilities on top of the servant core
11− module Servant.QQ,
12− module Servant.Utils.Links,
13− module Servant.Utils.StaticFiles,
14− -- | Useful re-exports
15− Proxy(..),
16− ) where
17−
18−import Data.Proxy
19−import Servant.API
20−import Servant.Common.Text
21−import Servant.Server
22−import Servant.QQ
23−import Servant.Utils.Links
24−import Servant.Utils.StaticFiles
src/Servant.htmlnew file+35
@@ -0,0 +1,35 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3+<html>
4+<head>
5+<!-- Generated by HsColour, http://code.haskell.org/~malcolm/hscolour/ -->
6+<title>src/Servant.hs</title>
7+<link type='text/css' rel='stylesheet' href='hscolour.css' />
8+</head>
9+<body>
10+<pre><a name="line-1"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span> <span class='hs-layout'>(</span>
11+<a name="line-2"></a> <span class='hs-comment'>-- | This module and its submodules can be used to define servant APIs. Note</span>
12+<a name="line-3"></a> <span class='hs-comment'>-- that these API definitions don't directly implement a server (or anything</span>
13+<a name="line-4"></a> <span class='hs-comment'>-- else).</span>
14+<a name="line-5"></a> <span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span><span class='hs-layout'>,</span>
15+<a name="line-6"></a> <span class='hs-comment'>-- | For implementing servers for servant APIs.</span>
16+<a name="line-7"></a> <span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Server</span><span class='hs-layout'>,</span>
17+<a name="line-8"></a> <span class='hs-comment'>-- | Using your types in request paths and query string parameters</span>
18+<a name="line-9"></a> <span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Common</span><span class='hs-varop'>.</span><span class='hs-conid'>Text</span><span class='hs-layout'>,</span>
19+<a name="line-10"></a> <span class='hs-comment'>-- | Utilities on top of the servant core</span>
20+<a name="line-11"></a> <span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>QQ</span><span class='hs-layout'>,</span>
21+<a name="line-12"></a> <span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Utils</span><span class='hs-varop'>.</span><span class='hs-conid'>Links</span><span class='hs-layout'>,</span>
22+<a name="line-13"></a> <span class='hs-keyword'>module</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Utils</span><span class='hs-varop'>.</span><span class='hs-conid'>StaticFiles</span><span class='hs-layout'>,</span>
23+<a name="line-14"></a> <span class='hs-comment'>-- | Useful re-exports</span>
24+<a name="line-15"></a> <span class='hs-conid'>Proxy</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span>
25+<a name="line-16"></a> <span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
26+<a name="line-17"></a>
27+<a name="line-18"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>Proxy</span>
28+<a name="line-19"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>API</span>
29+<a name="line-20"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Common</span><span class='hs-varop'>.</span><span class='hs-conid'>Text</span>
30+<a name="line-21"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Server</span>
31+<a name="line-22"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>QQ</span>
32+<a name="line-23"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Utils</span><span class='hs-varop'>.</span><span class='hs-conid'>Links</span>
33+<a name="line-24"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Servant</span><span class='hs-varop'>.</span><span class='hs-conid'>Utils</span><span class='hs-varop'>.</span><span class='hs-conid'>StaticFiles</span>
34+</pre></body>
35+</html>
src/Servant/API.hsdeleted−51
@@ -1,51 +0,0 @@
1−module Servant.API (
2−
3− -- * Combinators
4− -- | Type-level combinator for expressing subrouting: @':>'@
5− module Servant.API.Sub,
6− -- | Type-level combinator for alternative endpoints: @':<|>'@
7− module Servant.API.Alternative,
8−
9− -- * Accessing information from the request
10− -- | Capturing parts of the url path as parsed values: @'Capture'@
11− module Servant.API.Capture,
12− -- | Retrieving parameters from the query string of the 'URI': @'QueryParam'@
13− module Servant.API.QueryParam,
14− -- | Accessing the request body as a JSON-encoded type: @'ReqBody'@
15− module Servant.API.ReqBody,
16−
17− -- * Actual endpoints, distinguished by HTTP method
18− -- | GET requests
19− module Servant.API.Get,
20− -- | POST requests
21− module Servant.API.Post,
22− -- | DELETE requests
23− module Servant.API.Delete,
24− -- | PUT requests
25− module Servant.API.Put,
26−
27− -- * Untyped endpoints
28− -- | Plugging in a wai 'Network.Wai.Application', serving directories
29− module Servant.API.Raw,
30− module Servant.Utils.StaticFiles,
31−
32− -- * Utilities
33− -- | QuasiQuotes for endpoints
34− module Servant.QQ,
35− -- | Type-safe internal URLs
36− module Servant.Utils.Links,
37− ) where
38−
39−import Servant.API.Alternative
40−import Servant.API.Capture
41−import Servant.API.Delete
42−import Servant.API.Get
43−import Servant.API.Post
44−import Servant.API.Put
45−import Servant.API.QueryParam
46−import Servant.API.Raw
47−import Servant.API.ReqBody
48−import Servant.API.Sub
49−import Servant.QQ (sitemap)
50−import Servant.Utils.Links (mkLink)
51−import Servant.Utils.StaticFiles
src/Servant/API/Alternative.hsdeleted−39
@@ -1,39 +0,0 @@
1−{-# LANGUAGE TypeFamilies #-}
2−{-# LANGUAGE TypeOperators #-}
3−{-# LANGUAGE ScopedTypeVariables #-}
4−module Servant.API.Alternative where
5−
6−import Data.Monoid
7−import Data.Proxy
8−import Servant.Server
9−
10−-- | Union of two APIs, first takes precedence in case of overlap.
11−--
12−-- Example:
13−--
14−-- > type MyApi = "books" :> Get [Book] -- GET /books
15−-- > :<|> "books" :> ReqBody Book :> Post Book -- POST /books
16−data a :<|> b = a :<|> b
17−infixr 8 :<|>
18−
19−-- | A server for @a ':<|>' b@ first tries to match the request again the route
20−-- represented by @a@ and if it fails tries @b@. You must provide a request
21−-- handler for each route.
22−--
23−-- > type MyApi = "books" :> Get [Book] -- GET /books
24−-- > :<|> "books" :> ReqBody Book :> Post Book -- POST /books
25−-- >
26−-- > server :: Server MyApi
27−-- > server = listAllBooks :<|> postBook
28−-- > where listAllBooks = ...
29−-- > postBook book = ...
30−instance (HasServer a, HasServer b) => HasServer (a :<|> b) where
31− type Server (a :<|> b) = Server a :<|> Server b
32− route Proxy (a :<|> b) request respond =
33− route pa a request $ \ mResponse ->
34− if isMismatch mResponse
35− then route pb b request $ \mResponse' -> respond (mResponse <> mResponse')
36− else respond mResponse
37−
38− where pa = Proxy :: Proxy a
39− pb = Proxy :: Proxy b
src/Servant/API/Capture.hsdeleted−60
@@ -1,60 +0,0 @@
1−{-# LANGUAGE PolyKinds #-}
2−{-# LANGUAGE TypeFamilies #-}
3−{-# LANGUAGE TypeOperators #-}
4−{-# LANGUAGE FlexibleContexts #-}
5−{-# LANGUAGE FlexibleInstances #-}
6−{-# LANGUAGE ScopedTypeVariables #-}
7−module Servant.API.Capture (Capture) where
8−
9−import Data.Proxy
10−import Data.Text
11−import GHC.TypeLits
12−import Network.Wai
13−import Servant.API.Sub
14−import Servant.Common.Text
15−import Servant.Server
16−
17−-- | Capture a value from the request path under a certain type @a@.
18−--
19−-- Example:
20−--
21−-- > -- GET /books/:isbn
22−-- > type MyApi = "books" :> Capture "isbn" Text :> Get Book
23−data Capture sym a
24−
25−captured :: FromText a => proxy (Capture sym a) -> Text -> Maybe a
26−captured _ = fromText
27−
28−-- | If you use 'Capture' in one of the endpoints for your API,
29−-- this automatically requires your server-side handler to be a function
30−-- that takes an argument of the type specified by the 'Capture'.
31−-- This lets servant worry about getting it from the URL and turning
32−-- it into a value of the type you specify.
33−--
34−-- You can control how it'll be converted from 'Text' to your type
35−-- by simply providing an instance of 'FromText' for your type.
36−--
37−-- Example:
38−--
39−-- > type MyApi = "books" :> Capture "isbn" Text :> Get Book
40−-- >
41−-- > server :: Server MyApi
42−-- > server = getBook
43−-- > where getBook :: Text -> EitherT (Int, String) IO Book
44−-- > getBook isbn = ...
45−instance (KnownSymbol capture, FromText a, HasServer sublayout)
46− => HasServer (Capture capture a :> sublayout) where
47−
48− type Server (Capture capture a :> sublayout) =
49− a -> Server sublayout
50−
51− route Proxy subserver request respond = case pathInfo request of
52− (first : rest)
53− -> case captured captureProxy first of
54− Nothing -> respond $ failWith NotFound
55− Just v -> route (Proxy :: Proxy sublayout) (subserver v) request{
56− pathInfo = rest
57− } respond
58− _ -> respond $ failWith NotFound
59−
60− where captureProxy = Proxy :: Proxy (Capture capture a)
src/Servant/API/Delete.hsdeleted−48
@@ -1,48 +0,0 @@
1−{-# LANGUAGE TypeFamilies #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE ScopedTypeVariables #-}
4−{-# LANGUAGE DeriveDataTypeable #-}
5−module Servant.API.Delete where
6−
7−import Control.Monad.Trans.Either
8−import Data.Proxy
9−import Data.String.Conversions
10−import Data.Typeable
11−import Network.HTTP.Types
12−import Network.Wai
13−import Servant.Server
14−
15−-- | Combinator for DELETE requests.
16−--
17−-- Example:
18−--
19−-- > -- DELETE /books/:isbn
20−-- > type MyApi = "books" :> Capture "isbn" Text :> Delete
21−data Delete
22− deriving Typeable
23−
24−-- | If you have a 'Delete' endpoint in your API,
25−-- the handler for this endpoint is meant to delete
26−-- a resource.
27−--
28−-- The code of the handler will, just like
29−-- for 'Servant.API.Get.Get', 'Servant.API.Post.Post' and
30−-- 'Servant.API.Put.Put', run in @EitherT (Int, String) IO ()@.
31−-- The 'Int' represents the status code and the 'String' a message
32−-- to be returned. You can use 'Control.Monad.Trans.Either.left' to
33−-- painlessly error out if the conditions for a successful deletion
34−-- are not met.
35−instance HasServer Delete where
36− type Server Delete = EitherT (Int, String) IO ()
37−
38− route Proxy action request respond
39− | null (pathInfo request) && requestMethod request == methodDelete = do
40− e <- runEitherT action
41− respond $ succeedWith $ case e of
42− Right () ->
43− responseLBS status204 [] ""
44− Left (status, message) ->
45− responseLBS (mkStatus status (cs message)) [] (cs message)
46− | null (pathInfo request) && requestMethod request /= methodDelete =
47− respond $ failWith WrongMethod
48− | otherwise = respond $ failWith NotFound
src/Servant/API/Get.hsdeleted−47
@@ -1,47 +0,0 @@
1−{-# LANGUAGE TypeFamilies #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE ScopedTypeVariables #-}
4−{-# LANGUAGE DeriveDataTypeable #-}
5−module Servant.API.Get where
6−
7−import Control.Monad.Trans.Either
8−import Data.Aeson
9−import Data.Proxy
10−import Data.String.Conversions
11−import Data.Typeable
12−import Network.HTTP.Types
13−import Network.Wai
14−import Servant.Server
15−
16−-- | Endpoint for simple GET requests. Serves the result as JSON.
17−--
18−-- Example:
19−--
20−-- > type MyApi = "books" :> Get [Book]
21−data Get a
22− deriving Typeable
23−
24−-- | When implementing the handler for a 'Get' endpoint,
25−-- just like for 'Servant.API.Delete.Delete', 'Servant.API.Post.Post'
26−-- and 'Servant.API.Put.Put', the handler code runs in the
27−-- @EitherT (Int, String) IO@ monad, where the 'Int' represents
28−-- the status code and the 'String' a message, returned in case of
29−-- failure. You can quite handily use 'Control.Monad.Trans.EitherT.left'
30−-- to quickly fail if some conditions are not met.
31−--
32−-- If successfully returning a value, we just require that its type has
33−-- a 'ToJSON' instance and servant takes care of encoding it for you,
34−-- yielding status code 200 along the way.
35−instance ToJSON result => HasServer (Get result) where
36− type Server (Get result) = EitherT (Int, String) IO result
37− route Proxy action request respond
38− | null (pathInfo request) && requestMethod request == methodGet = do
39− e <- runEitherT action
40− respond . succeedWith $ case e of
41− Right output ->
42− responseLBS ok200 [("Content-Type", "application/json")] (encode output)
43− Left (status, message) ->
44− responseLBS (mkStatus status (cs message)) [] (cs message)
45− | null (pathInfo request) && requestMethod request /= methodGet =
46− respond $ failWith WrongMethod
47− | otherwise = respond $ failWith NotFound
src/Servant/API/Post.hsdeleted−53
@@ -1,53 +0,0 @@
1−{-# LANGUAGE TypeFamilies #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE ScopedTypeVariables #-}
4−{-# LANGUAGE DeriveDataTypeable #-}
5−module Servant.API.Post where
6−
7−import Control.Monad.Trans.Either
8−import Data.Aeson
9−import Data.Proxy
10−import Data.String.Conversions
11−import Data.Typeable
12−import Network.HTTP.Types
13−import Network.Wai
14−import Servant.Server
15−
16−-- | Endpoint for POST requests. The type variable represents the type of the
17−-- response body (not the request body, use 'Servant.API.RQBody.RQBody' for
18−-- that).
19−--
20−-- Example:
21−--
22−-- > -- POST /books
23−-- > -- with a JSON encoded Book as the request body
24−-- > -- returning the just-created Book
25−-- > type MyApi = "books" :> ReqBody Book :> Post Book
26−data Post a
27− deriving Typeable
28−
29−-- | When implementing the handler for a 'Post' endpoint,
30−-- just like for 'Servant.API.Delete.Delete', 'Servant.API.Get.Get'
31−-- and 'Servant.API.Put.Put', the handler code runs in the
32−-- @EitherT (Int, String) IO@ monad, where the 'Int' represents
33−-- the status code and the 'String' a message, returned in case of
34−-- failure. You can quite handily use 'Control.Monad.Trans.EitherT.left'
35−-- to quickly fail if some conditions are not met.
36−--
37−-- If successfully returning a value, we just require that its type has
38−-- a 'ToJSON' instance and servant takes care of encoding it for you,
39−-- yielding status code 201 along the way.
40−instance ToJSON a => HasServer (Post a) where
41− type Server (Post a) = EitherT (Int, String) IO a
42−
43− route Proxy action request respond
44− | null (pathInfo request) && requestMethod request == methodPost = do
45− e <- runEitherT action
46− respond . succeedWith $ case e of
47− Right out ->
48− responseLBS status201 [("Content-Type", "application/json")] (encode out)
49− Left (status, message) ->
50− responseLBS (mkStatus status (cs message)) [] (cs message)
51− | null (pathInfo request) && requestMethod request /= methodPost =
52− respond $ failWith WrongMethod
53− | otherwise = respond $ failWith NotFound
src/Servant/API/Put.hsdeleted−52
@@ -1,52 +0,0 @@
1−{-# LANGUAGE TypeFamilies #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE ScopedTypeVariables #-}
4−{-# LANGUAGE DeriveDataTypeable #-}
5−module Servant.API.Put where
6−
7−import Control.Monad.Trans.Either
8−import Data.Aeson
9−import Data.Proxy
10−import Data.String.Conversions
11−import Data.Typeable
12−import Network.HTTP.Types
13−import Network.Wai
14−import Servant.Server
15−
16−-- | Endpoint for PUT requests, usually used to update a ressource.
17−-- The type @a@ is the type of the response body that's returned.
18−--
19−-- Example:
20−--
21−-- > -- PUT /books/:isbn
22−-- > -- with a Book as request body, returning the updated Book
23−-- > type MyApi = "books" :> Capture "isbn" Text :> ReqBody Book :> Put Book
24−data Put a
25− deriving Typeable
26−
27−-- | When implementing the handler for a 'Put' endpoint,
28−-- just like for 'Servant.API.Delete.Delete', 'Servant.API.Get.Get'
29−-- and 'Servant.API.Post.Post', the handler code runs in the
30−-- @EitherT (Int, String) IO@ monad, where the 'Int' represents
31−-- the status code and the 'String' a message, returned in case of
32−-- failure. You can quite handily use 'Control.Monad.Trans.EitherT.left'
33−-- to quickly fail if some conditions are not met.
34−--
35−-- If successfully returning a value, we just require that its type has
36−-- a 'ToJSON' instance and servant takes care of encoding it for you,
37−-- yielding status code 200 along the way.
38−instance ToJSON a => HasServer (Put a) where
39− type Server (Put a) = EitherT (Int, String) IO a
40−
41− route Proxy action request respond
42− | null (pathInfo request) && requestMethod request == methodPut = do
43− e <- runEitherT action
44− respond . succeedWith $ case e of
45− Right out ->
46− responseLBS ok200 [("Content-Type", "application/json")] (encode out)
47− Left (status, message) ->
48− responseLBS (mkStatus status (cs message)) [] (cs message)
49− | null (pathInfo request) && requestMethod request /= methodPut =
50− respond $ failWith WrongMethod
51−
52− | otherwise = respond $ failWith NotFound
src/Servant/API/QueryParam.hsdeleted−162
@@ -1,162 +0,0 @@
1−{-# LANGUAGE PolyKinds #-}
2−{-# LANGUAGE TypeFamilies #-}
3−{-# LANGUAGE TypeOperators #-}
4−{-# LANGUAGE FlexibleContexts #-}
5−{-# LANGUAGE FlexibleInstances #-}
6−{-# LANGUAGE OverloadedStrings #-}
7−{-# LANGUAGE ScopedTypeVariables #-}
8−module Servant.API.QueryParam where
9−
10−import Data.Maybe
11−import Data.Proxy
12−import Data.String.Conversions
13−import GHC.TypeLits
14−import Network.HTTP.Types
15−import Network.Wai
16−import Servant.API.Sub
17−import Servant.Common.Text
18−import Servant.Server
19−
20−-- | Lookup the value associated to the @sym@ query string parameter
21−-- and try to extract it as a value of type @a@.
22−--
23−-- Example:
24−--
25−-- > -- /books?author=<author name>
26−-- > type MyApi = "books" :> QueryParam "author" Text :> Get [Book]
27−data QueryParam sym a
28−
29−-- | If you use @'QueryParam' "author" Text@ in one of the endpoints for your API,
30−-- this automatically requires your server-side handler to be a function
31−-- that takes an argument of type @'Maybe' 'Text'@.
32−--
33−-- This lets servant worry about looking it up in the query string
34−-- and turning it into a value of the type you specify, enclosed
35−-- in 'Maybe', because it may not be there and servant would then
36−-- hand you 'Nothing'.
37−--
38−-- You can control how it'll be converted from 'Text' to your type
39−-- by simply providing an instance of 'FromText' for your type.
40−--
41−-- Example:
42−--
43−-- > type MyApi = "books" :> QueryParam "author" Text :> Get [Book]
44−-- >
45−-- > server :: Server MyApi
46−-- > server = getBooksBy
47−-- > where getBooksBy :: Maybe Text -> EitherT (Int, String) IO [Book]
48−-- > getBooksBy Nothing = ...return all books...
49−-- > getBooksBy (Just author) = ...return books by the given author...
50−instance (KnownSymbol sym, FromText a, HasServer sublayout)
51− => HasServer (QueryParam sym a :> sublayout) where
52−
53− type Server (QueryParam sym a :> sublayout) =
54− Maybe a -> Server sublayout
55−
56− route Proxy subserver request respond = do
57− let querytext = parseQueryText $ rawQueryString request
58− param =
59− case lookup paramname querytext of
60− Nothing -> Nothing -- param absent from the query string
61− Just Nothing -> Nothing -- param present with no value -> Nothing
62− Just (Just v) -> fromText v -- if present, we try to convert to
63− -- the right type
64−
65− route (Proxy :: Proxy sublayout) (subserver param) request respond
66−
67− where paramname = cs $ symbolVal (Proxy :: Proxy sym)
68−
69−-- | Lookup the values associated to the @sym@ query string parameter
70−-- and try to extract it as a value of type @[a]@. This is typically
71−-- meant to support query string parameters of the form
72−-- @param[]=val1&param[]=val2@ and so on. Note that servant doesn't actually
73−-- require the @[]@s and will fetch the values just fine with
74−-- @param=val1&param=val2@, too.
75−--
76−-- Example:
77−--
78−-- > -- /books?authors[]=<author1>&authors[]=<author2>&...
79−-- > type MyApi = "books" :> QueryParams "authors" Text :> Get [Book]
80−data QueryParams sym a
81−
82−-- | If you use @'QueryParams' "authors" Text@ in one of the endpoints for your API,
83−-- this automatically requires your server-side handler to be a function
84−-- that takes an argument of type @['Text']@.
85−--
86−-- This lets servant worry about looking up 0 or more values in the query string
87−-- associated to @authors@ and turning each of them into a value of
88−-- the type you specify.
89−--
90−-- You can control how the individual values are converted from 'Text' to your type
91−-- by simply providing an instance of 'FromText' for your type.
92−--
93−-- Example:
94−--
95−-- > type MyApi = "books" :> QueryParams "authors" Text :> Get [Book]
96−-- >
97−-- > server :: Server MyApi
98−-- > server = getBooksBy
99−-- > where getBooksBy :: [Text] -> EitherT (Int, String) IO [Book]
100−-- > getBooksBy authors = ...return all books by these authors...
101−instance (KnownSymbol sym, FromText a, HasServer sublayout)
102− => HasServer (QueryParams sym a :> sublayout) where
103−
104− type Server (QueryParams sym a :> sublayout) =
105− [a] -> Server sublayout
106−
107− route Proxy subserver request respond = do
108− let querytext = parseQueryText $ rawQueryString request
109− -- if sym is "foo", we look for query string parameters
110− -- named "foo" or "foo[]" and call fromText on the
111− -- corresponding values
112− parameters = filter looksLikeParam querytext
113− values = catMaybes $ map (convert . snd) parameters
114−
115− route (Proxy :: Proxy sublayout) (subserver values) request respond
116−
117− where paramname = cs $ symbolVal (Proxy :: Proxy sym)
118− looksLikeParam (name, _) = name == paramname || name == (paramname <> "[]")
119− convert Nothing = Nothing
120− convert (Just v) = fromText v
121−
122−-- | Lookup a potentially value-less query string parameter
123−-- with boolean semantics. If the param @sym@ is there without any value,
124−-- or if it's there with value "true" or "1", it's interpreted as 'True'.
125−-- Otherwise, it's interpreted as 'False'.
126−--
127−-- Example:
128−--
129−-- > -- /books?published
130−-- > type MyApi = "books" :> QueryFlag "published" :> Get [Book]
131−data QueryFlag sym
132−
133−-- | If you use @'QueryFlag' "published"@ in one of the endpoints for your API,
134−-- this automatically requires your server-side handler to be a function
135−-- that takes an argument of type 'Bool'.
136−--
137−-- Example:
138−--
139−-- > type MyApi = "books" :> QueryFlag "published" :> Get [Book]
140−-- >
141−-- > server :: Server MyApi
142−-- > server = getBooks
143−-- > where getBooks :: Bool -> EitherT (Int, String) IO [Book]
144−-- > getBooks onlyPublished = ...return all books, or only the ones that are already published, depending on the argument...
145−instance (KnownSymbol sym, HasServer sublayout)
146− => HasServer (QueryFlag sym :> sublayout) where
147−
148− type Server (QueryFlag sym :> sublayout) =
149− Bool -> Server sublayout
150−
151− route Proxy subserver request respond = do
152− let querytext = parseQueryText $ rawQueryString request
153− param = case lookup paramname querytext of
154− Just Nothing -> True -- param is there, with no value
155− Just (Just v) -> examine v -- param with a value
156− Nothing -> False -- param not in the query string
157−
158− route (Proxy :: Proxy sublayout) (subserver param) request respond
159−
160− where paramname = cs $ symbolVal (Proxy :: Proxy sym)
161− examine v | v == "true" || v == "1" || v == "" = True
162− | otherwise = False
src/Servant/API/Raw.hsdeleted−32
@@ -1,32 +0,0 @@
1−{-# LANGUAGE InstanceSigs #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE TypeFamilies #-}
4−module Servant.API.Raw where
5−
6−import Data.Proxy
7−import Network.Wai
8−import Servant.Server
9−
10−-- | Endpoint for plugging in your own Wai 'Application's.
11−--
12−-- The given 'Application' will get the request as received by the server, potentially with
13−-- a modified (stripped) 'pathInfo' if the 'Application' is being routed with 'Servant.API.Sub.:>'.
14−--
15−-- In addition to just letting you plug in your existing WAI 'Application's,
16−-- this can also be used with 'Servant.Utils.StaticFiles.serveDirectory' to serve
17−-- static files stored in a particular directory on your filesystem, or to serve
18−-- your API's documentation with 'Servant.Utils.StaticFiles.serveDocumentation'.
19−data Raw
20−
21−-- | Just pass the request to the underlying application and serve its response.
22−--
23−-- Example:
24−--
25−-- > type MyApi = "images" :> Raw
26−-- >
27−-- > server :: Server MyApi
28−-- > server = serveDirectory "/var/www/images"
29−instance HasServer Raw where
30− type Server Raw = Application
31− route Proxy rawApplication request respond =
32− rawApplication request (respond . succeedWith)
src/Servant/API/ReqBody.hsdeleted−49
@@ -1,49 +0,0 @@
1−{-# LANGUAGE PolyKinds #-}
2−{-# LANGUAGE TypeFamilies #-}
3−{-# LANGUAGE TypeOperators #-}
4−{-# LANGUAGE FlexibleInstances #-}
5−{-# LANGUAGE ScopedTypeVariables #-}
6−module Servant.API.ReqBody where
7−
8−import Control.Applicative
9−import Data.Aeson
10−import Data.Proxy
11−import Network.Wai
12−import Servant.API.Sub
13−import Servant.Server
14−
15−-- | Extract the request body as a value of type @a@.
16−--
17−-- Example:
18−--
19−-- > -- POST /books
20−-- > type MyApi = "books" :> ReqBody Book :> Post Book
21−data ReqBody a
22−
23−-- | If you use 'ReqBody' in one of the endpoints for your API,
24−-- this automatically requires your server-side handler to be a function
25−-- that takes an argument of the type specified by 'ReqBody'.
26−-- This lets servant worry about extracting it from the request and turning
27−-- it into a value of the type you specify.
28−--
29−-- All it asks is for a 'FromJSON' instance.
30−--
31−-- Example:
32−--
33−-- > type MyApi = "books" :> ReqBody Book :> Post Book
34−-- >
35−-- > server :: Server MyApi
36−-- > server = postBook
37−-- > where postBook :: Book -> EitherT (Int, String) IO Book
38−-- > postBook book = ...insert into your db...
39−instance (FromJSON a, HasServer sublayout)
40− => HasServer (ReqBody a :> sublayout) where
41−
42− type Server (ReqBody a :> sublayout) =
43− a -> Server sublayout
44−
45− route Proxy subserver request respond = do
46− mrqbody <- decode' <$> lazyRequestBody request
47− case mrqbody of
48− Nothing -> respond $ failWith InvalidBody
49− Just v -> route (Proxy :: Proxy sublayout) (subserver v) request respond
src/Servant/API/Sub.hsdeleted−36
@@ -1,36 +0,0 @@
1−{-# LANGUAGE PolyKinds #-}
2−{-# LANGUAGE TypeFamilies #-}
3−{-# LANGUAGE TypeOperators #-}
4−{-# LANGUAGE ScopedTypeVariables #-}
5−module Servant.API.Sub where
6−
7−import Data.Proxy
8−import Data.String.Conversions
9−import GHC.TypeLits
10−import Network.Wai
11−import Servant.Server
12−
13−-- | The contained API (second argument) can be found under @("/" ++ path)@
14−-- (path being the first argument).
15−--
16−-- Example:
17−--
18−-- > -- GET /hello/world
19−-- > -- returning a JSON encoded World value
20−-- > type MyApi = "hello" :> "world" :> Get World
21−data (path :: k) :> a = Proxy path :> a
22−infixr 9 :>
23−
24−-- | Make sure the incoming request starts with @"/path"@, strip it and
25−-- pass the rest of the request path to @sublayout@.
26−instance (KnownSymbol path, HasServer sublayout) => HasServer (path :> sublayout) where
27− type Server (path :> sublayout) = Server sublayout
28− route Proxy subserver request respond = case pathInfo request of
29− (first : rest)
30− | first == cs (symbolVal proxyPath)
31− -> route (Proxy :: Proxy sublayout) subserver request{
32− pathInfo = rest
33− } respond
34− _ -> respond $ failWith NotFound
35−
36− where proxyPath = Proxy :: Proxy path
src/Servant/Common/Text.hsdeleted−130
@@ -1,130 +0,0 @@
1−{-# LANGUAGE FlexibleInstances #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE TypeSynonymInstances #-}
4−module Servant.Common.Text
5− ( FromText(..)
6− , ToText(..)
7− ) where
8−
9−import Data.String.Conversions
10−import Data.Int
11−import Data.Text
12−import Data.Text.Read
13−import Data.Word
14−
15−-- | For getting values from url captures and query string parameters
16−class FromText a where
17− fromText :: Text -> Maybe a
18−
19−-- | For putting values in paths and query string parameters
20−class ToText a where
21− toText :: a -> Text
22−
23−instance FromText Text where
24− fromText = Just
25−
26−instance ToText Text where
27− toText = id
28−
29−instance FromText String where
30− fromText = Just . cs
31−
32−instance ToText String where
33− toText = cs
34−
35−-- |
36−-- > fromText "true" = Just True
37−-- > fromText "false" = Just False
38−-- > fromText _ = Nothing
39−instance FromText Bool where
40− fromText "true" = Just True
41− fromText "false" = Just False
42− fromText _ = Nothing
43−
44−-- |
45−-- > toText True = "true"
46−-- > toText False = "false"
47−instance ToText Bool where
48− toText True = "true"
49− toText False = "false"
50−
51−instance FromText Int where
52− fromText = runReader (signed decimal)
53−
54−instance ToText Int where
55− toText = cs . show
56−
57−instance FromText Int8 where
58− fromText = runReader (signed decimal)
59−
60−instance ToText Int8 where
61− toText = cs . show
62−
63−instance FromText Int16 where
64− fromText = runReader (signed decimal)
65−
66−instance ToText Int16 where
67− toText = cs . show
68−
69−instance FromText Int32 where
70− fromText = runReader (signed decimal)
71−
72−instance ToText Int32 where
73− toText = cs . show
74−
75−instance FromText Int64 where
76− fromText = runReader (signed decimal)
77−
78−instance ToText Int64 where
79− toText = cs . show
80−
81−instance FromText Word where
82− fromText = runReader decimal
83−
84−instance ToText Word where
85− toText = cs . show
86−
87−instance FromText Word8 where
88− fromText = runReader decimal
89−
90−instance ToText Word8 where
91− toText = cs . show
92−
93−instance FromText Word16 where
94− fromText = runReader decimal
95−
96−instance ToText Word16 where
97− toText = cs . show
98−
99−instance FromText Word32 where
100− fromText = runReader decimal
101−
102−instance ToText Word32 where
103− toText = cs . show
104−
105−instance FromText Word64 where
106− fromText = runReader decimal
107−
108−instance ToText Word64 where
109− toText = cs . show
110−
111−instance FromText Integer where
112− fromText = runReader decimal
113−
114−instance ToText Integer where
115− toText = cs . show
116−
117−instance FromText Double where
118− fromText = runReader rational
119−
120−instance ToText Double where
121− toText = cs . show
122−
123−instance FromText Float where
124− fromText = runReader rational
125−
126−instance ToText Float where
127− toText = cs . show
128−
129−runReader :: Reader a -> Text -> Maybe a
130−runReader reader t = either (const Nothing) (Just . fst) $ reader t
src/Servant/QQ.hsdeleted−198
@@ -1,198 +0,0 @@
1−{-# LANGUAGE MultiParamTypeClasses #-}
2−{-# LANGUAGE FunctionalDependencies #-}
3−{-# LANGUAGE DataKinds #-}
4−{-# LANGUAGE FlexibleInstances #-}
5−{-# LANGUAGE ScopedTypeVariables #-}
6−{-# LANGUAGE TemplateHaskell #-}
7−{-# OPTIONS_GHC -fno-warn-unused-do-bind #-}
8−-- | QuasiQuoting utilities for API types.
9−--
10−-- 'sitemap' allows you to write your type in a very natural way:
11−--
12−-- @
13−-- [sitemap|
14−-- PUT hello String -> ()
15−-- POST hello/p:Int String -> ()
16−-- GET hello/?name:String Int
17−-- |]
18−-- @
19−--
20−-- Will generate:
21−--
22−-- @
23−-- "hello" :> ReqBody String :> Put ()
24−-- :\<|> "hello" :> Capture "p" Int :> ReqBody String :> Post ()
25−-- :\<|> "hello" :> QueryParam "name" String :> Get Int
26−-- @
27−--
28−-- Note the @/@ before a @QueryParam@!
29−module Servant.QQ where
30−
31−import Control.Monad (void)
32−import Control.Applicative hiding (many, (<|>), optional)
33−import Language.Haskell.TH.Quote
34−import Language.Haskell.TH
35−import Text.ParserCombinators.Parsec
36−
37−import Servant.API.Capture
38−import Servant.API.Get
39−import Servant.API.Post
40−import Servant.API.Put
41−import Servant.API.Delete
42−import Servant.API.QueryParam
43−import Servant.API.ReqBody
44−import Servant.API.Sub
45−import Servant.API.Alternative
46−
47−-- | Finally-tagless encoding for our DSL.
48−-- Keeping 'repr'' and 'repr' distinct when writing functions with an
49−-- @ExpSYM@ context ensures certain invariants (for instance, that there is
50−-- only one of 'get', 'post', 'put', and 'delete' in a value), but
51−-- sometimes requires a little more work.
52−class ExpSYM repr' repr | repr -> repr', repr' -> repr where
53− lit :: String -> repr' -> repr
54− capture :: String -> String -> repr -> repr
55− reqBody :: String -> repr -> repr
56− queryParam :: String -> String -> repr -> repr
57− conj :: repr' -> repr -> repr
58− get :: String -> repr
59− post :: String -> repr
60− put :: String -> repr
61− delete :: String -> repr
62−
63−
64−infixr 6 >:
65−
66−(>:) :: Type -> Type -> Type
67−(>:) = conj
68−
69−
70−instance ExpSYM Type Type where
71− lit name r = LitT (StrTyLit name) >: r
72− capture name typ r = AppT (AppT (ConT ''Capture) (LitT (StrTyLit name)))
73− (ConT $ mkName typ) >: r
74− reqBody typ r = AppT (ConT ''ReqBody) (ConT $ mkName typ) >: r
75− queryParam name typ r = AppT (AppT (ConT ''QueryParam) (LitT (StrTyLit name)))
76− (ConT $ mkName typ) >: r
77− conj x = AppT (AppT (ConT ''(:>)) x)
78− get typ = AppT (ConT ''Get) (ConT $ mkName typ)
79− post typ = AppT (ConT ''Post) (ConT $ mkName typ)
80− put typ = AppT (ConT ''Put) (ConT $ mkName typ)
81− delete "()" = ConT ''Delete
82− delete _ = error "Delete does not return a request body"
83−
84−parseMethod :: ExpSYM repr' repr => Parser (String -> repr)
85−parseMethod = try (string "GET" >> return get)
86− <|> try (string "POST" >> return post)
87− <|> try (string "PUT" >> return put)
88− <|> try (string "DELETE" >> return delete)
89−
90−parseUrlSegment :: ExpSYM repr repr => Parser (repr -> repr)
91−parseUrlSegment = try parseCapture
92− <|> try parseQueryParam
93− <|> try parseLit
94− where
95− parseCapture = do
96− cname <- many (noneOf " ?/:")
97− char ':'
98− ctyp <- many (noneOf " ?/:")
99− return $ capture cname ctyp
100− parseQueryParam = do
101− char '?'
102− cname <- many (noneOf " ?/:")
103− char ':'
104− ctyp <- many (noneOf " ?/:")
105− return $ queryParam cname ctyp
106− parseLit = lit <$> many (noneOf " ?/:")
107−
108−parseUrl :: ExpSYM repr repr => Parser (repr -> repr)
109−parseUrl = do
110− optional $ char '/'
111− url <- parseUrlSegment `sepBy1` char '/'
112− return $ foldr1 (.) url
113−
114−data Typ = Val String
115− | ReqArgVal String String
116−
117−parseTyp :: Parser Typ
118−parseTyp = do
119− f <- many (noneOf "-{\n\r")
120− spaces
121− s <- optionMaybe (try parseRet)
122− try $ optional inlineComment
123− try $ optional blockComment
124− case s of
125− Nothing -> return $ Val (stripTr f)
126− Just s' -> return $ ReqArgVal (stripTr f) (stripTr s')
127− where
128− parseRet :: Parser String
129− parseRet = do
130− string "->"
131− spaces
132− many (noneOf "-{\n\r")
133− stripTr = reverse . dropWhile (== ' ') . reverse
134−
135−
136−parseEntry :: ExpSYM repr repr => Parser repr
137−parseEntry = do
138− met <- parseMethod
139− spaces
140− url <- parseUrl
141− spaces
142− typ <- parseTyp
143− case typ of
144− Val s -> return $ url (met s)
145− ReqArgVal i o -> return $ url $ reqBody i (met o)
146−
147−blockComment :: Parser ()
148−blockComment = do
149− string "{-"
150− manyTill anyChar (try $ string "-}")
151− return ()
152−
153−inlineComment :: Parser ()
154−inlineComment = do
155− string "--"
156− manyTill anyChar (try $ lookAhead eol)
157− return ()
158−
159−eol :: Parser String
160−eol = try (string "\n\r")
161− <|> try (string "\r\n")
162− <|> string "\n"
163− <|> string "\r"
164− <?> "end of line"
165−
166−eols :: Parser ()
167−eols = skipMany $ void eol <|> blockComment <|> inlineComment
168−
169−parseAll :: Parser Type
170−parseAll = do
171− eols
172− entries <- parseEntry `endBy` eols
173− return $ foldr1 union entries
174− where union :: Type -> Type -> Type
175− union a = AppT (AppT (ConT ''(:<|>)) a)
176−
177−-- | The sitemap QuasiQuoter.
178−--
179−-- * @.../<var>:<type>/...@ becomes a capture
180−-- * @.../?<var>:<type>@ becomes a query parameter
181−-- * @<method> ... <typ>@ becomes a method returning @<typ>@
182−-- * @<method> ... <typ1> -> <typ2>@ becomes a method with request
183−-- body of @<typ1>@ and returning @<typ2>@
184−--
185−-- Comments are allowed, and have the standard Haskell format
186−--
187−-- * @--@ for inline
188−-- * @{- ... -}@ for block
189−--
190−sitemap :: QuasiQuoter
191−sitemap = QuasiQuoter { quoteExp = undefined
192− , quotePat = undefined
193− , quoteType = \x -> case parse parseAll "" x of
194− Left err -> error $ show err
195− Right st -> return st
196− , quoteDec = undefined
197− }
198−
src/Servant/Server.hsdeleted−105
@@ -1,105 +0,0 @@
1−{-# LANGUAGE TypeFamilies #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−
4−-- | This module lets you implement 'Server's for defined APIs. You'll
5−-- most likely just need 'serve'.
6−module Servant.Server where
7−
8−import Data.Monoid
9−import Data.Proxy
10−import Network.HTTP.Types
11−import Network.Wai
12−
13−-- * Implementing Servers
14−
15−-- | 'serve' allows you to implement an API and produce a wai 'Application'.
16−--
17−-- Example:
18−--
19−-- > type MyApi = "books" :> Get [Book] -- GET /books
20−-- > :<|> "books" :> ReqBody Book :> Post Book -- POST /books
21−-- >
22−-- > server :: Server MyApi
23−-- > server = listAllBooks :<|> postBook
24−-- > where listAllBooks = ...
25−-- > postBook book = ...
26−-- >
27−-- > app :: Application
28−-- > app = serve myApi server
29−-- >
30−-- > main :: IO ()
31−-- > main = Network.Wai.Handler.Warp.run 8080 app
32−serve :: HasServer layout => Proxy layout -> Server layout -> Application
33−serve p server = toApplication (route p server)
34−
35−toApplication :: RoutingApplication -> Application
36−toApplication ra request respond = do
37− ra request (routingRespond . routeResult)
38− where
39− routingRespond :: Either RouteMismatch Response -> IO ResponseReceived
40− routingRespond (Left NotFound) =
41− respond $ responseLBS notFound404 [] "not found"
42− routingRespond (Left WrongMethod) =
43− respond $ responseLBS methodNotAllowed405 [] "method not allowed"
44− routingRespond (Left InvalidBody) =
45− respond $ responseLBS badRequest400 [] "Invalid JSON in request body"
46− routingRespond (Right response) =
47− respond response
48−
49−-- * Route mismatch
50−data RouteMismatch =
51− NotFound -- ^ the usual "not found" error
52− | WrongMethod -- ^ a more informative "you just got the HTTP method wrong" error
53− | InvalidBody -- ^ an even more informative "your json request body wasn't valid" error
54− deriving (Eq, Show)
55−
56−-- |
57−-- @
58−-- > mempty = NotFound
59−-- >
60−-- > NotFound `mappend` x = x
61−-- > WrongMethod `mappend` InvalidBody = InvalidBody
62−-- > WrongMethod `mappend` _ = WrongMethod
63−-- > InvalidBody `mappend` _ = InvalidBody
64−-- @
65−instance Monoid RouteMismatch where
66− mempty = NotFound
67−
68− NotFound `mappend` x = x
69− WrongMethod `mappend` InvalidBody = InvalidBody
70− WrongMethod `mappend` _ = WrongMethod
71− InvalidBody `mappend` _ = InvalidBody
72−
73−-- | A wrapper around @'Either' 'RouteMismatch' a@.
74−newtype RouteResult a =
75− RR { routeResult :: Either RouteMismatch a }
76− deriving (Eq, Show)
77−
78−failWith :: RouteMismatch -> RouteResult a
79−failWith = RR . Left
80−
81−succeedWith :: a -> RouteResult a
82−succeedWith = RR . Right
83−
84−isMismatch :: RouteResult a -> Bool
85−isMismatch (RR (Left _)) = True
86−isMismatch _ = False
87−
88−-- | If we get a `Right`, it has precedence over everything else.
89−--
90−-- This in particular means that if we could get several 'Right's,
91−-- only the first we encounter would be taken into account.
92−instance Monoid (RouteResult a) where
93− mempty = RR $ Left mempty
94−
95− RR (Left x) `mappend` RR (Left y) = RR $ Left (x <> y)
96− RR (Left _) `mappend` RR (Right y) = RR $ Right y
97− r `mappend` _ = r
98−
99−type RoutingApplication =
100− Request -- ^ the request, the field 'pathInfo' may be modified by url routing
101− -> (RouteResult Response -> IO ResponseReceived) -> IO ResponseReceived
102−
103−class HasServer layout where
104− type Server layout :: *
105− route :: Proxy layout -> Server layout -> RoutingApplication
src/Servant/Utils/Links.hsdeleted−110
@@ -1,110 +0,0 @@
1−{-# LANGUAGE PolyKinds #-}
2−{-# LANGUAGE DataKinds #-}
3−{-# LANGUAGE FlexibleInstances #-}
4−{-# LANGUAGE TypeFamilies #-}
5−{-# LANGUAGE TypeOperators #-}
6−{-# LANGUAGE FunctionalDependencies #-}
7−{-# LANGUAGE ScopedTypeVariables #-}
8−{-# LANGUAGE UndecidableInstances #-}
9−-- | Type safe internal links.
10−--
11−-- Provides the function 'mkLink':
12−--
13−-- @
14−-- type API = Proxy ("hello" :> Get Int
15−-- :<|> "bye" :> QueryParam "name" String :> Post Bool)
16−--
17−-- api :: API
18−-- api = proxy
19−--
20−-- link1 :: Proxy ("hello" :> Get Int)
21−-- link1 = proxy
22−--
23−-- link2 :: Proxy ("hello" :> Delete)
24−-- link2 = proxy
25−--
26−-- mkLink link1 API -- typechecks, returns 'Link "/hello"'
27−--
28−-- mkLink link2 API -- doesn't typecheck
29−-- @
30−--
31−-- That is, 'mkLink' takes two arguments, a link proxy and a sitemap, and
32−-- returns a 'Link', but only typechecks if the link proxy is a valid link,
33−-- and part of the sitemap.
34−--
35−-- __N.B.:__ 'mkLink' assumes a capture matches any string (without slashes).
36−module Servant.Utils.Links where
37−
38−import Data.Proxy
39−import GHC.TypeLits
40−
41−import Servant.API.Capture
42−import Servant.API.ReqBody
43−import Servant.API.QueryParam
44−import Servant.API.Get
45−import Servant.API.Post
46−import Servant.API.Put
47−import Servant.API.Delete
48−import Servant.API.Sub
49−import Servant.API.Alternative
50−
51−
52−type family Or a b where
53− Or 'False 'False = 'False
54− Or 'True b = 'True
55− Or a 'True = 'True
56−
57−type family And a b where
58− And 'True 'True = 'True
59− And a 'False = 'False
60− And 'False b = 'False
61−
62−type family IsElem a s where
63− IsElem e (sa :<|> sb) = Or (IsElem e sa) (IsElem e sb)
64− IsElem (e :> sa) (e :> sb) = IsElem sa sb
65− IsElem (e :> sa) (Capture x y :> sb) = IsElem sa sb
66− IsElem sa (ReqBody x :> sb) = IsElem sa sb
67− IsElem sa (QueryParam x y :> sb) = IsElem sa sb
68− IsElem e e = 'True
69− IsElem e a = 'False
70−
71−type family IsLink'' l where
72− IsLink'' (e :> Get x) = IsLink' e
73− IsLink'' (e :> Post x) = IsLink' e
74− IsLink'' (e :> Put x) = IsLink' e
75− IsLink'' (e :> Delete) = IsLink' e
76− IsLink'' a = 'False
77−
78−type family IsLink' e where
79− IsLink' (f :: Symbol) = 'True
80−
81−type family IsLink e where
82− IsLink (a :> b) = Or (And (IsLink' a) (IsLink'' b))
83− (IsLink'' (a :> b))
84−
85−
86−-- | The 'ValidLinkIn f s' constraint holds when 's' is an API that
87−-- contains 'f', and 'f' is a link.
88−class ValidLinkIn f s where
89− mkLink :: f -> s -> Link -- ^ This function will only typecheck if `f`
90− -- is an URI within `s`
91−
92−instance ( IsElem f s ~ 'True
93− , IsLink f ~ 'True
94− , VLinkHelper f) => ValidLinkIn f s where
95− mkLink _ _ = Link (vlh (Proxy :: Proxy f))
96−
97−data Link = Link String deriving Show
98−
99−class VLinkHelper f where
100− vlh :: forall proxy. proxy f -> String
101−
102−instance (KnownSymbol s, VLinkHelper e) => VLinkHelper (s :> e) where
103− vlh _ = "/" ++ symbolVal (Proxy :: Proxy s) ++ vlh (Proxy :: Proxy e)
104−
105−instance VLinkHelper (Get x) where
106− vlh _ = ""
107−
108−instance VLinkHelper (Post x) where
109− vlh _ = ""
110−
src/Servant/Utils/StaticFiles.hsdeleted−36
@@ -1,36 +0,0 @@
1−-- | This module defines a sever-side handler that lets you serve static files.
2−--
3−-- - 'serveDirectory' lets you serve anything that lives under a particular
4−-- directory on your filesystem.
5−module Servant.Utils.StaticFiles (
6− serveDirectory,
7− ) where
8−
9−import Filesystem.Path.CurrentOS (decodeString)
10−import Network.Wai.Application.Static
11−import Servant.API.Raw
12−import Servant.Server
13−
14−-- | Serve anything under the specified directory as a 'Raw' endpoint.
15−--
16−-- @
17−-- type MyApi = "static" :> Raw
18−--
19−-- server :: Server MyApi
20−-- server = serveDirectory "\/var\/www"
21−-- @
22−--
23−-- would capture any request to @\/static\/\<something>@ and look for
24−-- @\<something>@ under @\/var\/www@.
25−--
26−-- It will do its best to guess the MIME type for that file, based on the extension,
27−-- and send an appropriate /Content-Type/ header if possible.
28−--
29−-- If your goal is to serve HTML, CSS and Javascript files that use the rest of the API
30−-- as a webapp backend, you will most likely not want the static files to be hidden
31−-- behind a /\/static\// prefix. In that case, remember to put the 'serveDirectory'
32−-- handler in the last position, because /servant/ will try to match the handlers
33−-- in order.
34−serveDirectory :: FilePath -> Server Raw
35−serveDirectory documentRoot =
36− staticApp (defaultFileServerSettings (decodeString (documentRoot ++ "/")))
src/hscolour.cssnew file+5
@@ -0,0 +1,5 @@
1+.hs-keyglyph, .hs-layout {color: red;}
2+.hs-keyword {color: blue;}
3+.hs-comment, .hs-comment a {color: green;}
4+.hs-str, .hs-chr {color: teal;}
5+.hs-keyword, .hs-conid, .hs-varid, .hs-conop, .hs-varop, .hs-num, .hs-cpp, .hs-sel, .hs-definition {}
synopsis.pngnew file

Binary file not shown.

test/Servant/QQSpec.hsdeleted−177
@@ -1,177 +0,0 @@
1−{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE FlexibleInstances #-}
3−{-# LANGUAGE FunctionalDependencies #-}
4−{-# LANGUAGE MultiParamTypeClasses #-}
5−{-# LANGUAGE OverlappingInstances #-}
6−{-# LANGUAGE QuasiQuotes #-}
7−{-# LANGUAGE TypeFamilies #-}
8−{-# LANGUAGE TypeOperators #-}
9−{-# LANGUAGE UndecidableInstances #-}
10−module Servant.QQSpec where
11−
12−import Test.Hspec
13−
14−import Servant.API
15−
16−--------------------------------------------------------------------------
17−-- Types for testing
18−--------------------------------------------------------------------------
19−
20−-- Methods ---------------------------------------------------------------
21−type SimpleGet = [sitemap|
22−GET hello ()
23−|]
24−type SimpleGet' = "hello" :> Get ()
25−type SimpleGet'' = "hello" :> Get Bool
26−
27−type SimpleGet2 = [sitemap|
28−GET hello Bool
29−|]
30−type SimpleGet2' = "hello" :> Get Bool
31−type SimpleGet2'' = "hello" :> Get Int
32−
33−type SimplePost = [sitemap|
34−POST hello ()
35−|]
36−type SimplePost' = "hello" :> Post ()
37−type SimplePost'' = "hello" :> Post Bool
38−
39−type SimplePost2 = [sitemap|
40−POST hello Bool
41−|]
42−type SimplePost2' = "hello" :> Post Bool
43−type SimplePost2'' = "hello" :> Post ()
44−
45−type SimplePut = [sitemap|
46−PUT hello ()
47−|]
48−type SimplePut' = "hello" :> Put ()
49−type SimplePut'' = "hello" :> Put Bool
50−
51−type SimplePut2 = [sitemap|
52−PUT hello Bool
53−|]
54−type SimplePut2' = "hello" :> Put Bool
55−type SimplePut2'' = "hello" :> Put ()
56−
57−-- Parameters ------------------------------------------------------------
58−
59−type SimpleReqBody = [sitemap|
60−POST hello () -> Bool
61−|]
62−type SimpleReqBody' = "hello" :> ReqBody () :> Post Bool
63−type SimpleReqBody'' = "hello" :> ReqBody Bool :> Post ()
64−
65−type SimpleCapture = [sitemap|
66−POST hello/p:Int Bool
67−|]
68−type SimpleCapture' = "hello" :> Capture "p" Int :> Post Bool
69−type SimpleCapture'' = "hello" :> Capture "r" Int :> Post Bool
70−type SimpleCapture''' = "hello" :> Capture "p" Bool :> Post Bool
71−
72−type SimpleQueryParam = [sitemap|
73−POST hello/?p:Int Bool
74−|]
75−type SimpleQueryParam' = "hello" :> QueryParam "p" Int :> Post Bool
76−type SimpleQueryParam'' = "hello" :> QueryParam "r" Int :> Post Bool
77−type SimpleQueryParam''' = "hello" :> QueryParam "p" Bool :> Post Bool
78−
79−-- Combinations ----------------------------------------------------------
80−
81−type TwoPaths = [sitemap|
82−POST hello Bool
83−GET hello Bool
84−|]
85−type TwoPaths' = ("hello" :> Post Bool) :<|> ("hello" :> Get Bool)
86−
87−type WithInlineComments = [sitemap|
88−GET hello Bool -- This is a comment
89−|]
90−type WithInlineComments' = "hello" :> Get Bool
91−
92−type WithInlineComments2 = [sitemap|
93−GET hello Bool
94−-- This is a comment
95−|]
96−type WithInlineComments2' = "hello" :> Get Bool
97−
98−
99−type WithBlockComments = [sitemap|
100−GET hello Bool {-
101−POST hello Bool
102−-}
103−|]
104−type WithBlockComments' = "hello" :> Get Bool
105−
106−type WithBlockComments2 = [sitemap|
107−GET hello Bool {-
108−POST hello Bool
109−-}
110−POST hello Bool
111−|]
112−type WithBlockComments2' = ("hello" :> Get Bool) :<|> ("hello" :> Post Bool)
113−
114−--------------------------------------------------------------------------
115−-- Spec
116−--------------------------------------------------------------------------
117−
118−spec :: Spec
119−spec = do
120− describe "'sitemap' QuasiQuoter" $ do
121− it "Handles simple GET types" $ do
122− (u::SimpleGet) ~= (u::SimpleGet' ) ~> True
123− (u::SimpleGet) ~= (u::SimpleGet'' ) ~> False
124− (u::SimpleGet2) ~= (u::SimpleGet2' ) ~> True
125− (u::SimpleGet2) ~= (u::SimpleGet2'') ~> False
126− it "Handles simple POST types" $ do
127− (u::SimplePost) ~= (u::SimplePost' ) ~> True
128− (u::SimplePost) ~= (u::SimplePost'' ) ~> False
129− (u::SimplePost2) ~= (u::SimplePost2' ) ~> True
130− (u::SimplePost2) ~= (u::SimplePost2'') ~> False
131− it "Handles simple PUT types" $ do
132− (u::SimplePut) ~= (u::SimplePut' ) ~> True
133− (u::SimplePut) ~= (u::SimplePut'' ) ~> False
134− (u::SimplePut2) ~= (u::SimplePut2' ) ~> True
135− (u::SimplePut2) ~= (u::SimplePut2'') ~> False
136− it "Handles simple request body types" $ do
137− (u::SimpleReqBody) ~= (u::SimpleReqBody' ) ~> True
138− (u::SimpleReqBody) ~= (u::SimpleReqBody'') ~> False
139− it "Handles simple captures" $ do
140− (u::SimpleCapture) ~= (u::SimpleCapture' ) ~> True
141− (u::SimpleCapture) ~= (u::SimpleCapture'') ~> False
142− (u::SimpleCapture) ~= (u::SimpleCapture''') ~> False
143− it "Handles simple querystring parameters" $ do
144− (u::SimpleQueryParam) ~= (u::SimpleQueryParam' ) ~> True
145− (u::SimpleQueryParam) ~= (u::SimpleQueryParam'') ~> False
146− (u::SimpleQueryParam) ~= (u::SimpleQueryParam''') ~> False
147− it "Handles multiples paths" $ do
148− (u::TwoPaths) ~= (u::TwoPaths') ~> True
149− it "Ignores inline comments" $ do
150− (u::WithInlineComments) ~= (u::WithInlineComments') ~> True
151− (u::WithInlineComments2) ~= (u::WithInlineComments2') ~> True
152− it "Ignores inline comments" $ do
153− (u::WithBlockComments) ~= (u::WithBlockComments') ~> True
154− (u::WithBlockComments2) ~= (u::WithBlockComments2') ~> True
155−
156−
157−--------------------------------------------------------------------------
158−-- Utilities
159−--------------------------------------------------------------------------
160−data HTrue
161−data HFalse
162−
163−-- Kiselyov's Type Equality predicate
164−class TypeEq x y b | x y -> b where { areEq :: x -> y -> Bool }
165−instance TypeEq x x HTrue where { areEq _ _ = True }
166−instance b ~ HFalse => TypeEq x y b where { areEq _ _ = False}
167−
168−infix 4 ~=
169−(~=) :: TypeEq x y b => x -> y -> Bool
170−(~=) = areEq
171−
172−u :: a
173−u = undefined
174−
175−infix 3 ~>
176−(~>) :: (Show a, Eq a) => a -> a -> Expectation
177−(~>) = shouldBe
test/Servant/ServerSpec.hsdeleted−258
@@ -1,258 +0,0 @@
1−{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE DeriveGeneric #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−{-# LANGUAGE QuasiQuotes #-}
5−{-# LANGUAGE ScopedTypeVariables #-}
6−{-# LANGUAGE TypeOperators #-}
7−
8−module Servant.ServerSpec where
9−
10−
11−import Control.Monad.Trans.Either
12−import Data.Aeson
13−import Data.Char
14−import Data.Proxy
15−import Data.String
16−import Data.String.Conversions
17−import GHC.Generics
18−import Network.HTTP.Types
19−import Network.Wai
20−import Network.Wai.Test
21−import Test.Hspec
22−import Test.Hspec.Wai
23−
24−import Servant.API.Capture
25−import Servant.API.Get
26−import Servant.API.ReqBody
27−import Servant.API.Post
28−import Servant.API.QueryParam
29−import Servant.API.Raw
30−import Servant.API.Sub
31−import Servant.API.Alternative
32−import Servant.Server
33−
34−
35−-- * test data types
36−
37−data Person = Person {
38− name :: String,
39− age :: Integer
40− }
41− deriving (Eq, Show, Generic)
42−
43−instance ToJSON Person
44−instance FromJSON Person
45−
46−alice :: Person
47−alice = Person "Alice" 42
48−
49−data Animal = Animal {
50− species :: String,
51− numberOfLegs :: Integer
52− }
53− deriving (Eq, Show, Generic)
54−
55−instance ToJSON Animal
56−instance FromJSON Animal
57−
58−jerry :: Animal
59−jerry = Animal "Mouse" 4
60−
61−tweety :: Animal
62−tweety = Animal "Bird" 2
63−
64−
65−-- * specs
66−
67−spec :: Spec
68−spec = do
69− captureSpec
70− getSpec
71− queryParamSpec
72− postSpec
73− rawSpec
74− unionSpec
75−
76−
77−type CaptureApi = Capture "legs" Integer :> Get Animal
78−captureApi :: Proxy CaptureApi
79−captureApi = Proxy
80−captureServer :: Integer -> EitherT (Int, String) IO Animal
81−captureServer legs = case legs of
82− 4 -> return jerry
83− 2 -> return tweety
84− _ -> left (404, "not found")
85−
86−captureSpec :: Spec
87−captureSpec = do
88− describe "Servant.API.Capture" $ do
89− with (return (serve captureApi captureServer)) $ do
90− it "can capture parts of the 'pathInfo'" $ do
91− response <- get "/2"
92− liftIO $ do
93− decode' (simpleBody response) `shouldBe` Just tweety
94−
95− with (return (serve
96− (Proxy :: Proxy (Capture "captured" String :> Raw))
97− (\ "captured" request respond ->
98− respond $ responseLBS ok200 [] (cs $ show $ pathInfo request)))) $ do
99− it "strips the captured path snippet from pathInfo" $ do
100− get "/captured/foo" `shouldRespondWith` (fromString (show ["foo" :: String]))
101−
102−
103−type GetApi = Get Person
104−getApi :: Proxy GetApi
105−getApi = Proxy
106−
107−getSpec :: Spec
108−getSpec = do
109− describe "Servant.API.Get" $ do
110− with (return (serve getApi (return alice))) $ do
111− it "allows to GET a Person" $ do
112− response <- get "/"
113− return response `shouldRespondWith` 200
114− liftIO $ do
115− decode' (simpleBody response) `shouldBe` Just alice
116−
117− it "throws 405 (wrong method) on POSTs" $ do
118− post "/" "" `shouldRespondWith` 405
119−
120−
121−type QueryParamApi = QueryParam "name" String :> Get Person
122− :<|> "a" :> QueryParams "names" String :> Get Person
123− :<|> "b" :> QueryFlag "capitalize" :> Get Person
124−
125−queryParamApi :: Proxy QueryParamApi
126−queryParamApi = Proxy
127−
128−qpServer :: Server QueryParamApi
129−qpServer = queryParamServer :<|> qpNames :<|> qpCapitalize
130−
131− where qpNames (_:name2:_) = return alice { name = name2 }
132− qpNames _ = return alice
133−
134− qpCapitalize False = return alice
135− qpCapitalize True = return alice { name = map toUpper (name alice) }
136−
137− queryParamServer (Just name) = return alice{name = name}
138− queryParamServer Nothing = return alice
139−
140−queryParamSpec :: Spec
141−queryParamSpec = do
142− describe "Servant.API.QueryParam" $ do
143− it "allows to retrieve simple GET parameters" $
144− (flip runSession) (serve queryParamApi qpServer) $ do
145− let params1 = "?name=bob"
146− response1 <- Network.Wai.Test.request defaultRequest{
147− rawQueryString = params1,
148− queryString = parseQuery params1
149− }
150− liftIO $ do
151− decode' (simpleBody response1) `shouldBe` Just alice{
152− name = "bob"
153− }
154−
155− it "allows to retrieve lists in GET parameters" $
156− (flip runSession) (serve queryParamApi qpServer) $ do
157− let params2 = "?names[]=bob&names[]=john"
158− response2 <- Network.Wai.Test.request defaultRequest{
159− rawQueryString = params2,
160− queryString = parseQuery params2,
161− pathInfo = ["a"]
162− }
163− liftIO $
164− decode' (simpleBody response2) `shouldBe` Just alice{
165− name = "john"
166− }
167−
168− it "allows to retrieve value-less GET parameters" $
169− (flip runSession) (serve queryParamApi qpServer) $ do
170− let params3 = "?capitalize"
171− response3 <- Network.Wai.Test.request defaultRequest{
172− rawQueryString = params3,
173− queryString = parseQuery params3,
174− pathInfo = ["b"]
175− }
176− liftIO $
177− decode' (simpleBody response3) `shouldBe` Just alice{
178− name = "ALICE"
179− }
180−
181− let params3' = "?capitalize="
182− response3' <- Network.Wai.Test.request defaultRequest{
183− rawQueryString = params3',
184− queryString = parseQuery params3',
185− pathInfo = ["b"]
186− }
187− liftIO $
188− decode' (simpleBody response3') `shouldBe` Just alice{
189− name = "ALICE"
190− }
191−
192−type PostApi = ReqBody Person :> Post Integer
193−postApi :: Proxy PostApi
194−postApi = Proxy
195−
196−postSpec :: Spec
197−postSpec = do
198− describe "Servant.API.Post and .ReqBody" $ do
199− with (return (serve postApi (return . age))) $ do
200− it "allows to POST a Person" $ do
201− post "/" (encode alice) `shouldRespondWith` "42"{
202− matchStatus = 201
203− }
204−
205− it "correctly rejects invalid request bodies with status 400" $ do
206− post "/" "some invalid body" `shouldRespondWith` 400
207−
208−
209−type RawApi = "foo" :> Raw
210−rawApi :: Proxy RawApi
211−rawApi = Proxy
212−rawApplication :: Show a => (Request -> a) -> Application
213−rawApplication f request respond = respond $ responseLBS ok200 [] (cs $ show $ f request)
214−
215−rawSpec :: Spec
216−rawSpec = do
217− describe "Servant.API.Raw" $ do
218− it "runs applications" $ do
219− (flip runSession) (serve rawApi (rawApplication (const (42 :: Integer)))) $ do
220− response <- Network.Wai.Test.request defaultRequest{
221− pathInfo = ["foo"]
222− }
223− liftIO $ do
224− simpleBody response `shouldBe` "42"
225−
226− it "gets the pathInfo modified" $ do
227− (flip runSession) (serve rawApi (rawApplication pathInfo)) $ do
228− response <- Network.Wai.Test.request defaultRequest{
229− pathInfo = ["foo", "bar"]
230− }
231− liftIO $ do
232− simpleBody response `shouldBe` cs (show ["bar" :: String])
233−
234−
235−type AlternativeApi =
236− "foo" :> Get Person
237− :<|> "bar" :> Get Animal
238−unionApi :: Proxy AlternativeApi
239−unionApi = Proxy
240−
241−unionServer :: Server AlternativeApi
242−unionServer =
243− return alice
244− :<|> return jerry
245−
246−unionSpec :: Spec
247−unionSpec = do
248− describe "Servant.API.Alternative" $ do
249− with (return $ serve unionApi unionServer) $ do
250− it "unions endpoints" $ do
251− response <- get "/foo"
252− liftIO $ do
253− decode' (simpleBody response) `shouldBe`
254− Just alice
255− response <- get "/bar"
256− liftIO $ do
257− decode' (simpleBody response) `shouldBe`
258− Just jerry
test/Servant/Utils/LinksSpec.hsdeleted−52
@@ -1,52 +0,0 @@
1−{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE PolyKinds #-}
3−{-# LANGUAGE TypeOperators #-}
4−module Servant.Utils.LinksSpec where
5−
6−import Test.Hspec
7−
8−import Servant.API
9−import Servant.QQSpec ( (~>) )
10−import Servant.Utils.Links (IsElem, IsLink)
11−
12−type TestApi =
13− "hello" :> Capture "name" String :> QueryParam "capital" Bool :> Get Bool
14− :<|> "greet" :> ReqBody 'True :> Post Bool
15−
16−type TestLink = "hello" :> "hi" :> Get Bool
17−type TestLink2 = "greet" :> Post Bool
18−
19−type BadTestLink = "hallo" :> "hi" :> Get Bool
20−type BadTestLink2 = "greet" :> Get Bool
21−
22−type NotALink = "hello" :> Capture "x" Bool :> Get Bool
23−type NotALink2 = "hello" :> ReqBody 'True :> Get Bool
24−
25−data Proxy x = Proxy
26−class ReflectT (x::Bool) where { reflected :: Proxy x -> Bool }
27−instance ReflectT 'True where { reflected _ = True }
28−instance ReflectT 'False where { reflected _ = False }
29−
30−spec :: Spec
31−spec = describe "Servant.API.Elem" $ do
32− isElem
33− isLink
34−
35−isElem :: Spec
36−isElem = describe "IsElem" $ do
37− it "is True when the first argument is an url within the second" $ do
38− reflected (Proxy::Proxy (IsElem TestLink TestApi)) ~> True
39− reflected (Proxy::Proxy (IsElem TestLink2 TestApi)) ~> True
40− it "is False when the first argument is not an url within the second" $ do
41− reflected (Proxy::Proxy (IsElem BadTestLink TestApi)) ~> False
42− reflected (Proxy::Proxy (IsElem BadTestLink2 TestApi)) ~> False
43−
44−isLink :: Spec
45−isLink = describe "IsLink" $ do
46− it "is True when all Subs are paths and the last is a method" $ do
47− reflected (Proxy::Proxy (IsLink TestLink)) ~> True
48− reflected (Proxy::Proxy (IsLink TestLink2)) ~> True
49− it "is False of anything with captures" $ do
50− reflected (Proxy::Proxy (IsLink NotALink)) ~> False
51− reflected (Proxy::Proxy (IsLink NotALink2)) ~> False
52−
test/Servant/Utils/StaticFilesSpec.hsdeleted−64
@@ -1,64 +0,0 @@
1−{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE FlexibleInstances #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−{-# LANGUAGE TypeOperators #-}
5−{-# OPTIONS_GHC -fno-warn-orphans #-}
6−module Servant.Utils.StaticFilesSpec where
7−
8−import Control.Exception
9−import Data.Proxy
10−import Network.Wai
11−import System.Directory
12−import System.IO.Temp
13−import Test.Hspec hiding (pending)
14−import Test.Hspec.Wai
15−
16−import Servant.API.Alternative
17−import Servant.API.Capture
18−import Servant.API.Get
19−import Servant.API.Raw
20−import Servant.API.Sub
21−import Servant.Server
22−import Servant.ServerSpec
23−import Servant.Utils.StaticFiles
24−
25−type Api =
26− "dummy_api" :> Capture "person_name" String :> Get Person
27− :<|> "static" :> Raw
28−
29−
30−api :: Proxy Api
31−api = Proxy
32−
33−app :: Application
34−app = serve api server
35−
36−server :: Server Api
37−server =
38− (\ name -> return (Person name 42))
39− :<|> serveDirectory "static"
40−
41−withStaticFiles :: IO () -> IO ()
42−withStaticFiles action = withSystemTempDirectory "servant-test" $ \ tmpDir ->
43− bracket (setup tmpDir) teardown (const action)
44− where
45− setup tmpDir = do
46− outer <- getCurrentDirectory
47− setCurrentDirectory tmpDir
48− createDirectory "static"
49− writeFile "static/foo.txt" "bar"
50− writeFile "static/index.html" "index"
51− return outer
52−
53− teardown outer = do
54− setCurrentDirectory outer
55−
56−spec :: Spec
57−spec = do
58− around_ withStaticFiles $ with (return app) $ do
59− describe "serveDirectory" $ do
60− it "successfully serves files" $ do
61− get "/static/foo.txt" `shouldRespondWith` "bar"
62−
63− it "serves the contents of index.html when requesting the root of a directory" $ do
64− get "/static" `shouldRespondWith` "index"
test/Spec.hsdeleted−1
@@ -1 +0,0 @@
1−{-# OPTIONS_GHC -F -pgmF hspec-discover #-}