packages feed

Ketchup 0.2.3 → 0.3

raw patch · 114 files changed

+2002/−86 lines, 114 filesdep +base64-bytestringdep −containersbinary-addedPVP ok

version bump matches the API change (PVP)

Dependencies added: base64-bytestring

Dependencies removed: containers

API changes (from Hackage documentation)

- Ketchup.Routing: type Parameters = Map ByteString ByteString
+ Ketchup.Utils: fallback :: Maybe a -> a -> a
- Ketchup.Httpd: type Headers = Map ByteString [ByteString]
+ Ketchup.Httpd: type Headers = [(ByteString, [ByteString])]
- Ketchup.Routing: type Route = Socket -> HTTPRequest -> Parameters -> IO ()
+ Ketchup.Routing: type Route = Socket -> HTTPRequest -> (ByteString -> Maybe ByteString) -> IO ()
- Ketchup.Utils: parseBody :: ByteString -> Map ByteString ByteString
+ Ketchup.Utils: parseBody :: ByteString -> [(ByteString, ByteString)]

Files

.git/COMMIT_EDITMSG view
@@ -1,1 +1,15 @@-Fixed chunked encoding not working+Version bump+# Please enter the commit message for your changes. Lines starting+# with '#' will be ignored, and an empty message aborts the commit.+# On branch master+# Your branch is ahead of 'origin/master' by 2 commits.+#   (use "git push" to publish your local commits)+#+# Changes to be committed:+#	modified:   Ketchup.cabal+#	modified:   README.md+#+# Untracked files:+#	.gitignore~+#	gendocs.sh~+#
.git/index view

binary file changed (976 → 1136 bytes)

.git/logs/HEAD view
@@ -20,3 +20,7 @@ a71ae79e4cf33baeecab2eeecf21ae31d35dd99f 0ef1467fc037c2b698808c4f8670b06f437a44c5 Hamcha <zikyky@gmail.com> 1402152846 +0200	commit: Updated readme 0ef1467fc037c2b698808c4f8670b06f437a44c5 b83c2375bba608232746064adfdb067cf57e5d80 Hamcha <zikyky@gmail.com> 1402175260 +0200	commit: Static doesn't depend on Routing anymore b83c2375bba608232746064adfdb067cf57e5d80 4ad51f9dc87b6aa48cb614030521d957b8498622 Hamcha <zikyky@gmail.com> 1403296411 +0200	commit: Fixed chunked encoding not working+4ad51f9dc87b6aa48cb614030521d957b8498622 f61d5b2caadecbdcf54d2d0ad7b131ca2adcdc28 Hamcha <zikyky@gmail.com> 1404003509 +0200	commit: Version bump + GenDoc script+f61d5b2caadecbdcf54d2d0ad7b131ca2adcdc28 139041d9f25f891c340cc0b858838f94306c9b93 Hamcha <zikyky@gmail.com> 1404078079 +0200	commit: So long Data.Map (and "containers" dependency)+139041d9f25f891c340cc0b858838f94306c9b93 0f03ed98a2eba1beb8db11eb86edb34b2321a261 Hamcha <zikyky@gmail.com> 1404079631 +0200	commit: Basic auth is in!+0f03ed98a2eba1beb8db11eb86edb34b2321a261 0fd36c65d057f7ce244a4e9a335d698f075530e6 Hamcha <zikyky@gmail.com> 1404079677 +0200	commit: Version bump
.git/logs/refs/heads/master view
@@ -20,3 +20,7 @@ a71ae79e4cf33baeecab2eeecf21ae31d35dd99f 0ef1467fc037c2b698808c4f8670b06f437a44c5 Hamcha <zikyky@gmail.com> 1402152846 +0200	commit: Updated readme 0ef1467fc037c2b698808c4f8670b06f437a44c5 b83c2375bba608232746064adfdb067cf57e5d80 Hamcha <zikyky@gmail.com> 1402175260 +0200	commit: Static doesn't depend on Routing anymore b83c2375bba608232746064adfdb067cf57e5d80 4ad51f9dc87b6aa48cb614030521d957b8498622 Hamcha <zikyky@gmail.com> 1403296411 +0200	commit: Fixed chunked encoding not working+4ad51f9dc87b6aa48cb614030521d957b8498622 f61d5b2caadecbdcf54d2d0ad7b131ca2adcdc28 Hamcha <zikyky@gmail.com> 1404003509 +0200	commit: Version bump + GenDoc script+f61d5b2caadecbdcf54d2d0ad7b131ca2adcdc28 139041d9f25f891c340cc0b858838f94306c9b93 Hamcha <zikyky@gmail.com> 1404078079 +0200	commit: So long Data.Map (and "containers" dependency)+139041d9f25f891c340cc0b858838f94306c9b93 0f03ed98a2eba1beb8db11eb86edb34b2321a261 Hamcha <zikyky@gmail.com> 1404079631 +0200	commit: Basic auth is in!+0f03ed98a2eba1beb8db11eb86edb34b2321a261 0fd36c65d057f7ce244a4e9a335d698f075530e6 Hamcha <zikyky@gmail.com> 1404079677 +0200	commit: Version bump
.git/logs/refs/remotes/origin/master view
@@ -19,3 +19,5 @@ a71ae79e4cf33baeecab2eeecf21ae31d35dd99f 0ef1467fc037c2b698808c4f8670b06f437a44c5 Hamcha <zikyky@gmail.com> 1402152850 +0200	update by push 0ef1467fc037c2b698808c4f8670b06f437a44c5 b83c2375bba608232746064adfdb067cf57e5d80 Hamcha <zikyky@gmail.com> 1402175263 +0200	update by push b83c2375bba608232746064adfdb067cf57e5d80 4ad51f9dc87b6aa48cb614030521d957b8498622 Hamcha <zikyky@gmail.com> 1403296415 +0200	update by push+4ad51f9dc87b6aa48cb614030521d957b8498622 f61d5b2caadecbdcf54d2d0ad7b131ca2adcdc28 Hamcha <zikyky@gmail.com> 1404003524 +0200	update by push+f61d5b2caadecbdcf54d2d0ad7b131ca2adcdc28 0fd36c65d057f7ce244a4e9a335d698f075530e6 Hamcha <zikyky@gmail.com> 1404079685 +0200	update by push
+ .git/objects/0f/03ed98a2eba1beb8db11eb86edb34b2321a261 view

binary file changed (absent → 160 bytes)

+ .git/objects/0f/d36c65d057f7ce244a4e9a335d698f075530e6 view
@@ -0,0 +1,3 @@+x•ŽA+Â0E]÷ْ™„$—žÀýL2µ¥¦)5]Ôӛ+¸úðßðcÉyª+NuQƋOäZh"jGž{ÖFú€1¡À0$qЭ´ÉR•J} &`ᐠ…“ÄÆ2¶§½ŽeSÊq$uýNó1÷W¦é}‰%ßXmµï÷ê¬Q뮵íZ•¿¤î)Ûg*‹â=¯Ý÷¥BÆ
+ .git/objects/13/9041d9f25f891c340cc0b858838f94306c9b93 view
@@ -0,0 +1,2 @@+x•ÎANÃ0FaÖ>Ũ+Re'v¤+±`Á†'ø=3i£ÖvÌ"œž^í“>éq+eéäÃðÐ7U’ÉÈhه˜Ø
\ÌyÎP9ƒçœ¦1™›ÖNóèdȞQÎÂóċ…Äì^ÃCXØ'ƒŸ~i} ðtú]®ûu;,·#·òJ.Ø`c²q¢gë­5÷z_ëú/d¾ÝZ=Ó;:ŽŸXéUèÀ­v,U·ï‰®ZE+ïOæøP
+ .git/objects/26/e2203e22a0c92e9fffb7c8d859af54bf1aa943 view

binary file changed (absent → 319 bytes)

+ .git/objects/2d/61778b316db7774bc73d9c80cfa8d76e7b7a97 view

binary file changed (absent → 980 bytes)

+ .git/objects/32/997e49181fa65740bdf9434d98e8f146601d75 view

binary file changed (absent → 682 bytes)

+ .git/objects/35/5acd3fb38dd6a8565e8652aca975260ad9ebe4 view

binary file changed (absent → 918 bytes)

+ .git/objects/37/e7da68243123c206a7b9b03e982cd2e1ffde61 view

binary file changed (absent → 320 bytes)

+ .git/objects/38/b1abd98d5569fa06054273349167b45184cc6c view

binary file changed (absent → 682 bytes)

+ .git/objects/3e/acc9c75ba313c63d9d9be3616d7b8b9f452975 view

binary file changed (absent → 98 bytes)

+ .git/objects/41/c17d736e3d73852a7d08c691182692e793ab3f view

binary file changed (absent → 320 bytes)

+ .git/objects/4a/10a87d8c968f4d836bca3a08d2f44c05060fad view

binary file changed (absent → 320 bytes)

+ .git/objects/60/07e4f98c57a347a051cf7d7de71ca08fd85b8f view

binary file changed (absent → 1432 bytes)

+ .git/objects/78/b20a019fafabb14b2745db2c5912176729df2c view

binary file changed (absent → 179 bytes)

+ .git/objects/82/8e849a50ad7d3abf4afe0cc48a2b68512310cb view
@@ -0,0 +1,1 @@+x}RQkÛ0Þ³ÁÿáP÷€®P¶QÚBÜm
¬l¡MÈCæb]f,9Ò¹]Öî¿O²;×-cz:ÝÝ÷Ý÷´QfïÞ¿ºOàjúår9½ü_oÑ*ʲRÿppþŽ£8ªŒhÂg¤¢lêÉ´¡2ŽF°áNÝew%ZͲª%Ø5\É­D8ñI¶'ìX'%·ï;ÈúfèÏß3¢Zü§¾$©\—¦ð0G»5¶r0[,æYÐéê%ÂÉ	¬GÙ@GÃÛ8Ïô®¤#0[-ZÍ+L`Ν»3VŒã¨—	éù3øS¡Zº 5ɂ“4®‘«ê͌k¡Ðö¸AKsÓ:ï¯ëý7C=¹-LS+t`Ã@pðRŸÙÁÓqÔþ	^C‰þÙmèßu‡Z\c­ö@ÇoŽüöØjµJސ%°æÞá'‰JäÏö3t‘ŒØ…Ñä÷.öu‹b„?é°¤J±|œýì´<:³—:Œ1VþBqz蓬ƒ<~º€éuxwÙ¤0Ú¯Ö¬ûíξ1–´QÂ|˜ÿž ڜ
+ .git/objects/84/bf304493959e3a08b3807bd704ec632a9fb8a9 view

binary file changed (absent → 905 bytes)

+ .git/objects/8b/beae61080d264f5b69734128be1ecea8d6bfd4 view

binary file changed (absent → 604 bytes)

+ .git/objects/9a/6ebc14c4c86e50b3654d62c33ed7d83351c524 view

binary file changed (absent → 762 bytes)

+ .git/objects/b3/591481b033fac241826b9fc64a51d925d71175 view

binary file changed (absent → 615 bytes)

+ .git/objects/b9/eb5d552bfc0adee1044e395991edcfd292826b view

binary file changed (absent → 978 bytes)

+ .git/objects/c2/d02249f1afb2578f5af2fcdfab5bcfbdcdb2e4 view

binary file changed (absent → 60 bytes)

+ .git/objects/d9/14ad60c2478c15e417bbfbae1ae6cbacfb8968 view

binary file changed (absent → 320 bytes)

+ .git/objects/da/f5ffbd0e64b1c1405b2bc670dd396d9c544a14 view

binary file changed (absent → 208 bytes)

+ .git/objects/de/93e13807a1416af9226a89e7292c83ca984bb0 view

binary file changed (absent → 1323 bytes)

+ .git/objects/eb/a023660b513baa6686d113b0d5108a83448e4a view

binary file changed (absent → 207 bytes)

+ .git/objects/f6/1d5b2caadecbdcf54d2d0ad7b131ca2adcdc28 view

binary file changed (absent → 172 bytes)

.git/refs/heads/master view
@@ -1,1 +1,1 @@-4ad51f9dc87b6aa48cb614030521d957b8498622+0fd36c65d057f7ce244a4e9a335d698f075530e6
.git/refs/remotes/origin/master view
@@ -1,1 +1,1 @@-4ad51f9dc87b6aa48cb614030521d957b8498622+0fd36c65d057f7ce244a4e9a335d698f075530e6
.gitignore view
@@ -3,4 +3,3 @@ example
 dist
 docs
-gendocs.sh
.gitignore~ view
@@ -3,3 +3,4 @@ example
 dist
 docs
+gendocs.sh
Ketchup.cabal view
@@ -1,5 +1,5 @@ Name:           Ketchup
-Version:        0.2.3
+Version:        0.3
 Cabal-Version:  >= 1.6
 Build-Type:     Simple
 License:        MIT
@@ -10,7 +10,7 @@ Category:       Web, Ketchup
 Synopsis:       A super small web framework for those who don't like big and fancy codebases
 Description:
-    Ketchup is a very small HTTP server implementation, currently under 300 LoC total!
+    Ketchup is a very small HTTP server implementation, currently under 400 LoC total!
     .
     Ketchup is also made to be as modular and embeddable as possible, if you want a cabal-free Haskell app, just take those two/three files you need and put it in your project!
     .
@@ -22,7 +22,17 @@     .
     * Static file handler (ie. \`static \".\"\` as route/handler)
     .
-    Most of the project is dependency-free and only uses stuff included in Prelude, with the exception of Ketchup.Static who uses the mime-types package from Hackage, which is a single separately downloadable file.
+    Dependencies
+    .
+    The core parts of Ketchup are all depedency free, that includes Ketchup.Httpd and Ketchup.Utils (and to a certain extent, Ketchup.Chunked).
+    The dependencies required are for the following modules:
+    .
+    * Ketchup.Routing (uses regex-pcre-builtin, This can ben modified to use builtin POSIX regexp)
+    .
+    * Ketchup.Static (uses mime-types)
+    .
+    * Ketchup.Auth (uses base64-bytestring)
+    .
 
 Extra-Source-Files:
   example.hs,
@@ -39,8 +49,8 @@ 
   Build-Depends:
     base               ==4.*,
+    base64-bytestring   <1.1.0.0,
     bytestring         >=0.9 && <0.11,
-    containers         >=0.2 && <0.6,
     directory           <1.3,
     mime-types          <0.2,
     network             <2.5,
Ketchup/Auth.hs view
@@ -5,6 +5,33 @@ ) where
 
 import qualified Data.ByteString.Char8 as B
+import qualified Data.ByteString.Base64 as B64
+import           Ketchup.Httpd
 import           Ketchup.Utils
 
-basicAuth :: B.ByteString -> Handler+-- |Performs HTTP Basic Auth
+basicAuth :: [(B.ByteString, B.ByteString)] -- ^ List of (Username, Password)
+          -> B.ByteString                   -- ^ Authentication Realm
+          -> Handler                        -- ^ Success Handler
+          -> Handler
+basicAuth couples realm success hnd req =
+    case authHead of
+        Nothing -> fail
+        Just x  -> case authData `elem` couples of
+                       False -> fail
+                       True  -> success hnd req
+                   where
+                   authData = parseAuth $ x !! 0
+    where
+    authHead = lookup "Authorization" $ headers req
+    authField = B.concat ["Basic realm=\"",realm,"\""]
+    fail = sendReply hnd 401 [("WWW-Authenticate", [authField])
+                             ,("Content-Type", ["text/html"])]
+                             "<h1>401 Unauthorized</h1>"
+
+parseAuth :: B.ByteString -> (B.ByteString, B.ByteString)
+parseAuth authStr =
+    breakBS ":" $ B64.decodeLenient authData
+    where
+    authData = snd parts
+    parts = breakBS " " authStr
− Ketchup/Chunked.hs~
@@ -1,46 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}
-
-module Ketchup.Chunked
-( chunkHeaders
-, chunk
-, endchunk
-) where
-
-import qualified Data.ByteString.Char8 as B
-import qualified Data.List as List
-import           Ketchup.Httpd
-import           Ketchup.Utils
-import           Network
-import           Network.Socket.ByteString
-import           Numeric
-
--- |Send HTTP reply headers and begin a Chunked transmission
-chunkHeaders :: Socket                           -- ^ Socket to write to
-             -> Int                              -- ^ Status code
-             -> [(B.ByteString, [B.ByteString])] -- ^ Headers
-             -> IO ()
-chunkHeaders handle status headers = do
-    sendAll handle content
-    where
-    content = B.concat ["HTTP/1.1 ", statusMsg status, "\r\n\
-        \Connection: close\r\n",heads,"\r\n\
-        \Transfer-Encoding: chunked\r\n\r\n"]
-    heads = B.concat $ map toHeader headers
-    toHeader x = B.concat [fst x, ": "
-                          ,B.concat $ List.intersperse "," $ snd x
-                          ,"\r\n"]
-
--- |Sends a chunk
-chunk :: Socket       -- ^ Socket to write to
-      -> B.ByteString -- ^ Content to write
-      -> IO ()
-chunk handle value =
-    sendAll handle content
-    where
-    content = B.concat [B.pack $ showHex (B.length value) "",
-                        "\r\n", value, "\r\n"]
-
--- |Send the final/closing chunk
-endchunk :: Socket -- ^ Socket to write to
-         -> IO ()
-endchunk handle = sendAll handle "0\r\n\r\n"
Ketchup/Httpd.hs view
@@ -9,13 +9,12 @@ 
 import           Control.Concurrent (forkIO)
 import qualified Data.ByteString.Char8 as B
-import qualified Data.Map as Map
 import           Network
 import qualified Network.Socket as NS
 import           Network.Socket.ByteString
 import           Ketchup.Utils
 
-type Headers  = Map.Map B.ByteString [B.ByteString]
+type Headers  = [(B.ByteString, [B.ByteString])]
 type Handler  = Socket -> HTTPRequest -> IO ()
 
 -- |HTTP Request type
@@ -58,7 +57,7 @@     HTTPRequest { method=met, uri=ur, httpver=ver, headers=heads, body=body }
     where
     [met, ur, ver] = B.words $ head headers -- First line is METHOD URI VERSION
-    heads   = Map.fromList $ map parseRequestLine $ tail headers
+    heads   = map parseRequestLine $ tail headers
     body    = snd reqlines
     headers = fst reqlines
 
Ketchup/Routing.hs view
@@ -2,20 +2,17 @@ 
 module Ketchup.Routing
 ( Route      (..)
-, Parameters (..)
 , route
 , useHandler
 ) where
 
 import qualified Data.ByteString.Char8 as B
-import qualified Data.Map as M
 import           Ketchup.Httpd
 import           Ketchup.Utils
 import           Network
 import qualified Text.Regex.PCRE as R
 
-type Parameters = M.Map B.ByteString B.ByteString
-type Route = Socket -> HTTPRequest -> Parameters -> IO ()
+type Route = Socket -> HTTPRequest -> (B.ByteString -> Maybe B.ByteString) -> IO ()
 
 -- |Router function
 -- Takes a list of routes and iterates through them for every requeust
@@ -45,14 +42,15 @@     urlparts = B.split '/' url
     tmpparts = B.split '/' template
 
-params :: B.ByteString -> B.ByteString -> Parameters
-params url template =
-    M.fromList $ filter (not . B.null . fst) $
-        zipWith retrieve urlparts tmpparts
+params :: B.ByteString -> B.ByteString -> B.ByteString -> Maybe B.ByteString
+params url template name =
+    lookup name list
     where
+    list = filter (not . B.null . fst) $
+               zipWith retrieve urlparts tmpparts
     retrieve x y
         | or [B.null y, B.null x] = ("","")
         | B.head y == ':'         = (B.tail y, x)
         | otherwise               = ("","")
     urlparts = B.split '/' url
-    tmpparts = B.split '/' template
+    tmpparts = B.split '/' template
Ketchup/Utils.hs view
@@ -3,6 +3,7 @@ module Ketchup.Utils
 ( trim
 , breakBS
+, fallback
 , parseBody
 , sendReply
 , sendBadRequest
@@ -13,7 +14,6 @@ import qualified Data.ByteString.Char8 as B
 import           Data.Char (isSpace)
 import qualified Data.List as List
-import qualified Data.Map  as Map
 import           Network
 import           Network.Socket.ByteString
 
@@ -28,6 +28,8 @@     | stat == 204 = "204 No Content"
     -- 400 Client Errors
     | stat == 400 = "400 Bad Request"
+    | stat == 401 = "401 Unauthorized"
+    | stat == 402 = "402 Payment Required"
     | stat == 403 = "403 Forbidden"
     | stat == 404 = "404 Not Found"
     | stat == 405 = "405 Method Not Allowed"
@@ -86,5 +88,9 @@     broke  = B.breakSubstring delimiter source
 
 -- |Parse a URL-encoded Request
-parseBody :: B.ByteString -> Map.Map B.ByteString B.ByteString
-parseBody body = Map.fromList $ map (breakBS "=") $ B.split '&' body+parseBody :: B.ByteString -> [(B.ByteString, B.ByteString)]
+parseBody body = map (breakBS "=") $ B.split '&' body
+
+fallback :: Maybe a -> a -> a
+fallback (Just value) fallback = value
+fallback Nothing      fallback = fallback
README.md view
@@ -1,6 +1,6 @@ # Howdy, this is Ketchup!
 
-Ketchup is a very small HTTP server implementation, currently [under 300 LoC total](http://ix.io/cQM)!
+Ketchup is a very small HTTP server implementation, currently [less than 400 LoC total](http://ix.io/dch)!
 
 Ketchup is also made to be as modular and embeddable as possible, if you want a cabal-free Haskell app, just take those two/three files you need and put it in your project!
 
@@ -10,7 +10,14 @@ - Regexp routing with parameters (ie. `/user/:name/(.\*)`)
 - Static file handler (ie. `static "."` as route/handler)
 
-Most of the project is dependency-free and only uses stuff included in Prelude, with the exception of Ketchup.Static who uses the mime-types package from Hackage, which is a single separately downloadable file.
+### Dependencies
+
+The core parts of Ketchup are all depedency free, that includes Ketchup.Httpd and Ketchup.Utils (and to a certain extent, Ketchup.Chunked).
+The dependencies required are for the following modules:
+
+- Ketchup.Routing (uses **regex-pcre-builtin**, *This can ben modified to use builtin POSIX regexp*)
+- Ketchup.Static (uses **mime-types**)
+- Ketchup.Auth (uses **base64-bytestring**)
 
 ### A word of warning
 
+ docs/.git/COMMIT_EDITMSG view
@@ -0,0 +1,221 @@+Updated docs to 0.3+# Please enter the commit message for your changes. Lines starting+# with '#' will be ignored, and an empty message aborts the commit.+# On branch gh-pages+# Your branch is up-to-date with 'origin/gh-pages'.+#+# Changes to be committed:+#	new file:   Ketchup-Auth.html+#	modified:   Ketchup-Httpd.html+#	modified:   Ketchup-Routing.html+#	modified:   Ketchup-Utils.html+#	modified:   doc-index.html+#	modified:   index-frames.html+#	modified:   index.html+#	modified:   main.txt+#	new file:   mini_Ketchup-Auth.html+#	modified:   mini_Ketchup-Routing.html+#	modified:   mini_Ketchup-Utils.html+#+# ------------------------ >8 ------------------------+# Do not touch the line above.+# Everything below will be removed.+diff --git a/Ketchup-Auth.html b/Ketchup-Auth.html+new file mode 100644+index 0000000..ff6a9f5+--- /dev/null++++ b/Ketchup-Auth.html+@@ -0,0 +1,8 @@++<!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>Ketchup.Auth</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[++window.onload = function () {pageLoad();setSynopsis("mini_Ketchup-Auth.html");};++//]]>++</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 empty">&nbsp;</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr></table><p class="caption">Ketchup.Auth</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"><a href="#v:basicAuth">basicAuth</a> &#8759; [(ByteString, ByteString)] &#8594; ByteString &#8594; <a href="Ketchup-Httpd.html#t:Handler">Handler</a> &#8594; <a href="Ketchup-Httpd.html#t:Handler">Handler</a></li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><a name="v:basicAuth" class="def">basicAuth</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">&#8759; [(ByteString, ByteString)]</td><td class="doc"><p>List of (Username, Password)++</p></td></tr><tr><td class="src">&#8594; ByteString</td><td class="doc"><p>Authentication Realm++</p></td></tr><tr><td class="src">&#8594; <a href="Ketchup-Httpd.html#t:Handler">Handler</a></td><td class="doc"><p>Success Handler++</p></td></tr><tr><td class="src">&#8594; <a href="Ketchup-Httpd.html#t:Handler">Handler</a></td><td class="doc empty">&nbsp;</td></tr></table></div><div class="doc"><p>Performs HTTP Basic Auth++</p></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.13.2</p></div></body></html>+\ No newline at end of file+diff --git a/Ketchup-Httpd.html b/Ketchup-Httpd.html+index b5c49f7..5c7dd67 100644+--- a/Ketchup-Httpd.html++++ b/Ketchup-Httpd.html+@@ -1,14 +1,14 @@+ <!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>Ketchup.Httpd</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[+ window.onload = function () {pageLoad();setSynopsis("mini_Ketchup-Httpd.html");};+ //]]>+-</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 empty">&nbsp;</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr></table><p class="caption">Ketchup.Httpd</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:HTTPRequest">HTTPRequest</a>  = <a href="#v:HTTPRequest">HTTPRequest</a> {<ul class="subs"><li><a href="#v:method">method</a> &#8759; ByteString</li><li><a href="#v:uri">uri</a> &#8759; ByteString</li><li><a href="#v:httpver">httpver</a> &#8759; ByteString</li><li><a href="#v:headers">headers</a> &#8759; <a href="Ketchup-Httpd.html#t:Headers">Headers</a></li><li><a href="#v:body">body</a> &#8759; ByteString</li></ul>}</li><li class="src short"><span class="keyword">type</span> <a href="#t:Headers">Headers</a> = Map ByteString [ByteString]</li><li class="src short"><span class="keyword">type</span> <a href="#t:Handler">Handler</a> = Socket &#8594; <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a> &#8594; IO ()</li><li class="src short"><a href="#v:listenHTTP">listenHTTP</a> &#8759; String &#8594; PortNumber &#8594; <a href="Ketchup-Httpd.html#t:Handler">Handler</a> &#8594; IO ()</li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><span class="keyword">data</span>  <a name="t:HTTPRequest" class="def">HTTPRequest</a>  </p><div class="doc"><p>HTTP Request type++</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 empty">&nbsp;</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr></table><p class="caption">Ketchup.Httpd</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:HTTPRequest">HTTPRequest</a>  = <a href="#v:HTTPRequest">HTTPRequest</a> {<ul class="subs"><li><a href="#v:method">method</a> &#8759; ByteString</li><li><a href="#v:uri">uri</a> &#8759; ByteString</li><li><a href="#v:httpver">httpver</a> &#8759; ByteString</li><li><a href="#v:headers">headers</a> &#8759; <a href="Ketchup-Httpd.html#t:Headers">Headers</a></li><li><a href="#v:body">body</a> &#8759; ByteString</li></ul>}</li><li class="src short"><span class="keyword">type</span> <a href="#t:Headers">Headers</a> = [(ByteString, [ByteString])]</li><li class="src short"><span class="keyword">type</span> <a href="#t:Handler">Handler</a> = Socket &#8594; <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a> &#8594; IO ()</li><li class="src short"><a href="#v:listenHTTP">listenHTTP</a> &#8759; String &#8594; PortNumber &#8594; <a href="Ketchup-Httpd.html#t:Handler">Handler</a> &#8594; IO ()</li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><span class="keyword">data</span>  <a name="t:HTTPRequest" class="def">HTTPRequest</a>  </p><div class="doc"><p>HTTP Request type+  This holds a complete HTTP request+ </p></div><div class="subs constructors"><p class="caption">Constructors</p><table><tr><td class="src"><a name="v:HTTPRequest" class="def">HTTPRequest</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:method" class="def">method</a> &#8759; ByteString</dt><dd class="doc"><p>Get HTTP Request Method (GET, POST etc.)+ </p></dd><dt class="src"><a name="v:uri" class="def">uri</a> &#8759; ByteString</dt><dd class="doc"><p>Get Request URI+ </p></dd><dt class="src"><a name="v:httpver" class="def">httpver</a> &#8759; ByteString</dt><dd class="doc"><p>Get HTTP Version+ </p></dd><dt class="src"><a name="v:headers" class="def">headers</a> &#8759; <a href="Ketchup-Httpd.html#t:Headers">Headers</a></dt><dd class="doc"><p>Get HTTP Headers (header, [values])+ </p></dd><dt class="src"><a name="v:body" class="def">body</a> &#8759; ByteString</dt><dd class="doc"><p>Get HTTP Post body (raw string)+-</p></dd></dl><div class="clear"></div></div></td></tr></table></div><div class="subs instances"><p id="control.i:HTTPRequest" class="caption collapser" onclick="toggleSection('i:HTTPRequest')">Instances</p><div id="section.i:HTTPRequest" class="show"><table><tr><td class="src">Show <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a></td><td class="doc empty">&nbsp;</td></tr></table></div></div></div><div class="top"><p class="src"><span class="keyword">type</span> <a name="t:Headers" class="def">Headers</a> = Map ByteString [ByteString]</p></div><div class="top"><p class="src"><span class="keyword">type</span> <a name="t:Handler" class="def">Handler</a> = Socket &#8594; <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a> &#8594; IO ()</p></div><div class="top"><p class="src"><a name="v:listenHTTP" class="def">listenHTTP</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">&#8759; String</td><td class="doc"><p>Address to bind (ie. <a href="*.html">*</a>)++</p></dd></dl><div class="clear"></div></div></td></tr></table></div><div class="subs instances"><p id="control.i:HTTPRequest" class="caption collapser" onclick="toggleSection('i:HTTPRequest')">Instances</p><div id="section.i:HTTPRequest" class="show"><table><tr><td class="src">Show <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a></td><td class="doc empty">&nbsp;</td></tr></table></div></div></div><div class="top"><p class="src"><span class="keyword">type</span> <a name="t:Headers" class="def">Headers</a> = [(ByteString, [ByteString])]</p></div><div class="top"><p class="src"><span class="keyword">type</span> <a name="t:Handler" class="def">Handler</a> = Socket &#8594; <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a> &#8594; IO ()</p></div><div class="top"><p class="src"><a name="v:listenHTTP" class="def">listenHTTP</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">&#8759; String</td><td class="doc"><p>Address to bind (ie. <a href="*.html">*</a>)+ </p></td></tr><tr><td class="src">&#8594; PortNumber</td><td class="doc"><p>Port to listen on+ </p></td></tr><tr><td class="src">&#8594; <a href="Ketchup-Httpd.html#t:Handler">Handler</a></td><td class="doc"><p>Route function to call+ </p></td></tr><tr><td class="src">&#8594; IO ()</td><td class="doc empty">&nbsp;</td></tr></table></div><div class="doc"><p>Listens for incoming HTTP request+diff --git a/Ketchup-Routing.html b/Ketchup-Routing.html+index c8298c8..6350f4f 100644+--- a/Ketchup-Routing.html++++ b/Ketchup-Routing.html+@@ -1,7 +1,7 @@+ <!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>Ketchup.Routing</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[+ window.onload = function () {pageLoad();setSynopsis("mini_Ketchup-Routing.html");};+ //]]>+-</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 empty">&nbsp;</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr></table><p class="caption">Ketchup.Routing</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">type</span> <a href="#t:Route">Route</a> = Socket &#8594; <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a> &#8594; <a href="Ketchup-Routing.html#t:Parameters">Parameters</a> &#8594; IO ()</li><li class="src short"><span class="keyword">type</span> <a href="#t:Parameters">Parameters</a> = Map ByteString ByteString</li><li class="src short"><a href="#v:route">route</a> &#8759; [(ByteString, <a href="Ketchup-Routing.html#t:Route">Route</a>)] &#8594; <a href="Ketchup-Httpd.html#t:Handler">Handler</a></li><li class="src short"><a href="#v:useHandler">useHandler</a> &#8759; <a href="Ketchup-Httpd.html#t:Handler">Handler</a> &#8594; <a href="Ketchup-Routing.html#t:Route">Route</a></li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><span class="keyword">type</span> <a name="t:Route" class="def">Route</a> = Socket &#8594; <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a> &#8594; <a href="Ketchup-Routing.html#t:Parameters">Parameters</a> &#8594; IO ()</p></div><div class="top"><p class="src"><span class="keyword">type</span> <a name="t:Parameters" class="def">Parameters</a> = Map ByteString ByteString</p></div><div class="top"><p class="src"><a name="v:route" class="def">route</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">&#8759; [(ByteString, <a href="Ketchup-Routing.html#t:Route">Route</a>)]</td><td class="doc"><p>Routes++</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 empty">&nbsp;</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr></table><p class="caption">Ketchup.Routing</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">type</span> <a href="#t:Route">Route</a> = Socket &#8594; <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a> &#8594; (ByteString &#8594; Maybe ByteString) &#8594; IO ()</li><li class="src short"><a href="#v:route">route</a> &#8759; [(ByteString, <a href="Ketchup-Routing.html#t:Route">Route</a>)] &#8594; <a href="Ketchup-Httpd.html#t:Handler">Handler</a></li><li class="src short"><a href="#v:useHandler">useHandler</a> &#8759; <a href="Ketchup-Httpd.html#t:Handler">Handler</a> &#8594; <a href="Ketchup-Routing.html#t:Route">Route</a></li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><span class="keyword">type</span> <a name="t:Route" class="def">Route</a> = Socket &#8594; <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a> &#8594; (ByteString &#8594; Maybe ByteString) &#8594; IO ()</p></div><div class="top"><p class="src"><a name="v:route" class="def">route</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">&#8759; [(ByteString, <a href="Ketchup-Routing.html#t:Route">Route</a>)]</td><td class="doc"><p>Routes+ </p></td></tr><tr><td class="src">&#8594; <a href="Ketchup-Httpd.html#t:Handler">Handler</a></td><td class="doc empty">&nbsp;</td></tr></table></div><div class="doc"><p>Router function+  Takes a list of routes and iterates through them for every requeust+ </p></div></div><div class="top"><p class="src"><a name="v:useHandler" class="def">useHandler</a> &#8759; <a href="Ketchup-Httpd.html#t:Handler">Handler</a> &#8594; <a href="Ketchup-Routing.html#t:Route">Route</a></p><div class="doc"><p>Wrap a handler in a route+diff --git a/Ketchup-Utils.html b/Ketchup-Utils.html+index d7b0897..0ef0bb4 100644+--- a/Ketchup-Utils.html++++ b/Ketchup-Utils.html+@@ -1,9 +1,9 @@+ <!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>Ketchup.Utils</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[+ window.onload = function () {pageLoad();setSynopsis("mini_Ketchup-Utils.html");};+ //]]>+-</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 empty">&nbsp;</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr></table><p class="caption">Ketchup.Utils</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"><a href="#v:trim">trim</a> &#8759; ByteString &#8594; ByteString</li><li class="src short"><a href="#v:breakBS">breakBS</a> &#8759; ByteString &#8594; ByteString &#8594; (ByteString, ByteString)</li><li class="src short"><a href="#v:parseBody">parseBody</a> &#8759; ByteString &#8594; Map ByteString ByteString</li><li class="src short"><a href="#v:sendReply">sendReply</a> &#8759; Socket &#8594; Int &#8594; [(ByteString, [ByteString])] &#8594; ByteString &#8594; IO ()</li><li class="src short"><a href="#v:sendBadRequest">sendBadRequest</a> &#8759; Socket &#8594; IO ()</li><li class="src short"><a href="#v:sendNotFound">sendNotFound</a> &#8759; Socket &#8594; IO ()</li><li class="src short"><a href="#v:statusMsg">statusMsg</a> &#8759; Int &#8594; ByteString</li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><a name="v:trim" class="def">trim</a> &#8759; ByteString &#8594; ByteString</p><div class="doc"><p>Trim whitespace from headers++</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 empty">&nbsp;</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr></table><p class="caption">Ketchup.Utils</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"><a href="#v:trim">trim</a> &#8759; ByteString &#8594; ByteString</li><li class="src short"><a href="#v:breakBS">breakBS</a> &#8759; ByteString &#8594; ByteString &#8594; (ByteString, ByteString)</li><li class="src short"><a href="#v:fallback">fallback</a> &#8759;  Maybe a &#8594; a &#8594; a</li><li class="src short"><a href="#v:parseBody">parseBody</a> &#8759; ByteString &#8594; [(ByteString, ByteString)]</li><li class="src short"><a href="#v:sendReply">sendReply</a> &#8759; Socket &#8594; Int &#8594; [(ByteString, [ByteString])] &#8594; ByteString &#8594; IO ()</li><li class="src short"><a href="#v:sendBadRequest">sendBadRequest</a> &#8759; Socket &#8594; IO ()</li><li class="src short"><a href="#v:sendNotFound">sendNotFound</a> &#8759; Socket &#8594; IO ()</li><li class="src short"><a href="#v:statusMsg">statusMsg</a> &#8759; Int &#8594; ByteString</li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><a name="v:trim" class="def">trim</a> &#8759; ByteString &#8594; ByteString</p><div class="doc"><p>Trim whitespace from headers+ </p></div></div><div class="top"><p class="src"><a name="v:breakBS" class="def">breakBS</a> &#8759; ByteString &#8594; ByteString &#8594; (ByteString, ByteString)</p><div class="doc"><p>ByteString breakSubstring wrapper that drops delimiters+-</p></div></div><div class="top"><p class="src"><a name="v:parseBody" class="def">parseBody</a> &#8759; ByteString &#8594; Map ByteString ByteString</p><div class="doc"><p>Parse a URL-encoded Request++</p></div></div><div class="top"><p class="src"><a name="v:fallback" class="def">fallback</a> &#8759;  Maybe a &#8594; a &#8594; a</p></div><div class="top"><p class="src"><a name="v:parseBody" class="def">parseBody</a> &#8759; ByteString &#8594; [(ByteString, ByteString)]</p><div class="doc"><p>Parse a URL-encoded Request+ </p></div></div><div class="top"><p class="src"><a name="v:sendReply" class="def">sendReply</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">&#8759; Socket</td><td class="doc"><p>Socket to write to+ </p></td></tr><tr><td class="src">&#8594; Int</td><td class="doc"><p>Status Code to send+ </p></td></tr><tr><td class="src">&#8594; [(ByteString, [ByteString])]</td><td class="doc"><p>HTTP headers (<a href="Header.html">Header</a>,[<a href="value1.html">value1</a>, <a href="value2.html">value2</a>])+diff --git a/doc-index.html b/doc-index.html+index ad296ab..e5dc6ab 100644+--- a/doc-index.html++++ b/doc-index.html+@@ -1,4 +1,4 @@+ <!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> (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[+ window.onload = function () {pageLoad();};+ //]]>+-</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 empty">&nbsp;</p></div><div id="content"><div id="index"><p class="caption">Index</p><table><tr><td class="src">body</td><td class="module"><a href="Ketchup-Httpd.html#v:body">Ketchup.Httpd</a></td></tr><tr><td class="src">breakBS</td><td class="module"><a href="Ketchup-Utils.html#v:breakBS">Ketchup.Utils</a></td></tr><tr><td class="src">chunk</td><td class="module"><a href="Ketchup-Chunked.html#v:chunk">Ketchup.Chunked</a></td></tr><tr><td class="src">chunkHeaders</td><td class="module"><a href="Ketchup-Chunked.html#v:chunkHeaders">Ketchup.Chunked</a></td></tr><tr><td class="src">endchunk</td><td class="module"><a href="Ketchup-Chunked.html#v:endchunk">Ketchup.Chunked</a></td></tr><tr><td class="src">Handler</td><td class="module"><a href="Ketchup-Httpd.html#t:Handler">Ketchup.Httpd</a></td></tr><tr><td class="src">Headers</td><td class="module"><a href="Ketchup-Httpd.html#t:Headers">Ketchup.Httpd</a></td></tr><tr><td class="src">headers</td><td class="module"><a href="Ketchup-Httpd.html#v:headers">Ketchup.Httpd</a></td></tr><tr><td class="src">HTTPRequest</td><td>&nbsp;</td></tr><tr><td class="alt">1 (Type/Class)</td><td class="module"><a href="Ketchup-Httpd.html#t:HTTPRequest">Ketchup.Httpd</a></td></tr><tr><td class="alt">2 (Data Constructor)</td><td class="module"><a href="Ketchup-Httpd.html#v:HTTPRequest">Ketchup.Httpd</a></td></tr><tr><td class="src">httpver</td><td class="module"><a href="Ketchup-Httpd.html#v:httpver">Ketchup.Httpd</a></td></tr><tr><td class="src">listenHTTP</td><td class="module"><a href="Ketchup-Httpd.html#v:listenHTTP">Ketchup.Httpd</a></td></tr><tr><td class="src">method</td><td class="module"><a href="Ketchup-Httpd.html#v:method">Ketchup.Httpd</a></td></tr><tr><td class="src">Parameters</td><td class="module"><a href="Ketchup-Routing.html#t:Parameters">Ketchup.Routing</a></td></tr><tr><td class="src">parseBody</td><td class="module"><a href="Ketchup-Utils.html#v:parseBody">Ketchup.Utils</a></td></tr><tr><td class="src">Route</td><td class="module"><a href="Ketchup-Routing.html#t:Route">Ketchup.Routing</a></td></tr><tr><td class="src">route</td><td class="module"><a href="Ketchup-Routing.html#v:route">Ketchup.Routing</a></td></tr><tr><td class="src">sendBadRequest</td><td class="module"><a href="Ketchup-Utils.html#v:sendBadRequest">Ketchup.Utils</a></td></tr><tr><td class="src">sendNotFound</td><td class="module"><a href="Ketchup-Utils.html#v:sendNotFound">Ketchup.Utils</a></td></tr><tr><td class="src">sendReply</td><td class="module"><a href="Ketchup-Utils.html#v:sendReply">Ketchup.Utils</a></td></tr><tr><td class="src">static</td><td class="module"><a href="Ketchup-Static.html#v:static">Ketchup.Static</a></td></tr><tr><td class="src">statusMsg</td><td class="module"><a href="Ketchup-Utils.html#v:statusMsg">Ketchup.Utils</a></td></tr><tr><td class="src">trim</td><td class="module"><a href="Ketchup-Utils.html#v:trim">Ketchup.Utils</a></td></tr><tr><td class="src">uri</td><td class="module"><a href="Ketchup-Httpd.html#v:uri">Ketchup.Httpd</a></td></tr><tr><td class="src">useHandler</td><td class="module"><a href="Ketchup-Routing.html#v:useHandler">Ketchup.Routing</a></td></tr></table></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.13.2</p></div></body></html>+\ No newline at end of file++</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 empty">&nbsp;</p></div><div id="content"><div id="index"><p class="caption">Index</p><table><tr><td class="src">basicAuth</td><td class="module"><a href="Ketchup-Auth.html#v:basicAuth">Ketchup.Auth</a></td></tr><tr><td class="src">body</td><td class="module"><a href="Ketchup-Httpd.html#v:body">Ketchup.Httpd</a></td></tr><tr><td class="src">breakBS</td><td class="module"><a href="Ketchup-Utils.html#v:breakBS">Ketchup.Utils</a></td></tr><tr><td class="src">chunk</td><td class="module"><a href="Ketchup-Chunked.html#v:chunk">Ketchup.Chunked</a></td></tr><tr><td class="src">chunkHeaders</td><td class="module"><a href="Ketchup-Chunked.html#v:chunkHeaders">Ketchup.Chunked</a></td></tr><tr><td class="src">endchunk</td><td class="module"><a href="Ketchup-Chunked.html#v:endchunk">Ketchup.Chunked</a></td></tr><tr><td class="src">fallback</td><td class="module"><a href="Ketchup-Utils.html#v:fallback">Ketchup.Utils</a></td></tr><tr><td class="src">Handler</td><td class="module"><a href="Ketchup-Httpd.html#t:Handler">Ketchup.Httpd</a></td></tr><tr><td class="src">Headers</td><td class="module"><a href="Ketchup-Httpd.html#t:Headers">Ketchup.Httpd</a></td></tr><tr><td class="src">headers</td><td class="module"><a href="Ketchup-Httpd.html#v:headers">Ketchup.Httpd</a></td></tr><tr><td class="src">HTTPRequest</td><td>&nbsp;</td></tr><tr><td class="alt">1 (Type/Class)</td><td class="module"><a href="Ketchup-Httpd.html#t:HTTPRequest">Ketchup.Httpd</a></td></tr><tr><td class="alt">2 (Data Constructor)</td><td class="module"><a href="Ketchup-Httpd.html#v:HTTPRequest">Ketchup.Httpd</a></td></tr><tr><td class="src">httpver</td><td class="module"><a href="Ketchup-Httpd.html#v:httpver">Ketchup.Httpd</a></td></tr><tr><td class="src">listenHTTP</td><td class="module"><a href="Ketchup-Httpd.html#v:listenHTTP">Ketchup.Httpd</a></td></tr><tr><td class="src">method</td><td class="module"><a href="Ketchup-Httpd.html#v:method">Ketchup.Httpd</a></td></tr><tr><td class="src">parseBody</td><td class="module"><a href="Ketchup-Utils.html#v:parseBody">Ketchup.Utils</a></td></tr><tr><td class="src">Route</td><td class="module"><a href="Ketchup-Routing.html#t:Route">Ketchup.Routing</a></td></tr><tr><td class="src">route</td><td class="module"><a href="Ketchup-Routing.html#v:route">Ketchup.Routing</a></td></tr><tr><td class="src">sendBadRequest</td><td class="module"><a href="Ketchup-Utils.html#v:sendBadRequest">Ketchup.Utils</a></td></tr><tr><td class="src">sendNotFound</td><td class="module"><a href="Ketchup-Utils.html#v:sendNotFound">Ketchup.Utils</a></td></tr><tr><td class="src">sendReply</td><td class="module"><a href="Ketchup-Utils.html#v:sendReply">Ketchup.Utils</a></td></tr><tr><td class="src">static</td><td class="module"><a href="Ketchup-Static.html#v:static">Ketchup.Static</a></td></tr><tr><td class="src">statusMsg</td><td class="module"><a href="Ketchup-Utils.html#v:statusMsg">Ketchup.Utils</a></td></tr><tr><td class="src">trim</td><td class="module"><a href="Ketchup-Utils.html#v:trim">Ketchup.Utils</a></td></tr><tr><td class="src">uri</td><td class="module"><a href="Ketchup-Httpd.html#v:uri">Ketchup.Httpd</a></td></tr><tr><td class="src">useHandler</td><td class="module"><a href="Ketchup-Routing.html#v:useHandler">Ketchup.Routing</a></td></tr></table></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.13.2</p></div></body></html>+\ No newline at end of file+diff --git a/index-frames.html b/index-frames.html+index 9de2c9d..8766065 100644+--- a/index-frames.html++++ b/index-frames.html+@@ -1,4 +1,4 @@+ <!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></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[+ window.onload = function () {pageLoad();};+ //]]>+-</script></head><body id="mini"><div id="module-list"><p class="caption">Modules</p><ul><li class="module"><a href="Ketchup-Chunked.html" target="main">Ketchup.Chunked</a></li><li class="module"><a href="Ketchup-Httpd.html" target="main">Ketchup.Httpd</a></li><li class="module"><a href="Ketchup-Routing.html" target="main">Ketchup.Routing</a></li><li class="module"><a href="Ketchup-Static.html" target="main">Ketchup.Static</a></li><li class="module"><a href="Ketchup-Utils.html" target="main">Ketchup.Utils</a></li></ul></div></body></html>+\ No newline at end of file++</script></head><body id="mini"><div id="module-list"><p class="caption">Modules</p><ul><li class="module"><a href="Ketchup-Auth.html" target="main">Ketchup.Auth</a></li><li class="module"><a href="Ketchup-Chunked.html" target="main">Ketchup.Chunked</a></li><li class="module"><a href="Ketchup-Httpd.html" target="main">Ketchup.Httpd</a></li><li class="module"><a href="Ketchup-Routing.html" target="main">Ketchup.Routing</a></li><li class="module"><a href="Ketchup-Static.html" target="main">Ketchup.Static</a></li><li class="module"><a href="Ketchup-Utils.html" target="main">Ketchup.Utils</a></li></ul></div></body></html>+\ No newline at end of file+diff --git a/index.html b/index.html+index 75be0ea..0427491 100644+--- a/index.html++++ b/index.html+@@ -1,4 +1,4 @@+ <!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></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[+ window.onload = function () {pageLoad();};+ //]]>+-</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 empty">&nbsp;</p></div><div id="content"><div id="module-list"><p class="caption">Modules</p><ul><li><span id="control.n.1" class="module collapser" onclick="toggleSection('n.1')">Ketchup</span><ul id="section.n.1" class="show"><li><span class="module"><a href="Ketchup-Chunked.html">Ketchup.Chunked</a></span></li><li><span class="module"><a href="Ketchup-Httpd.html">Ketchup.Httpd</a></span></li><li><span class="module"><a href="Ketchup-Routing.html">Ketchup.Routing</a></span></li><li><span class="module"><a href="Ketchup-Static.html">Ketchup.Static</a></span></li><li><span class="module"><a href="Ketchup-Utils.html">Ketchup.Utils</a></span></li></ul></li></ul></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.13.2</p></div></body></html>+\ No newline at end of file++</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 empty">&nbsp;</p></div><div id="content"><div id="module-list"><p class="caption">Modules</p><ul><li><span id="control.n.1" class="module collapser" onclick="toggleSection('n.1')">Ketchup</span><ul id="section.n.1" class="show"><li><span class="module"><a href="Ketchup-Auth.html">Ketchup.Auth</a></span></li><li><span class="module"><a href="Ketchup-Chunked.html">Ketchup.Chunked</a></span></li><li><span class="module"><a href="Ketchup-Httpd.html">Ketchup.Httpd</a></span></li><li><span class="module"><a href="Ketchup-Routing.html">Ketchup.Routing</a></span></li><li><span class="module"><a href="Ketchup-Static.html">Ketchup.Static</a></span></li><li><span class="module"><a href="Ketchup-Utils.html">Ketchup.Utils</a></span></li></ul></li></ul></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.13.2</p></div></body></html>+\ No newline at end of file+diff --git a/main.txt b/main.txt+index dab38cf..e8a9b10 100644+--- a/main.txt++++ b/main.txt+@@ -10,9 +10,10 @@ trim :: ByteString -> ByteString+ + -- | ByteString breakSubstring wrapper that drops delimiters+ breakBS :: ByteString -> ByteString -> (ByteString, ByteString)++fallback :: Maybe a -> a -> a+ + -- | Parse a URL-encoded Request+-parseBody :: ByteString -> Map ByteString ByteString++parseBody :: ByteString -> [(ByteString, ByteString)]+ + -- | Send a HTTP reply Sends a reply with the given parameters+ sendReply :: Socket -> Int -> [(ByteString, [ByteString])] -> ByteString -> IO ()+@@ -46,16 +47,26 @@ headers :: HTTPRequest -> Headers+ + -- | Get HTTP Post body (raw string)+ body :: HTTPRequest -> ByteString+-type Headers = Map ByteString [ByteString]++type Headers = [(ByteString, [ByteString])]+ type Handler = Socket -> HTTPRequest -> IO ()+ + -- | Listens for incoming HTTP request+ listenHTTP :: String -> PortNumber -> Handler -> IO ()+ instance Show HTTPRequest+ ++module Ketchup.Chunked++++-- | Send HTTP reply headers and begin a Chunked transmission++chunkHeaders :: Socket -> Int -> [(ByteString, [ByteString])] -> IO ()++++-- | Sends a chunk++chunk :: Socket -> ByteString -> IO ()++++-- | Send the final/closing chunk++endchunk :: Socket -> IO ()+++ module Ketchup.Routing+-type Route = Socket -> HTTPRequest -> Parameters -> IO ()+-type Parameters = Map ByteString ByteString++type Route = Socket -> HTTPRequest -> (ByteString -> Maybe ByteString) -> IO ()+ + -- | Router function Takes a list of routes and iterates through them for+ --   every requeust+@@ -70,13 +81,7 @@ module Ketchup.Static+ -- | Static file handler Takes a directory and returns a route+ static :: ByteString -> Handler+ +-module Ketchup.Chunked+-+--- | Send HTTP reply headers and begin a Chunked transmission+-chunkHeaders :: Socket -> Int -> [(ByteString, [ByteString])] -> IO ()+-+--- | Sends a chunk+-chunk :: Socket -> ByteString -> IO ()++module Ketchup.Auth+ +--- | Send the final/closing chunk+-endchunk :: Socket -> IO ()++-- | Performs HTTP Basic Auth++basicAuth :: [(ByteString, ByteString)] -> ByteString -> Handler -> Handler+diff --git a/mini_Ketchup-Auth.html b/mini_Ketchup-Auth.html+new file mode 100644+index 0000000..7015cd0+--- /dev/null++++ b/mini_Ketchup-Auth.html+@@ -0,0 +1,4 @@++<!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>Ketchup.Auth</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[++window.onload = function () {pageLoad();};++//]]>++</script></head><body id="mini"><div id="module-header"><p class="caption">Ketchup.Auth</p></div><div id="interface"><div class="top"><p class="src"><a href="Ketchup-Auth.html#v:basicAuth" target="main">basicAuth</a></p></div></div></body></html>+\ No newline at end of file+diff --git a/mini_Ketchup-Routing.html b/mini_Ketchup-Routing.html+index a33f00a..f8b79cf 100644+--- a/mini_Ketchup-Routing.html++++ b/mini_Ketchup-Routing.html+@@ -1,4 +1,4 @@+ <!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>Ketchup.Routing</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[+ window.onload = function () {pageLoad();};+ //]]>+-</script></head><body id="mini"><div id="module-header"><p class="caption">Ketchup.Routing</p></div><div id="interface"><div class="top"><p class="src"><span class="keyword">type</span> <a href="Ketchup-Routing.html#t:Route" target="main">Route</a> </p></div><div class="top"><p class="src"><span class="keyword">type</span> <a href="Ketchup-Routing.html#t:Parameters" target="main">Parameters</a> </p></div><div class="top"><p class="src"><a href="Ketchup-Routing.html#v:route" target="main">route</a></p></div><div class="top"><p class="src"><a href="Ketchup-Routing.html#v:useHandler" target="main">useHandler</a></p></div></div></body></html>+\ No newline at end of file++</script></head><body id="mini"><div id="module-header"><p class="caption">Ketchup.Routing</p></div><div id="interface"><div class="top"><p class="src"><span class="keyword">type</span> <a href="Ketchup-Routing.html#t:Route" target="main">Route</a> </p></div><div class="top"><p class="src"><a href="Ketchup-Routing.html#v:route" target="main">route</a></p></div><div class="top"><p class="src"><a href="Ketchup-Routing.html#v:useHandler" target="main">useHandler</a></p></div></div></body></html>+\ No newline at end of file+diff --git a/mini_Ketchup-Utils.html b/mini_Ketchup-Utils.html+index bfbd19d..cc746e2 100644+--- a/mini_Ketchup-Utils.html++++ b/mini_Ketchup-Utils.html+@@ -1,4 +1,4 @@+ <!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>Ketchup.Utils</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[+ window.onload = function () {pageLoad();};+ //]]>+-</script></head><body id="mini"><div id="module-header"><p class="caption">Ketchup.Utils</p></div><div id="interface"><div class="top"><p class="src"><a href="Ketchup-Utils.html#v:trim" target="main">trim</a></p></div><div class="top"><p class="src"><a href="Ketchup-Utils.html#v:breakBS" target="main">breakBS</a></p></div><div class="top"><p class="src"><a href="Ketchup-Utils.html#v:parseBody" target="main">parseBody</a></p></div><div class="top"><p class="src"><a href="Ketchup-Utils.html#v:sendReply" target="main">sendReply</a></p></div><div class="top"><p class="src"><a href="Ketchup-Utils.html#v:sendBadRequest" target="main">sendBadRequest</a></p></div><div class="top"><p class="src"><a href="Ketchup-Utils.html#v:sendNotFound" target="main">sendNotFound</a></p></div><div class="top"><p class="src"><a href="Ketchup-Utils.html#v:statusMsg" target="main">statusMsg</a></p></div></div></body></html>+\ No newline at end of file++</script></head><body id="mini"><div id="module-header"><p class="caption">Ketchup.Utils</p></div><div id="interface"><div class="top"><p class="src"><a href="Ketchup-Utils.html#v:trim" target="main">trim</a></p></div><div class="top"><p class="src"><a href="Ketchup-Utils.html#v:breakBS" target="main">breakBS</a></p></div><div class="top"><p class="src"><a href="Ketchup-Utils.html#v:fallback" target="main">fallback</a></p></div><div class="top"><p class="src"><a href="Ketchup-Utils.html#v:parseBody" target="main">parseBody</a></p></div><div class="top"><p class="src"><a href="Ketchup-Utils.html#v:sendReply" target="main">sendReply</a></p></div><div class="top"><p class="src"><a href="Ketchup-Utils.html#v:sendBadRequest" target="main">sendBadRequest</a></p></div><div class="top"><p class="src"><a href="Ketchup-Utils.html#v:sendNotFound" target="main">sendNotFound</a></p></div><div class="top"><p class="src"><a href="Ketchup-Utils.html#v:statusMsg" target="main">statusMsg</a></p></div></div></body></html>+\ No newline at end of file
+ docs/.git/HEAD view
@@ -0,0 +1,1 @@+ref: refs/heads/gh-pages
+ docs/.git/config view
@@ -0,0 +1,11 @@+[core]+	repositoryformatversion = 0+	filemode = true+	bare = false+	logallrefupdates = true+[remote "origin"]+	url = ssh://git@github.com/Hamcha/ketchup+	fetch = +refs/heads/*:refs/remotes/origin/*+[branch "gh-pages"]+	remote = origin+	merge = refs/heads/gh-pages
+ docs/.git/config~ view
@@ -0,0 +1,11 @@+[core]+	repositoryformatversion = 0+	filemode = true+	bare = false+	logallrefupdates = true+[remote "origin"]+	url = https://github.com/Hamcha/ketchup+	fetch = +refs/heads/*:refs/remotes/origin/*+[branch "gh-pages"]+	remote = origin+	merge = refs/heads/gh-pages
+ docs/.git/description view
@@ -0,0 +1,1 @@+Unnamed repository; edit this file 'description' to name the repository.
+ docs/.git/hooks/applypatch-msg.sample view
@@ -0,0 +1,15 @@+#!/bin/sh+#+# An example hook script to check the commit log message taken by+# applypatch from an e-mail message.+#+# The hook should exit with non-zero status after issuing an+# appropriate message if it wants to stop the commit.  The hook is+# allowed to edit the commit message file.+#+# To enable this hook, rename this file to "applypatch-msg".++. git-sh-setup+test -x "$GIT_DIR/hooks/commit-msg" &&+	exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"}+:
+ docs/.git/hooks/commit-msg.sample view
@@ -0,0 +1,24 @@+#!/bin/sh+#+# An example hook script to check the commit log message.+# Called by "git commit" with one argument, the name of the file+# that has the commit message.  The hook should exit with non-zero+# status after issuing an appropriate message if it wants to stop the+# commit.  The hook is allowed to edit the commit message file.+#+# To enable this hook, rename this file to "commit-msg".++# Uncomment the below to add a Signed-off-by line to the message.+# Doing this in a hook is a bad idea in general, but the prepare-commit-msg+# hook is more suited to it.+#+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"++# This example catches duplicate Signed-off-by lines.++test "" = "$(grep '^Signed-off-by: ' "$1" |+	 sort | uniq -c | sed -e '/^[ 	]*1[ 	]/d')" || {+	echo >&2 Duplicate Signed-off-by lines.+	exit 1+}
+ docs/.git/hooks/post-update.sample view
@@ -0,0 +1,8 @@+#!/bin/sh+#+# An example hook script to prepare a packed repository for use over+# dumb transports.+#+# To enable this hook, rename this file to "post-update".++exec git update-server-info
+ docs/.git/hooks/pre-applypatch.sample view
@@ -0,0 +1,14 @@+#!/bin/sh+#+# An example hook script to verify what is about to be committed+# by applypatch from an e-mail message.+#+# The hook should exit with non-zero status after issuing an+# appropriate message if it wants to stop the commit.+#+# To enable this hook, rename this file to "pre-applypatch".++. git-sh-setup+test -x "$GIT_DIR/hooks/pre-commit" &&+	exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"}+:
+ docs/.git/hooks/pre-commit.sample view
@@ -0,0 +1,49 @@+#!/bin/sh+#+# An example hook script to verify what is about to be committed.+# Called by "git commit" with no arguments.  The hook should+# exit with non-zero status after issuing an appropriate message if+# it wants to stop the commit.+#+# To enable this hook, rename this file to "pre-commit".++if git rev-parse --verify HEAD >/dev/null 2>&1+then+	against=HEAD+else+	# Initial commit: diff against an empty tree object+	against=4b825dc642cb6eb9a060e54bf8d69288fbee4904+fi++# If you want to allow non-ASCII filenames set this variable to true.+allownonascii=$(git config --bool hooks.allownonascii)++# Redirect output to stderr.+exec 1>&2++# Cross platform projects tend to avoid non-ASCII filenames; prevent+# them from being added to the repository. We exploit the fact that the+# printable range starts at the space character and ends with tilde.+if [ "$allownonascii" != "true" ] &&+	# Note that the use of brackets around a tr range is ok here, (it's+	# even required, for portability to Solaris 10's /usr/bin/tr), since+	# the square bracket bytes happen to fall in the designated range.+	test $(git diff --cached --name-only --diff-filter=A -z $against |+	  LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0+then+	cat <<\EOF+Error: Attempt to add a non-ASCII file name.++This can cause problems if you want to work with people on other platforms.++To be portable it is advisable to rename the file.++If you know what you are doing you can disable this check using:++  git config hooks.allownonascii true+EOF+	exit 1+fi++# If there are whitespace errors, print the offending file names and fail.+exec git diff-index --check --cached $against --
+ docs/.git/hooks/pre-push.sample view
@@ -0,0 +1,54 @@+#!/bin/sh++# An example hook script to verify what is about to be pushed.  Called by "git+# push" after it has checked the remote status, but before anything has been+# pushed.  If this script exits with a non-zero status nothing will be pushed.+#+# This hook is called with the following parameters:+#+# $1 -- Name of the remote to which the push is being done+# $2 -- URL to which the push is being done+#+# If pushing without using a named remote those arguments will be equal.+#+# Information about the commits which are being pushed is supplied as lines to+# the standard input in the form:+#+#   <local ref> <local sha1> <remote ref> <remote sha1>+#+# This sample shows how to prevent push of commits where the log message starts+# with "WIP" (work in progress).++remote="$1"+url="$2"++z40=0000000000000000000000000000000000000000++IFS=' '+while read local_ref local_sha remote_ref remote_sha+do+	if [ "$local_sha" = $z40 ]+	then+		# Handle delete+		:+	else+		if [ "$remote_sha" = $z40 ]+		then+			# New branch, examine all commits+			range="$local_sha"+		else+			# Update to existing branch, examine new commits+			range="$remote_sha..$local_sha"+		fi++		# Check for WIP commit+		commit=`git rev-list -n 1 --grep '^WIP' "$range"`+		if [ -n "$commit" ]+		then+			echo "Found WIP commit in $local_ref, not pushing"+			exit 1+		fi+	fi+done++exit 0
+ docs/.git/hooks/pre-rebase.sample view
@@ -0,0 +1,169 @@+#!/bin/sh+#+# Copyright (c) 2006, 2008 Junio C Hamano+#+# The "pre-rebase" hook is run just before "git rebase" starts doing+# its job, and can prevent the command from running by exiting with+# non-zero status.+#+# The hook is called with the following parameters:+#+# $1 -- the upstream the series was forked from.+# $2 -- the branch being rebased (or empty when rebasing the current branch).+#+# This sample shows how to prevent topic branches that are already+# merged to 'next' branch from getting rebased, because allowing it+# would result in rebasing already published history.++publish=next+basebranch="$1"+if test "$#" = 2+then+	topic="refs/heads/$2"+else+	topic=`git symbolic-ref HEAD` ||+	exit 0 ;# we do not interrupt rebasing detached HEAD+fi++case "$topic" in+refs/heads/??/*)+	;;+*)+	exit 0 ;# we do not interrupt others.+	;;+esac++# Now we are dealing with a topic branch being rebased+# on top of master.  Is it OK to rebase it?++# Does the topic really exist?+git show-ref -q "$topic" || {+	echo >&2 "No such branch $topic"+	exit 1+}++# Is topic fully merged to master?+not_in_master=`git rev-list --pretty=oneline ^master "$topic"`+if test -z "$not_in_master"+then+	echo >&2 "$topic is fully merged to master; better remove it."+	exit 1 ;# we could allow it, but there is no point.+fi++# Is topic ever merged to next?  If so you should not be rebasing it.+only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`+only_next_2=`git rev-list ^master           ${publish} | sort`+if test "$only_next_1" = "$only_next_2"+then+	not_in_topic=`git rev-list "^$topic" master`+	if test -z "$not_in_topic"+	then+		echo >&2 "$topic is already up-to-date with master"+		exit 1 ;# we could allow it, but there is no point.+	else+		exit 0+	fi+else+	not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`+	/usr/local/bin/perl -e '+		my $topic = $ARGV[0];+		my $msg = "* $topic has commits already merged to public branch:\n";+		my (%not_in_next) = map {+			/^([0-9a-f]+) /;+			($1 => 1);+		} split(/\n/, $ARGV[1]);+		for my $elem (map {+				/^([0-9a-f]+) (.*)$/;+				[$1 => $2];+			} split(/\n/, $ARGV[2])) {+			if (!exists $not_in_next{$elem->[0]}) {+				if ($msg) {+					print STDERR $msg;+					undef $msg;+				}+				print STDERR " $elem->[1]\n";+			}+		}+	' "$topic" "$not_in_next" "$not_in_master"+	exit 1+fi++exit 0++################################################################++This sample hook safeguards topic branches that have been+published from being rewound.++The workflow assumed here is:++ * Once a topic branch forks from "master", "master" is never+   merged into it again (either directly or indirectly).++ * Once a topic branch is fully cooked and merged into "master",+   it is deleted.  If you need to build on top of it to correct+   earlier mistakes, a new topic branch is created by forking at+   the tip of the "master".  This is not strictly necessary, but+   it makes it easier to keep your history simple.++ * Whenever you need to test or publish your changes to topic+   branches, merge them into "next" branch.++The script, being an example, hardcodes the publish branch name+to be "next", but it is trivial to make it configurable via+$GIT_DIR/config mechanism.++With this workflow, you would want to know:++(1) ... if a topic branch has ever been merged to "next".  Young+    topic branches can have stupid mistakes you would rather+    clean up before publishing, and things that have not been+    merged into other branches can be easily rebased without+    affecting other people.  But once it is published, you would+    not want to rewind it.++(2) ... if a topic branch has been fully merged to "master".+    Then you can delete it.  More importantly, you should not+    build on top of it -- other people may already want to+    change things related to the topic as patches against your+    "master", so if you need further changes, it is better to+    fork the topic (perhaps with the same name) afresh from the+    tip of "master".++Let's look at this example:++		   o---o---o---o---o---o---o---o---o---o "next"+		  /       /           /           /+		 /   a---a---b A     /           /+		/   /               /           /+	       /   /   c---c---c---c B         /+	      /   /   /             \         /+	     /   /   /   b---b C     \       /+	    /   /   /   /             \     /+    ---o---o---o---o---o---o---o---o---o---o---o "master"+++A, B and C are topic branches.++ * A has one fix since it was merged up to "next".++ * B has finished.  It has been fully merged up to "master" and "next",+   and is ready to be deleted.++ * C has not merged to "next" at all.++We would want to allow C to be rebased, refuse A, and encourage+B to be deleted.++To compute (1):++	git rev-list ^master ^topic next+	git rev-list ^master        next++	if these match, topic has not merged in next at all.++To compute (2):++	git rev-list master..topic++	if this is empty, it is fully merged to "master".
+ docs/.git/hooks/prepare-commit-msg.sample view
@@ -0,0 +1,36 @@+#!/bin/sh+#+# An example hook script to prepare the commit log message.+# Called by "git commit" with the name of the file that has the+# commit message, followed by the description of the commit+# message's source.  The hook's purpose is to edit the commit+# message file.  If the hook fails with a non-zero status,+# the commit is aborted.+#+# To enable this hook, rename this file to "prepare-commit-msg".++# This hook includes three examples.  The first comments out the+# "Conflicts:" part of a merge commit.+#+# The second includes the output of "git diff --name-status -r"+# into the message, just before the "git status" output.  It is+# commented because it doesn't cope with --amend or with squashed+# commits.+#+# The third example adds a Signed-off-by line to the message, that can+# still be edited.  This is rarely a good idea.++case "$2,$3" in+  merge,)+    /usr/local/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;++# ,|template,)+#   /usr/local/bin/perl -i.bak -pe '+#      print "\n" . `git diff --cached --name-status -r`+#	 if /^#/ && $first++ == 0' "$1" ;;++  *) ;;+esac++# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
+ docs/.git/hooks/update.sample view
@@ -0,0 +1,128 @@+#!/bin/sh+#+# An example hook script to blocks unannotated tags from entering.+# Called by "git receive-pack" with arguments: refname sha1-old sha1-new+#+# To enable this hook, rename this file to "update".+#+# Config+# ------+# hooks.allowunannotated+#   This boolean sets whether unannotated tags will be allowed into the+#   repository.  By default they won't be.+# hooks.allowdeletetag+#   This boolean sets whether deleting tags will be allowed in the+#   repository.  By default they won't be.+# hooks.allowmodifytag+#   This boolean sets whether a tag may be modified after creation. By default+#   it won't be.+# hooks.allowdeletebranch+#   This boolean sets whether deleting branches will be allowed in the+#   repository.  By default they won't be.+# hooks.denycreatebranch+#   This boolean sets whether remotely creating branches will be denied+#   in the repository.  By default this is allowed.+#++# --- Command line+refname="$1"+oldrev="$2"+newrev="$3"++# --- Safety check+if [ -z "$GIT_DIR" ]; then+	echo "Don't run this script from the command line." >&2+	echo " (if you want, you could supply GIT_DIR then run" >&2+	echo "  $0 <ref> <oldrev> <newrev>)" >&2+	exit 1+fi++if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then+	echo "usage: $0 <ref> <oldrev> <newrev>" >&2+	exit 1+fi++# --- Config+allowunannotated=$(git config --bool hooks.allowunannotated)+allowdeletebranch=$(git config --bool hooks.allowdeletebranch)+denycreatebranch=$(git config --bool hooks.denycreatebranch)+allowdeletetag=$(git config --bool hooks.allowdeletetag)+allowmodifytag=$(git config --bool hooks.allowmodifytag)++# check for no description+projectdesc=$(sed -e '1q' "$GIT_DIR/description")+case "$projectdesc" in+"Unnamed repository"* | "")+	echo "*** Project description file hasn't been set" >&2+	exit 1+	;;+esac++# --- Check types+# if $newrev is 0000...0000, it's a commit to delete a ref.+zero="0000000000000000000000000000000000000000"+if [ "$newrev" = "$zero" ]; then+	newrev_type=delete+else+	newrev_type=$(git cat-file -t $newrev)+fi++case "$refname","$newrev_type" in+	refs/tags/*,commit)+		# un-annotated tag+		short_refname=${refname##refs/tags/}+		if [ "$allowunannotated" != "true" ]; then+			echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2+			echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2+			exit 1+		fi+		;;+	refs/tags/*,delete)+		# delete tag+		if [ "$allowdeletetag" != "true" ]; then+			echo "*** Deleting a tag is not allowed in this repository" >&2+			exit 1+		fi+		;;+	refs/tags/*,tag)+		# annotated tag+		if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1+		then+			echo "*** Tag '$refname' already exists." >&2+			echo "*** Modifying a tag is not allowed in this repository." >&2+			exit 1+		fi+		;;+	refs/heads/*,commit)+		# branch+		if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then+			echo "*** Creating a branch is not allowed in this repository" >&2+			exit 1+		fi+		;;+	refs/heads/*,delete)+		# delete branch+		if [ "$allowdeletebranch" != "true" ]; then+			echo "*** Deleting a branch is not allowed in this repository" >&2+			exit 1+		fi+		;;+	refs/remotes/*,commit)+		# tracking branch+		;;+	refs/remotes/*,delete)+		# delete tracking branch+		if [ "$allowdeletebranch" != "true" ]; then+			echo "*** Deleting a tracking branch is not allowed in this repository" >&2+			exit 1+		fi+		;;+	*)+		# Anything else (is there anything else?)+		echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2+		exit 1+		;;+esac++# --- Finished+exit 0
+ docs/.git/index view

binary file changed (absent → 1928 bytes)

+ docs/.git/info/exclude view
@@ -0,0 +1,6 @@+# git ls-files --others --exclude-from=.git/info/exclude+# Lines that start with '#' are comments.+# For a project mostly in C, the following would be a good set of+# exclude patterns (uncomment them if you want to use them):+# *.[oa]+# *~
+ docs/.git/logs/HEAD view
@@ -0,0 +1,3 @@+0000000000000000000000000000000000000000 4ac44b6241517d43310da25b086e175b3b9c0b49 Hamcha <zikyky@gmail.com> 1404003477 +0200	clone: from https://github.com/Hamcha/ketchup+4ac44b6241517d43310da25b086e175b3b9c0b49 33d1dadf72d9a1c6217c5a6c7992dcdaaa343742 Hamcha <zikyky@gmail.com> 1404003595 +0200	commit: Updated docs+33d1dadf72d9a1c6217c5a6c7992dcdaaa343742 4c2353910734c89633d869f0ffccf8f565c93221 Hamcha <zikyky@gmail.com> 1404079702 +0200	commit: Updated docs to 0.3
+ docs/.git/logs/refs/heads/gh-pages view
@@ -0,0 +1,3 @@+0000000000000000000000000000000000000000 4ac44b6241517d43310da25b086e175b3b9c0b49 Hamcha <zikyky@gmail.com> 1404003477 +0200	clone: from https://github.com/Hamcha/ketchup+4ac44b6241517d43310da25b086e175b3b9c0b49 33d1dadf72d9a1c6217c5a6c7992dcdaaa343742 Hamcha <zikyky@gmail.com> 1404003595 +0200	commit: Updated docs+33d1dadf72d9a1c6217c5a6c7992dcdaaa343742 4c2353910734c89633d869f0ffccf8f565c93221 Hamcha <zikyky@gmail.com> 1404079702 +0200	commit: Updated docs to 0.3
+ docs/.git/logs/refs/remotes/origin/HEAD view
@@ -0,0 +1,1 @@+0000000000000000000000000000000000000000 4ad51f9dc87b6aa48cb614030521d957b8498622 Hamcha <zikyky@gmail.com> 1404003477 +0200	clone: from https://github.com/Hamcha/ketchup
+ docs/.git/logs/refs/remotes/origin/gh-pages view
@@ -0,0 +1,2 @@+4ac44b6241517d43310da25b086e175b3b9c0b49 33d1dadf72d9a1c6217c5a6c7992dcdaaa343742 Hamcha <zikyky@gmail.com> 1404003933 +0200	update by push+33d1dadf72d9a1c6217c5a6c7992dcdaaa343742 4c2353910734c89633d869f0ffccf8f565c93221 Hamcha <zikyky@gmail.com> 1404079711 +0200	update by push
+ docs/.git/objects/04/27491eaa020186e459934ed69cdb7d808501cd view
@@ -0,0 +1,4 @@+x”ßOÛ0Ç÷Ì_aü0à!ñJ…4ÖÄ+L Á@´Mˆ×1M¨k{±Óšö¿ïl(Ý&M}jz¾ûÜÝ×çI=B½ƒƒþ›lûørX|¿:A•›JtuûñülˆpBÈ×þãâ};-.ÎQ/}‡Š†)[»Z+&	9ù‚®œ3™Ïç鼟êfLŠk²ð¬žî>·™–®Ä4ùS©lþJïðð0{WÁJšM…cP¥3‰øÑÖ³µrB¹¤XÿrìÄÂO ^±Æ+—ߟ’÷š¹ÚIA3ÒýÊZMPՈ‡k.˜J¹µ5BæØº¥¶Âaä C!:Ǘ>$`-ojãm84ÃÊRóIÒºZ¦€[‰~d3}¡-¿hÖEÿϐlûnx|TÝmÍkUêyª•Ô¬D9zh÷÷v÷ÐOÃÆâì»{ƒ_ƒ-BîïéÖKUérI³²ž¡ºÌ±a|Q‰?
ÔÔJÄ%³p'^(>zËT¨dM3¸† #©—Óî2lFtæ½V=AdÕûÌG¾¸’VÒÌ<eæÌ„žÄÔ¸%¦oÕȚAFp¡î—⻇¢žÚ™ê²•"‘µu`]bzΡF`ù”¾Dk˜+]z\£eªÒLS!a¶¤dƂBH+.k>iÐã±7"è¿»Q;{˜~ŽW­ÙäôÚèõ+m+=ïô%¼ÊO"wÄä¨uU§ugJ½)г=Ëþ_ÀaÕª‰(טusì)¼Ðuh°m޼Öð–Ôx­Òκ9öÆ1Wó5j4n½…WoטÁö2}¸²øfûõ„?hí³4ôªÙå¢D£%zž•í[1;R†Üm ‚éiÜE>7š‰ÆúU±ŸöúéþÊ{"q'„Ióø
+ docs/.git/objects/0e/f0bb4acb2a054328faea81aaa1b6ef08ab4324 view

binary file changed (absent → 1451 bytes)

+ docs/.git/objects/31/0e7b443f14a92b46059c540620e2e3ec9eeecf view

binary file changed (absent → 918 bytes)

+ docs/.git/objects/33/d1dadf72d9a1c6217c5a6c7992dcdaaa343742 view

binary file changed (absent → 161 bytes)

+ docs/.git/objects/4c/2353910734c89633d869f0ffccf8f565c93221 view
@@ -0,0 +1,2 @@+x•ÎA+1@Q×=Eö‚$MǶ âÒx€˜T´vëBOï\Áí‡_[­cOiÕçR@%R$ÝJæ„å2äA‰Ng$JÈçÄAÝ$syv`62±Kô–eqž¢²Õ˜³75áÀ1x'ï~k3¥êM`÷ïŸûçp­2>6Úê(`À˜#zX£GtK]Özù¹Ódҋ5}Ao€v?¹C$
+ docs/.git/objects/5c/7dd6782bd7103baeb041d69fd3e17410ab46dd view

binary file changed (absent → 1552 bytes)

+ docs/.git/objects/63/50f4f119a8325852c5279f96ae5b0c34cce55f view

binary file changed (absent → 1142 bytes)

+ docs/.git/objects/70/15cd0af9b0fc60257cff8d057cee6a475f44d8 view

binary file changed (absent → 456 bytes)

+ docs/.git/objects/87/66065959fca5de5327f875dbb67559f69b52b6 view
@@ -0,0 +1,3 @@+x•’]oÓ0†¹î¯ð|µ]$^5!QêD*éÐ݇F*@Ó.\Ûk¼:vˆOšVˆÿŽmPѾïsìsÎJۏÏß¾¡'óÛ,ÿ~w‰+(5º[~X|ʎùz‘2ÏçèÛU~½@ãøå53N²†iB.o0Â@õž¶mãö"¶õšä÷dXã`–¼rÆNioWj㒿PƓɤ7©d"¥¥æ_	U$4j›à̐¢|_IŒx¿K0Ȑ@Ÿ"^°ÚIH–ùÇèF$¥ @˔’aÖÊlPQ˧[.™‰¹sÕR'ØÁ^KWH	0€;AçNðm°tXÇkUr5÷ŸaBX¾‰P:~ö¸Wîg¶e½Ö‹ô«”îè¡'Ù|–ÏF­2¶±5Ú2ôÔêNÏÐϊ­åŸŸžMMG„<>¦£— ¤Ïâʊ=R"Á¥2Ê?B¨m¿µ¢Ñ2Òʁ?­×ÌùÊpV>N¯»{GI•ÒF§T«?’²»ñ&_.“Ÿ%𢩢YE+áSÀ굯.™ò¬A%ÌgB«ÿ"fEc6R„š£¸W¾«S;ÅQÌ{ëÀ¬¾uÐÅý?ˆí%GQ—¾YÝAh§xa’ÐÄwCOù)”:ý
æ{.
+ docs/.git/objects/a3/3f00a997926762956b66487bc763c7500b5912 view

binary file changed (absent → 529 bytes)

+ docs/.git/objects/ad/296ab5c62662ad2f55c20cd75483c7014e3a9e view

binary file changed (absent → 1002 bytes)

+ docs/.git/objects/c8/298c807614715a3dd52fe3fddcd74b42d8dd51 view

binary file changed (absent → 1169 bytes)

+ docs/.git/objects/ca/7171c6a9384a3af595c1110538b011803b834c view

binary file changed (absent → 727 bytes)

+ docs/.git/objects/cc/746e214c400d625c17bb704964d2490009dcd6 view

binary file changed (absent → 554 bytes)

+ docs/.git/objects/da/b38cfd353bbdc462641543658ea8acd3eac19d view

binary file changed (absent → 928 bytes)

+ docs/.git/objects/e5/dc6abf9873d9eaf80c4e5d308832b23e5b18cd view

binary file changed (absent → 1028 bytes)

+ docs/.git/objects/e8/a9b100db71a644cc6cf513f26b5f44a42d17ab view

binary file changed (absent → 972 bytes)

+ docs/.git/objects/ec/a1b33fcd1c0373e31d108a81dca8be042fd89c view

binary file changed (absent → 672 bytes)

+ docs/.git/objects/f8/b79cfde7e99e07a48a906d6b0f43517cdee2b3 view

binary file changed (absent → 507 bytes)

+ docs/.git/objects/ff/6a9f5d733cd98051951968bb686e9766cf0a44 view

binary file changed (absent → 960 bytes)

+ docs/.git/objects/pack/pack-91a33bcc9daf02ed2b87eb63c5967322fb125afb.idx view

binary file changed (absent → 5776 bytes)

+ docs/.git/objects/pack/pack-91a33bcc9daf02ed2b87eb63c5967322fb125afb.pack view

binary file changed (absent → 49903 bytes)

+ docs/.git/packed-refs view
@@ -0,0 +1,3 @@+# pack-refs with: peeled fully-peeled +4ac44b6241517d43310da25b086e175b3b9c0b49 refs/remotes/origin/gh-pages+4ad51f9dc87b6aa48cb614030521d957b8498622 refs/remotes/origin/master
+ docs/.git/refs/heads/gh-pages view
@@ -0,0 +1,1 @@+4c2353910734c89633d869f0ffccf8f565c93221
+ docs/.git/refs/remotes/origin/HEAD view
@@ -0,0 +1,1 @@+ref: refs/remotes/origin/master
+ docs/.git/refs/remotes/origin/gh-pages view
@@ -0,0 +1,1 @@+4c2353910734c89633d869f0ffccf8f565c93221
+ docs/Ketchup-Auth.html view
@@ -0,0 +1,8 @@+<!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>Ketchup.Auth</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[+window.onload = function () {pageLoad();setSynopsis("mini_Ketchup-Auth.html");};+//]]>+</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 empty">&nbsp;</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr></table><p class="caption">Ketchup.Auth</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"><a href="#v:basicAuth">basicAuth</a> &#8759; [(ByteString, ByteString)] &#8594; ByteString &#8594; <a href="Ketchup-Httpd.html#t:Handler">Handler</a> &#8594; <a href="Ketchup-Httpd.html#t:Handler">Handler</a></li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><a name="v:basicAuth" class="def">basicAuth</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">&#8759; [(ByteString, ByteString)]</td><td class="doc"><p>List of (Username, Password)+</p></td></tr><tr><td class="src">&#8594; ByteString</td><td class="doc"><p>Authentication Realm+</p></td></tr><tr><td class="src">&#8594; <a href="Ketchup-Httpd.html#t:Handler">Handler</a></td><td class="doc"><p>Success Handler+</p></td></tr><tr><td class="src">&#8594; <a href="Ketchup-Httpd.html#t:Handler">Handler</a></td><td class="doc empty">&nbsp;</td></tr></table></div><div class="doc"><p>Performs HTTP Basic Auth+</p></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.13.2</p></div></body></html>
+ docs/Ketchup-Chunked.html view
@@ -0,0 +1,13 @@+<!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>Ketchup.Chunked</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[+window.onload = function () {pageLoad();setSynopsis("mini_Ketchup-Chunked.html");};+//]]>+</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 empty">&nbsp;</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr></table><p class="caption">Ketchup.Chunked</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"><a href="#v:chunkHeaders">chunkHeaders</a> &#8759; Socket &#8594; Int &#8594; [(ByteString, [ByteString])] &#8594; IO ()</li><li class="src short"><a href="#v:chunk">chunk</a> &#8759; Socket &#8594; ByteString &#8594; IO ()</li><li class="src short"><a href="#v:endchunk">endchunk</a> &#8759; Socket &#8594; IO ()</li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><a name="v:chunkHeaders" class="def">chunkHeaders</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">&#8759; Socket</td><td class="doc"><p>Socket to write to+</p></td></tr><tr><td class="src">&#8594; Int</td><td class="doc"><p>Status code+</p></td></tr><tr><td class="src">&#8594; [(ByteString, [ByteString])]</td><td class="doc"><p>Headers+</p></td></tr><tr><td class="src">&#8594; IO ()</td><td class="doc empty">&nbsp;</td></tr></table></div><div class="doc"><p>Send HTTP reply headers and begin a Chunked transmission+</p></div></div><div class="top"><p class="src"><a name="v:chunk" class="def">chunk</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">&#8759; Socket</td><td class="doc"><p>Socket to write to+</p></td></tr><tr><td class="src">&#8594; ByteString</td><td class="doc"><p>Content to write+</p></td></tr><tr><td class="src">&#8594; IO ()</td><td class="doc empty">&nbsp;</td></tr></table></div><div class="doc"><p>Sends a chunk+</p></div></div><div class="top"><p class="src"><a name="v:endchunk" class="def">endchunk</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">&#8759; Socket</td><td class="doc"><p>Socket to write to+</p></td></tr><tr><td class="src">&#8594; IO ()</td><td class="doc empty">&nbsp;</td></tr></table></div><div class="doc"><p>Send the final/closing chunk+</p></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.13.2</p></div></body></html>
+ docs/Ketchup-Httpd.html view
@@ -0,0 +1,15 @@+<!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>Ketchup.Httpd</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[+window.onload = function () {pageLoad();setSynopsis("mini_Ketchup-Httpd.html");};+//]]>+</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 empty">&nbsp;</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr></table><p class="caption">Ketchup.Httpd</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:HTTPRequest">HTTPRequest</a>  = <a href="#v:HTTPRequest">HTTPRequest</a> {<ul class="subs"><li><a href="#v:method">method</a> &#8759; ByteString</li><li><a href="#v:uri">uri</a> &#8759; ByteString</li><li><a href="#v:httpver">httpver</a> &#8759; ByteString</li><li><a href="#v:headers">headers</a> &#8759; <a href="Ketchup-Httpd.html#t:Headers">Headers</a></li><li><a href="#v:body">body</a> &#8759; ByteString</li></ul>}</li><li class="src short"><span class="keyword">type</span> <a href="#t:Headers">Headers</a> = [(ByteString, [ByteString])]</li><li class="src short"><span class="keyword">type</span> <a href="#t:Handler">Handler</a> = Socket &#8594; <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a> &#8594; IO ()</li><li class="src short"><a href="#v:listenHTTP">listenHTTP</a> &#8759; String &#8594; PortNumber &#8594; <a href="Ketchup-Httpd.html#t:Handler">Handler</a> &#8594; IO ()</li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><span class="keyword">data</span>  <a name="t:HTTPRequest" class="def">HTTPRequest</a>  </p><div class="doc"><p>HTTP Request type+ This holds a complete HTTP request+</p></div><div class="subs constructors"><p class="caption">Constructors</p><table><tr><td class="src"><a name="v:HTTPRequest" class="def">HTTPRequest</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:method" class="def">method</a> &#8759; ByteString</dt><dd class="doc"><p>Get HTTP Request Method (GET, POST etc.)+</p></dd><dt class="src"><a name="v:uri" class="def">uri</a> &#8759; ByteString</dt><dd class="doc"><p>Get Request URI+</p></dd><dt class="src"><a name="v:httpver" class="def">httpver</a> &#8759; ByteString</dt><dd class="doc"><p>Get HTTP Version+</p></dd><dt class="src"><a name="v:headers" class="def">headers</a> &#8759; <a href="Ketchup-Httpd.html#t:Headers">Headers</a></dt><dd class="doc"><p>Get HTTP Headers (header, [values])+</p></dd><dt class="src"><a name="v:body" class="def">body</a> &#8759; ByteString</dt><dd class="doc"><p>Get HTTP Post body (raw string)+</p></dd></dl><div class="clear"></div></div></td></tr></table></div><div class="subs instances"><p id="control.i:HTTPRequest" class="caption collapser" onclick="toggleSection('i:HTTPRequest')">Instances</p><div id="section.i:HTTPRequest" class="show"><table><tr><td class="src">Show <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a></td><td class="doc empty">&nbsp;</td></tr></table></div></div></div><div class="top"><p class="src"><span class="keyword">type</span> <a name="t:Headers" class="def">Headers</a> = [(ByteString, [ByteString])]</p></div><div class="top"><p class="src"><span class="keyword">type</span> <a name="t:Handler" class="def">Handler</a> = Socket &#8594; <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a> &#8594; IO ()</p></div><div class="top"><p class="src"><a name="v:listenHTTP" class="def">listenHTTP</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">&#8759; String</td><td class="doc"><p>Address to bind (ie. <a href="*.html">*</a>)+</p></td></tr><tr><td class="src">&#8594; PortNumber</td><td class="doc"><p>Port to listen on+</p></td></tr><tr><td class="src">&#8594; <a href="Ketchup-Httpd.html#t:Handler">Handler</a></td><td class="doc"><p>Route function to call+</p></td></tr><tr><td class="src">&#8594; IO ()</td><td class="doc empty">&nbsp;</td></tr></table></div><div class="doc"><p>Listens for incoming HTTP request+</p></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.13.2</p></div></body></html>
+ docs/Ketchup-Routing.html view
@@ -0,0 +1,9 @@+<!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>Ketchup.Routing</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[+window.onload = function () {pageLoad();setSynopsis("mini_Ketchup-Routing.html");};+//]]>+</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 empty">&nbsp;</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr></table><p class="caption">Ketchup.Routing</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">type</span> <a href="#t:Route">Route</a> = Socket &#8594; <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a> &#8594; (ByteString &#8594; Maybe ByteString) &#8594; IO ()</li><li class="src short"><a href="#v:route">route</a> &#8759; [(ByteString, <a href="Ketchup-Routing.html#t:Route">Route</a>)] &#8594; <a href="Ketchup-Httpd.html#t:Handler">Handler</a></li><li class="src short"><a href="#v:useHandler">useHandler</a> &#8759; <a href="Ketchup-Httpd.html#t:Handler">Handler</a> &#8594; <a href="Ketchup-Routing.html#t:Route">Route</a></li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><span class="keyword">type</span> <a name="t:Route" class="def">Route</a> = Socket &#8594; <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a> &#8594; (ByteString &#8594; Maybe ByteString) &#8594; IO ()</p></div><div class="top"><p class="src"><a name="v:route" class="def">route</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">&#8759; [(ByteString, <a href="Ketchup-Routing.html#t:Route">Route</a>)]</td><td class="doc"><p>Routes+</p></td></tr><tr><td class="src">&#8594; <a href="Ketchup-Httpd.html#t:Handler">Handler</a></td><td class="doc empty">&nbsp;</td></tr></table></div><div class="doc"><p>Router function+ Takes a list of routes and iterates through them for every requeust+</p></div></div><div class="top"><p class="src"><a name="v:useHandler" class="def">useHandler</a> &#8759; <a href="Ketchup-Httpd.html#t:Handler">Handler</a> &#8594; <a href="Ketchup-Routing.html#t:Route">Route</a></p><div class="doc"><p>Wrap a handler in a route+ Lets you use a handler (no parameters) as a route+</p></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.13.2</p></div></body></html>
+ docs/Ketchup-Static.html view
@@ -0,0 +1,7 @@+<!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>Ketchup.Static</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[+window.onload = function () {pageLoad();setSynopsis("mini_Ketchup-Static.html");};+//]]>+</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 empty">&nbsp;</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr></table><p class="caption">Ketchup.Static</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"><a href="#v:static">static</a> &#8759; ByteString &#8594; <a href="Ketchup-Httpd.html#t:Handler">Handler</a></li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><a name="v:static" class="def">static</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">&#8759; ByteString</td><td class="doc"><p>Path to serve static files from+</p></td></tr><tr><td class="src">&#8594; <a href="Ketchup-Httpd.html#t:Handler">Handler</a></td><td class="doc empty">&nbsp;</td></tr></table></div><div class="doc"><p>Static file handler+ Takes a directory and returns a route+</p></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.13.2</p></div></body></html>
+ docs/Ketchup-Utils.html view
@@ -0,0 +1,19 @@+<!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>Ketchup.Utils</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[+window.onload = function () {pageLoad();setSynopsis("mini_Ketchup-Utils.html");};+//]]>+</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 empty">&nbsp;</p></div><div id="content"><div id="module-header"><table class="info"><tr><th>Safe Haskell</th><td>None</td></tr></table><p class="caption">Ketchup.Utils</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"><a href="#v:trim">trim</a> &#8759; ByteString &#8594; ByteString</li><li class="src short"><a href="#v:breakBS">breakBS</a> &#8759; ByteString &#8594; ByteString &#8594; (ByteString, ByteString)</li><li class="src short"><a href="#v:fallback">fallback</a> &#8759;  Maybe a &#8594; a &#8594; a</li><li class="src short"><a href="#v:parseBody">parseBody</a> &#8759; ByteString &#8594; [(ByteString, ByteString)]</li><li class="src short"><a href="#v:sendReply">sendReply</a> &#8759; Socket &#8594; Int &#8594; [(ByteString, [ByteString])] &#8594; ByteString &#8594; IO ()</li><li class="src short"><a href="#v:sendBadRequest">sendBadRequest</a> &#8759; Socket &#8594; IO ()</li><li class="src short"><a href="#v:sendNotFound">sendNotFound</a> &#8759; Socket &#8594; IO ()</li><li class="src short"><a href="#v:statusMsg">statusMsg</a> &#8759; Int &#8594; ByteString</li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><a name="v:trim" class="def">trim</a> &#8759; ByteString &#8594; ByteString</p><div class="doc"><p>Trim whitespace from headers+</p></div></div><div class="top"><p class="src"><a name="v:breakBS" class="def">breakBS</a> &#8759; ByteString &#8594; ByteString &#8594; (ByteString, ByteString)</p><div class="doc"><p>ByteString breakSubstring wrapper that drops delimiters+</p></div></div><div class="top"><p class="src"><a name="v:fallback" class="def">fallback</a> &#8759;  Maybe a &#8594; a &#8594; a</p></div><div class="top"><p class="src"><a name="v:parseBody" class="def">parseBody</a> &#8759; ByteString &#8594; [(ByteString, ByteString)]</p><div class="doc"><p>Parse a URL-encoded Request+</p></div></div><div class="top"><p class="src"><a name="v:sendReply" class="def">sendReply</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">&#8759; Socket</td><td class="doc"><p>Socket to write to+</p></td></tr><tr><td class="src">&#8594; Int</td><td class="doc"><p>Status Code to send+</p></td></tr><tr><td class="src">&#8594; [(ByteString, [ByteString])]</td><td class="doc"><p>HTTP headers (<a href="Header.html">Header</a>,[<a href="value1.html">value1</a>, <a href="value2.html">value2</a>])+</p></td></tr><tr><td class="src">&#8594; ByteString</td><td class="doc"><p>Body+</p></td></tr><tr><td class="src">&#8594; IO ()</td><td class="doc empty">&nbsp;</td></tr></table></div><div class="doc"><p>Send a HTTP reply+ Sends a reply with the given parameters+</p></div></div><div class="top"><p class="src"><a name="v:sendBadRequest" class="def">sendBadRequest</a> &#8759; Socket &#8594; IO ()</p><div class="doc"><p>Send 400 Bad Request error+</p></div></div><div class="top"><p class="src"><a name="v:sendNotFound" class="def">sendNotFound</a> &#8759; Socket &#8594; IO ()</p><div class="doc"><p>Send 404 Not Found error+</p></div></div><div class="top"><p class="src"><a name="v:statusMsg" class="def">statusMsg</a></p><div class="subs arguments"><p class="caption">Arguments</p><table><tr><td class="src">&#8759; Int</td><td class="doc"><p>Status code (ex. 404)+</p></td></tr><tr><td class="src">&#8594; ByteString</td><td class="doc"><p>Status message (ex. <a href="404 Not Found.html">404 Not Found</a>)+</p></td></tr></table></div><div class="doc"><p>Status Messages+ Returns status message from a given status id+</p></div></div></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.13.2</p></div></body></html>
+ docs/doc-index.html view
@@ -0,0 +1,4 @@+<!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> (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[+window.onload = function () {pageLoad();};+//]]>+</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 empty">&nbsp;</p></div><div id="content"><div id="index"><p class="caption">Index</p><table><tr><td class="src">basicAuth</td><td class="module"><a href="Ketchup-Auth.html#v:basicAuth">Ketchup.Auth</a></td></tr><tr><td class="src">body</td><td class="module"><a href="Ketchup-Httpd.html#v:body">Ketchup.Httpd</a></td></tr><tr><td class="src">breakBS</td><td class="module"><a href="Ketchup-Utils.html#v:breakBS">Ketchup.Utils</a></td></tr><tr><td class="src">chunk</td><td class="module"><a href="Ketchup-Chunked.html#v:chunk">Ketchup.Chunked</a></td></tr><tr><td class="src">chunkHeaders</td><td class="module"><a href="Ketchup-Chunked.html#v:chunkHeaders">Ketchup.Chunked</a></td></tr><tr><td class="src">endchunk</td><td class="module"><a href="Ketchup-Chunked.html#v:endchunk">Ketchup.Chunked</a></td></tr><tr><td class="src">fallback</td><td class="module"><a href="Ketchup-Utils.html#v:fallback">Ketchup.Utils</a></td></tr><tr><td class="src">Handler</td><td class="module"><a href="Ketchup-Httpd.html#t:Handler">Ketchup.Httpd</a></td></tr><tr><td class="src">Headers</td><td class="module"><a href="Ketchup-Httpd.html#t:Headers">Ketchup.Httpd</a></td></tr><tr><td class="src">headers</td><td class="module"><a href="Ketchup-Httpd.html#v:headers">Ketchup.Httpd</a></td></tr><tr><td class="src">HTTPRequest</td><td>&nbsp;</td></tr><tr><td class="alt">1 (Type/Class)</td><td class="module"><a href="Ketchup-Httpd.html#t:HTTPRequest">Ketchup.Httpd</a></td></tr><tr><td class="alt">2 (Data Constructor)</td><td class="module"><a href="Ketchup-Httpd.html#v:HTTPRequest">Ketchup.Httpd</a></td></tr><tr><td class="src">httpver</td><td class="module"><a href="Ketchup-Httpd.html#v:httpver">Ketchup.Httpd</a></td></tr><tr><td class="src">listenHTTP</td><td class="module"><a href="Ketchup-Httpd.html#v:listenHTTP">Ketchup.Httpd</a></td></tr><tr><td class="src">method</td><td class="module"><a href="Ketchup-Httpd.html#v:method">Ketchup.Httpd</a></td></tr><tr><td class="src">parseBody</td><td class="module"><a href="Ketchup-Utils.html#v:parseBody">Ketchup.Utils</a></td></tr><tr><td class="src">Route</td><td class="module"><a href="Ketchup-Routing.html#t:Route">Ketchup.Routing</a></td></tr><tr><td class="src">route</td><td class="module"><a href="Ketchup-Routing.html#v:route">Ketchup.Routing</a></td></tr><tr><td class="src">sendBadRequest</td><td class="module"><a href="Ketchup-Utils.html#v:sendBadRequest">Ketchup.Utils</a></td></tr><tr><td class="src">sendNotFound</td><td class="module"><a href="Ketchup-Utils.html#v:sendNotFound">Ketchup.Utils</a></td></tr><tr><td class="src">sendReply</td><td class="module"><a href="Ketchup-Utils.html#v:sendReply">Ketchup.Utils</a></td></tr><tr><td class="src">static</td><td class="module"><a href="Ketchup-Static.html#v:static">Ketchup.Static</a></td></tr><tr><td class="src">statusMsg</td><td class="module"><a href="Ketchup-Utils.html#v:statusMsg">Ketchup.Utils</a></td></tr><tr><td class="src">trim</td><td class="module"><a href="Ketchup-Utils.html#v:trim">Ketchup.Utils</a></td></tr><tr><td class="src">uri</td><td class="module"><a href="Ketchup-Httpd.html#v:uri">Ketchup.Httpd</a></td></tr><tr><td class="src">useHandler</td><td class="module"><a href="Ketchup-Routing.html#v:useHandler">Ketchup.Routing</a></td></tr></table></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.13.2</p></div></body></html>
+ docs/frames.html view
@@ -0,0 +1,30 @@+<!DOCTYPE html +     PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">+<html xmlns="http://www.w3.org/1999/xhtml">+<head>+<title></title>+<script src="haddock-util.js" type="text/javascript"></script>+<script type="text/javascript"><!--+/*++  The synopsis frame needs to be updated using javascript, so we hide+  it by default and only show it if javascript is enabled.++  TODO: provide some means to disable it.+*/+function load() {+  var d = document.getElementById("inner-fs");+  d.rows = "50%,50%";+  postReframe();+}+--></script>+</head>+<frameset id="outer-fs" cols="25%,75%" onload="load()">+  <frameset id="inner-fs" rows="100%,0%">+    <frame src="index-frames.html" name="modules" />+    <frame src="" name="synopsis" />+  </frameset>+  <frame src="index.html" name="main" />+</frameset>+</html>
+ docs/haddock-util.js view
@@ -0,0 +1,344 @@+// Haddock JavaScript utilities++var rspace = /\s\s+/g,+	  rtrim = /^\s+|\s+$/g;++function spaced(s) { return (" " + s + " ").replace(rspace, " "); }+function trim(s)   { return s.replace(rtrim, ""); }++function hasClass(elem, value) {+  var className = spaced(elem.className || "");+  return className.indexOf( " " + value + " " ) >= 0;+}++function addClass(elem, value) {+  var className = spaced(elem.className || "");+  if ( className.indexOf( " " + value + " " ) < 0 ) {+    elem.className = trim(className + " " + value);+  }+}++function removeClass(elem, value) {+  var className = spaced(elem.className || "");+  className = className.replace(" " + value + " ", " ");+  elem.className = trim(className);+}++function toggleClass(elem, valueOn, valueOff, bool) {+  if (bool == null) { bool = ! hasClass(elem, valueOn); }+  if (bool) {+    removeClass(elem, valueOff);+    addClass(elem, valueOn);+  }+  else {+    removeClass(elem, valueOn);+    addClass(elem, valueOff);+  }+  return bool;+}+++function makeClassToggle(valueOn, valueOff)+{+  return function(elem, bool) {+    return toggleClass(elem, valueOn, valueOff, bool);+  }+}++toggleShow = makeClassToggle("show", "hide");+toggleCollapser = makeClassToggle("collapser", "expander");++function toggleSection(id)+{+  var b = toggleShow(document.getElementById("section." + id));+  toggleCollapser(document.getElementById("control." + id), b);+  rememberCollapsed(id, b);+  return b;+}++var collapsed = {};+function rememberCollapsed(id, b)+{+  if(b)+    delete collapsed[id]+  else+    collapsed[id] = null;++  var sections = [];+  for(var i in collapsed)+  {+    if(collapsed.hasOwnProperty(i))+      sections.push(i);+  }+  // cookie specific to this page; don't use setCookie which sets path=/+  document.cookie = "collapsed=" + escape(sections.join('+'));+}++function restoreCollapsed()+{+  var cookie = getCookie("collapsed");+  if(!cookie)+    return;++  var ids = cookie.split('+');+  for(var i in ids)+  {+    if(document.getElementById("section." + ids[i]))+      toggleSection(ids[i]);+  }+}++function setCookie(name, value) {+  document.cookie = name + "=" + escape(value) + ";path=/;";+}++function clearCookie(name) {+  document.cookie = name + "=;path=/;expires=Thu, 01-Jan-1970 00:00:01 GMT;";+}++function getCookie(name) {+  var nameEQ = name + "=";+  var ca = document.cookie.split(';');+  for(var i=0;i < ca.length;i++) {+    var c = ca[i];+    while (c.charAt(0)==' ') c = c.substring(1,c.length);+    if (c.indexOf(nameEQ) == 0) {+      return unescape(c.substring(nameEQ.length,c.length));+    }+  }+  return null;+}++++var max_results = 75; // 50 is not enough to search for map in the base libraries+var shown_range = null;+var last_search = null;++function quick_search()+{+    perform_search(false);+}++function full_search()+{+    perform_search(true);+}+++function perform_search(full)+{+    var text = document.getElementById("searchbox").value.toLowerCase();+    if (text == last_search && !full) return;+    last_search = text;+    +    var table = document.getElementById("indexlist");+    var status = document.getElementById("searchmsg");+    var children = table.firstChild.childNodes;+    +    // first figure out the first node with the prefix+    var first = bisect(-1);+    var last = (first == -1 ? -1 : bisect(1));++    if (first == -1)+    {+        table.className = "";+        status.innerHTML = "No results found, displaying all";+    }+    else if (first == 0 && last == children.length - 1)+    {+        table.className = "";+        status.innerHTML = "";+    }+    else if (last - first >= max_results && !full)+    {+        table.className = "";+        status.innerHTML = "More than " + max_results + ", press Search to display";+    }+    else+    {+        // decide what you need to clear/show+        if (shown_range)+            setclass(shown_range[0], shown_range[1], "indexrow");+        setclass(first, last, "indexshow");+        shown_range = [first, last];+        table.className = "indexsearch";+        status.innerHTML = "";+    }++    +    function setclass(first, last, status)+    {+        for (var i = first; i <= last; i++)+        {+            children[i].className = status;+        }+    }+    +    +    // do a binary search, treating 0 as ...+    // return either -1 (no 0's found) or location of most far match+    function bisect(dir)+    {+        var first = 0, finish = children.length - 1;+        var mid, success = false;++        while (finish - first > 3)+        {+            mid = Math.floor((finish + first) / 2);++            var i = checkitem(mid);+            if (i == 0) i = dir;+            if (i == -1)+                finish = mid;+            else+                first = mid;+        }+        var a = (dir == 1 ? first : finish);+        var b = (dir == 1 ? finish : first);+        for (var i = b; i != a - dir; i -= dir)+        {+            if (checkitem(i) == 0) return i;+        }+        return -1;+    }    +    +    +    // from an index, decide what the result is+    // 0 = match, -1 is lower, 1 is higher+    function checkitem(i)+    {+        var s = getitem(i).toLowerCase().substr(0, text.length);+        if (s == text) return 0;+        else return (s > text ? -1 : 1);+    }+    +    +    // from an index, get its string+    // this abstracts over alternates+    function getitem(i)+    {+        for ( ; i >= 0; i--)+        {+            var s = children[i].firstChild.firstChild.data;+            if (s.indexOf(' ') == -1)+                return s;+        }+        return ""; // should never be reached+    }+}++function setSynopsis(filename) {+    if (parent.window.synopsis) {+        if (parent.window.synopsis.location.replace) {+            // In Firefox this avoids adding the change to the history.+            parent.window.synopsis.location.replace(filename);+        } else {+            parent.window.synopsis.location = filename;+        }+    }+}++function addMenuItem(html) {+  var menu = document.getElementById("page-menu");+  if (menu) {+    var btn = menu.firstChild.cloneNode(false);+    btn.innerHTML = html;+    menu.appendChild(btn);+  }+}++function adjustForFrames() {+  var bodyCls;+  +  if (parent.location.href == window.location.href) {+    // not in frames, so add Frames button+    addMenuItem("<a href='#' onclick='reframe();return true;'>Frames</a>");+    bodyCls = "no-frame";+  }+  else {+    bodyCls = "in-frame";+  }+  addClass(document.body, bodyCls);+}++function reframe() {+  setCookie("haddock-reframe", document.URL);+  window.location = "frames.html";+}++function postReframe() {+  var s = getCookie("haddock-reframe");+  if (s) {+    parent.window.main.location = s;+    clearCookie("haddock-reframe");+  }+}++function styles() {+  var i, a, es = document.getElementsByTagName("link"), rs = [];+  for (i = 0; a = es[i]; i++) {+    if(a.rel.indexOf("style") != -1 && a.title) {+      rs.push(a);+    }+  }+  return rs;+}++function addStyleMenu() {+  var as = styles();+  var i, a, btns = "";+  for(i=0; a = as[i]; i++) {+    btns += "<li><a href='#' onclick=\"setActiveStyleSheet('"+      + a.title + "'); return false;\">"+      + a.title + "</a></li>"+  }+  if (as.length > 1) {+    var h = "<div id='style-menu-holder'>"+      + "<a href='#' onclick='styleMenu(); return false;'>Style &#9662;</a>"+      + "<ul id='style-menu' class='hide'>" + btns + "</ul>"+      + "</div>";+    addMenuItem(h);+  }+}++function setActiveStyleSheet(title) {+  var as = styles();+  var i, a, found;+  for(i=0; a = as[i]; i++) {+    a.disabled = true;+          // need to do this always, some browsers are edge triggered+    if(a.title == title) {+      found = a;+    }+  }+  if (found) {+    found.disabled = false;+    setCookie("haddock-style", title);+  }+  else {+    as[0].disabled = false;+    clearCookie("haddock-style");+  }+  styleMenu(false);+}++function resetStyle() {+  var s = getCookie("haddock-style");+  if (s) setActiveStyleSheet(s);+}+++function styleMenu(show) {+  var m = document.getElementById('style-menu');+  if (m) toggleShow(m, show);+}+++function pageLoad() {+  addStyleMenu();+  adjustForFrames();+  resetStyle();+  restoreCollapsed();+}+
+ docs/hslogo-16.png view

binary file changed (absent → 1684 bytes)

+ docs/index-frames.html view
@@ -0,0 +1,4 @@+<!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></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[+window.onload = function () {pageLoad();};+//]]>+</script></head><body id="mini"><div id="module-list"><p class="caption">Modules</p><ul><li class="module"><a href="Ketchup-Auth.html" target="main">Ketchup.Auth</a></li><li class="module"><a href="Ketchup-Chunked.html" target="main">Ketchup.Chunked</a></li><li class="module"><a href="Ketchup-Httpd.html" target="main">Ketchup.Httpd</a></li><li class="module"><a href="Ketchup-Routing.html" target="main">Ketchup.Routing</a></li><li class="module"><a href="Ketchup-Static.html" target="main">Ketchup.Static</a></li><li class="module"><a href="Ketchup-Utils.html" target="main">Ketchup.Utils</a></li></ul></div></body></html>
+ docs/index.html view
@@ -0,0 +1,4 @@+<!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></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[+window.onload = function () {pageLoad();};+//]]>+</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 empty">&nbsp;</p></div><div id="content"><div id="module-list"><p class="caption">Modules</p><ul><li><span id="control.n.1" class="module collapser" onclick="toggleSection('n.1')">Ketchup</span><ul id="section.n.1" class="show"><li><span class="module"><a href="Ketchup-Auth.html">Ketchup.Auth</a></span></li><li><span class="module"><a href="Ketchup-Chunked.html">Ketchup.Chunked</a></span></li><li><span class="module"><a href="Ketchup-Httpd.html">Ketchup.Httpd</a></span></li><li><span class="module"><a href="Ketchup-Routing.html">Ketchup.Routing</a></span></li><li><span class="module"><a href="Ketchup-Static.html">Ketchup.Static</a></span></li><li><span class="module"><a href="Ketchup-Utils.html">Ketchup.Utils</a></span></li></ul></li></ul></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.13.2</p></div></body></html>
+ docs/main.txt view
@@ -0,0 +1,87 @@+-- Hoogle documentation, generated by Haddock+-- See Hoogle, http://www.haskell.org/hoogle/++@package main++module Ketchup.Utils++-- | Trim whitespace from headers+trim :: ByteString -> ByteString++-- | ByteString breakSubstring wrapper that drops delimiters+breakBS :: ByteString -> ByteString -> (ByteString, ByteString)+fallback :: Maybe a -> a -> a++-- | Parse a URL-encoded Request+parseBody :: ByteString -> [(ByteString, ByteString)]++-- | Send a HTTP reply Sends a reply with the given parameters+sendReply :: Socket -> Int -> [(ByteString, [ByteString])] -> ByteString -> IO ()++-- | Send 400 Bad Request error+sendBadRequest :: Socket -> IO ()++-- | Send 404 Not Found error+sendNotFound :: Socket -> IO ()++-- | Status Messages Returns status message from a given status id+statusMsg :: Int -> ByteString++module Ketchup.Httpd++-- | HTTP Request type This holds a complete HTTP request+data HTTPRequest+HTTPRequest :: ByteString -> ByteString -> ByteString -> Headers -> ByteString -> HTTPRequest++-- | Get HTTP Request Method (GET, POST etc.)+method :: HTTPRequest -> ByteString++-- | Get Request URI+uri :: HTTPRequest -> ByteString++-- | Get HTTP Version+httpver :: HTTPRequest -> ByteString++-- | Get HTTP Headers (header, [values])+headers :: HTTPRequest -> Headers++-- | Get HTTP Post body (raw string)+body :: HTTPRequest -> ByteString+type Headers = [(ByteString, [ByteString])]+type Handler = Socket -> HTTPRequest -> IO ()++-- | Listens for incoming HTTP request+listenHTTP :: String -> PortNumber -> Handler -> IO ()+instance Show HTTPRequest++module Ketchup.Chunked++-- | Send HTTP reply headers and begin a Chunked transmission+chunkHeaders :: Socket -> Int -> [(ByteString, [ByteString])] -> IO ()++-- | Sends a chunk+chunk :: Socket -> ByteString -> IO ()++-- | Send the final/closing chunk+endchunk :: Socket -> IO ()++module Ketchup.Routing+type Route = Socket -> HTTPRequest -> (ByteString -> Maybe ByteString) -> IO ()++-- | Router function Takes a list of routes and iterates through them for+--   every requeust+route :: [(ByteString, Route)] -> Handler++-- | Wrap a handler in a route Lets you use a handler (no parameters) as a+--   route+useHandler :: Handler -> Route++module Ketchup.Static++-- | Static file handler Takes a directory and returns a route+static :: ByteString -> Handler++module Ketchup.Auth++-- | Performs HTTP Basic Auth+basicAuth :: [(ByteString, ByteString)] -> ByteString -> Handler -> Handler
+ docs/mini_Ketchup-Auth.html view
@@ -0,0 +1,4 @@+<!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>Ketchup.Auth</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[+window.onload = function () {pageLoad();};+//]]>+</script></head><body id="mini"><div id="module-header"><p class="caption">Ketchup.Auth</p></div><div id="interface"><div class="top"><p class="src"><a href="Ketchup-Auth.html#v:basicAuth" target="main">basicAuth</a></p></div></div></body></html>
+ docs/mini_Ketchup-Chunked.html view
@@ -0,0 +1,4 @@+<!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>Ketchup.Chunked</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[+window.onload = function () {pageLoad();};+//]]>+</script></head><body id="mini"><div id="module-header"><p class="caption">Ketchup.Chunked</p></div><div id="interface"><div class="top"><p class="src"><a href="Ketchup-Chunked.html#v:chunkHeaders" target="main">chunkHeaders</a></p></div><div class="top"><p class="src"><a href="Ketchup-Chunked.html#v:chunk" target="main">chunk</a></p></div><div class="top"><p class="src"><a href="Ketchup-Chunked.html#v:endchunk" target="main">endchunk</a></p></div></div></body></html>
+ docs/mini_Ketchup-Httpd.html view
@@ -0,0 +1,4 @@+<!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>Ketchup.Httpd</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[+window.onload = function () {pageLoad();};+//]]>+</script></head><body id="mini"><div id="module-header"><p class="caption">Ketchup.Httpd</p></div><div id="interface"><div class="top"><p class="src"><span class="keyword">data</span> <a href="Ketchup-Httpd.html#t:HTTPRequest" target="main">HTTPRequest</a> </p></div><div class="top"><p class="src"><span class="keyword">type</span> <a href="Ketchup-Httpd.html#t:Headers" target="main">Headers</a> </p></div><div class="top"><p class="src"><span class="keyword">type</span> <a href="Ketchup-Httpd.html#t:Handler" target="main">Handler</a> </p></div><div class="top"><p class="src"><a href="Ketchup-Httpd.html#v:listenHTTP" target="main">listenHTTP</a></p></div></div></body></html>
+ docs/mini_Ketchup-Routing.html view
@@ -0,0 +1,4 @@+<!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>Ketchup.Routing</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[+window.onload = function () {pageLoad();};+//]]>+</script></head><body id="mini"><div id="module-header"><p class="caption">Ketchup.Routing</p></div><div id="interface"><div class="top"><p class="src"><span class="keyword">type</span> <a href="Ketchup-Routing.html#t:Route" target="main">Route</a> </p></div><div class="top"><p class="src"><a href="Ketchup-Routing.html#v:route" target="main">route</a></p></div><div class="top"><p class="src"><a href="Ketchup-Routing.html#v:useHandler" target="main">useHandler</a></p></div></div></body></html>
+ docs/mini_Ketchup-Static.html view
@@ -0,0 +1,4 @@+<!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>Ketchup.Static</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[+window.onload = function () {pageLoad();};+//]]>+</script></head><body id="mini"><div id="module-header"><p class="caption">Ketchup.Static</p></div><div id="interface"><div class="top"><p class="src"><a href="Ketchup-Static.html#v:static" target="main">static</a></p></div></div></body></html>
+ docs/mini_Ketchup-Utils.html view
@@ -0,0 +1,4 @@+<!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>Ketchup.Utils</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[+window.onload = function () {pageLoad();};+//]]>+</script></head><body id="mini"><div id="module-header"><p class="caption">Ketchup.Utils</p></div><div id="interface"><div class="top"><p class="src"><a href="Ketchup-Utils.html#v:trim" target="main">trim</a></p></div><div class="top"><p class="src"><a href="Ketchup-Utils.html#v:breakBS" target="main">breakBS</a></p></div><div class="top"><p class="src"><a href="Ketchup-Utils.html#v:fallback" target="main">fallback</a></p></div><div class="top"><p class="src"><a href="Ketchup-Utils.html#v:parseBody" target="main">parseBody</a></p></div><div class="top"><p class="src"><a href="Ketchup-Utils.html#v:sendReply" target="main">sendReply</a></p></div><div class="top"><p class="src"><a href="Ketchup-Utils.html#v:sendBadRequest" target="main">sendBadRequest</a></p></div><div class="top"><p class="src"><a href="Ketchup-Utils.html#v:sendNotFound" target="main">sendNotFound</a></p></div><div class="top"><p class="src"><a href="Ketchup-Utils.html#v:statusMsg" target="main">statusMsg</a></p></div></div></body></html>
+ docs/minus.gif view

binary file changed (absent → 56 bytes)

+ docs/ocean.css view
@@ -0,0 +1,546 @@+/* @group Fundamentals */++* { margin: 0; padding: 0 }++/* Is this portable? */+html {+  background-color: white;+  width: 100%;+  height: 100%;+}++body {+  background: white;+  color: black;+  text-align: left;+  min-height: 100%;+  position: relative;+}++p {+  margin: 0.8em 0;+}++ul, ol {+  margin: 0.8em 0 0.8em 2em;+}++dl {+  margin: 0.8em 0;+}++dt {+  font-weight: bold;+}+dd {+  margin-left: 2em;+}++a { text-decoration: none; }+a[href]:link { color: rgb(196,69,29); }+a[href]:visited { color: rgb(171,105,84); }+a[href]:hover { text-decoration:underline; }++/* @end */++/* @group Fonts & Sizes */++/* Basic technique & IE workarounds from YUI 3+   For reasons, see:+      http://yui.yahooapis.com/3.1.1/build/cssfonts/fonts.css+ */+ +body {+	font:13px/1.4 sans-serif;+	*font-size:small; /* for IE */+	*font:x-small; /* for IE in quirks mode */+}++h1 { font-size: 146.5%; /* 19pt */ } +h2 { font-size: 131%;   /* 17pt */ }+h3 { font-size: 116%;   /* 15pt */ }+h4 { font-size: 100%;   /* 13pt */ }+h5 { font-size: 100%;   /* 13pt */ }++select, input, button, textarea {+	font:99% sans-serif;+}++table {+	font-size:inherit;+	font:100%;+}++pre, code, kbd, samp, tt, .src {+	font-family:monospace;+	*font-size:108%;+	line-height: 124%;+}++.links, .link {+  font-size: 85%; /* 11pt */+}++#module-header .caption {+  font-size: 182%; /* 24pt */+}++.info  {+  font-size: 85%; /* 11pt */+}++#table-of-contents, #synopsis  {+  /* font-size: 85%; /* 11pt */+}+++/* @end */++/* @group Common */++.caption, h1, h2, h3, h4, h5, h6 { +  font-weight: bold;+  color: rgb(78,98,114);+  margin: 0.8em 0 0.4em;+}++* + h1, * + h2, * + h3, * + h4, * + h5, * + h6 {+  margin-top: 2em;+}++h1 + h2, h2 + h3, h3 + h4, h4 + h5, h5 + h6 {+  margin-top: inherit;+}++ul.links {+  list-style: none;+  text-align: left;+  float: right;+  display: inline-table;+  margin: 0 0 0 1em;+}++ul.links li {+  display: inline;+  border-left: 1px solid #d5d5d5; +  white-space: nowrap;+  padding: 0;+}++ul.links li a {+  padding: 0.2em 0.5em;+}++.hide { display: none; }+.show { display: inherit; }+.clear { clear: both; }++.collapser {+  background-image: url(minus.gif);+  background-repeat: no-repeat;+}+.expander {+  background-image: url(plus.gif);+  background-repeat: no-repeat;+}+p.caption.collapser,+p.caption.expander {+  background-position: 0 0.4em;+}+.collapser, .expander {+  padding-left: 14px;+  margin-left: -14px;+  cursor: pointer;+}++pre {+  padding: 0.25em;+  margin: 0.8em 0;+  background: rgb(229,237,244);+  overflow: auto;+  border-bottom: 0.25em solid white;+  /* white border adds some space below the box to compensate+     for visual extra space that paragraphs have between baseline+     and the bounding box */+}++.src {+  background: #f0f0f0;+  padding: 0.2em 0.5em;+}++.keyword { font-weight: normal; }+.def { font-weight: bold; }+++/* @end */++/* @group Page Structure */++#content {+  margin: 0 auto;+  padding: 0 2em 6em;+}++#package-header {+  background: rgb(41,56,69);+  border-top: 5px solid rgb(78,98,114);+  color: #ddd;+  padding: 0.2em;+  position: relative;+  text-align: left;+}++#package-header .caption {+  background: url(hslogo-16.png) no-repeat 0em;+  color: white;+  margin: 0 2em;+  font-weight: normal;+  font-style: normal;+  padding-left: 2em;+}++#package-header a:link, #package-header a:visited { color: white; }+#package-header a:hover { background: rgb(78,98,114); }++#module-header .caption {+  color: rgb(78,98,114);+  font-weight: bold;+  border-bottom: 1px solid #ddd;+}++table.info {+  float: right;+  padding: 0.5em 1em;+  border: 1px solid #ddd;+  color: rgb(78,98,114);+  background-color: #fff;+  max-width: 40%;+  border-spacing: 0;+  position: relative;+  top: -0.5em;+  margin: 0 0 0 2em;+}++.info th {+	padding: 0 1em 0 0;+}++div#style-menu-holder {+  position: relative;+  z-index: 2;+  display: inline;+}++#style-menu {+  position: absolute;+  z-index: 1;+  overflow: visible;+  background: #374c5e;+  margin: 0;+  text-align: center;+  right: 0;+  padding: 0;+  top: 1.25em;+}++#style-menu li {+	display: list-item;+	border-style: none;+	margin: 0;+	padding: 0;+	color: #000;+	list-style-type: none;+}++#style-menu li + li {+	border-top: 1px solid #919191;+}++#style-menu a {+  width: 6em;+  padding: 3px;+  display: block;+}++#footer {+  background: #ddd;+  border-top: 1px solid #aaa;+  padding: 0.5em 0;+  color: #666;+  text-align: center;+  position: absolute;+  bottom: 0;+  width: 100%;+  height: 3em;+}++/* @end */++/* @group Front Matter */++#table-of-contents {+  float: right;+  clear: right;+  background: #faf9dc;+  border: 1px solid #d8d7ad;+  padding: 0.5em 1em;+  max-width: 20em;+  margin: 0.5em 0 1em 1em;+}++#table-of-contents .caption {+  text-align: center;+  margin: 0;+}++#table-of-contents ul {+  list-style: none;+  margin: 0;+}++#table-of-contents ul ul {+  margin-left: 2em;+}++#description .caption {+  display: none;+}++#synopsis {+  display: none;+}++.no-frame #synopsis {+  display: block;+  position: fixed;+  right: 0;+  height: 80%;+  top: 10%;+  padding: 0;+}++#synopsis .caption {+  float: left;+  width: 29px;+  color: rgba(255,255,255,0);+  height: 110px;+  margin: 0;+  font-size: 1px;+  padding: 0;+}++#synopsis p.caption.collapser {+  background: url(synopsis.png) no-repeat -64px -8px;+}++#synopsis p.caption.expander {+  background: url(synopsis.png) no-repeat 0px -8px;+}++#synopsis ul {+  height: 100%;+  overflow: auto;+  padding: 0.5em;+  margin: 0;+}++#synopsis ul ul {+  overflow: hidden;+}++#synopsis ul,+#synopsis ul li.src {+  background-color: #faf9dc;+  white-space: nowrap;+  list-style: none;+  margin-left: 0;+}++/* @end */++/* @group Main Content */++#interface div.top { margin: 2em 0; }+#interface h1 + div.top,+#interface h2 + div.top,+#interface h3 + div.top,+#interface h4 + div.top,+#interface h5 + div.top {+ 	margin-top: 1em;+}+#interface p.src .link {+  float: right;+  color: #919191;+  border-left: 1px solid #919191;+  background: #f0f0f0;+  padding: 0 0.5em 0.2em;+  margin: 0 -0.5em 0 0.5em;+}++#interface table { border-spacing: 2px; }+#interface td {+  vertical-align: top;+  padding-left: 0.5em;+}+#interface td.src {+  white-space: nowrap;+}+#interface td.doc p {+  margin: 0;+}+#interface td.doc p + p {+  margin-top: 0.8em;+}++.subs dl {+  margin: 0;+}++.subs dt {+  float: left;+  clear: left;+  display: block;+  margin: 1px 0;+}++.subs dd {+  float: right;+  width: 90%;+  display: block;+  padding-left: 0.5em;+  margin-bottom: 0.5em;+}++.subs dd.empty {+  display: none;+}++.subs dd p {+  margin: 0;+}++.top p.src {+  border-top: 1px solid #ccc;+}++.subs, .doc {+  /* use this selector for one level of indent */+  padding-left: 2em;+}++.warning {+  color: red;+}++.arguments {+  margin-top: -0.4em;+}+.arguments .caption {+  display: none;+}++.fields { padding-left: 1em; }++.fields .caption { display: none; }++.fields p { margin: 0 0; }++/* this seems bulky to me+.methods, .constructors {+  background: #f8f8f8;+  border: 1px solid #eee;+}+*/++/* @end */++/* @group Auxillary Pages */++#mini {+  margin: 0 auto;+  padding: 0 1em 1em;+}++#mini > * {+  font-size: 93%; /* 12pt */  +}++#mini #module-list .caption,+#mini #module-header .caption {+  font-size: 125%; /* 15pt */+}++#mini #interface h1,+#mini #interface h2,+#mini #interface h3,+#mini #interface h4 {+  font-size: 109%; /* 13pt */+  margin: 1em 0 0;+}++#mini #interface .top,+#mini #interface .src {+  margin: 0;+}++#mini #module-list ul {+  list-style: none;+  margin: 0;+}++#alphabet ul {+	list-style: none;+	padding: 0;+	margin: 0.5em 0 0;+	text-align: center;+}++#alphabet li {+	display: inline;+	margin: 0 0.25em;+}++#alphabet a {+	font-weight: bold;+}++#index .caption,+#module-list .caption { font-size: 131%; /* 17pt */ }++#index table {+  margin-left: 2em;+}++#index .src {+  font-weight: bold;+}+#index .alt {+  font-size: 77%; /* 10pt */+  font-style: italic;+  padding-left: 2em;+}++#index td + td {+  padding-left: 1em;+}++#module-list ul {+  list-style: none;+  margin: 0 0 0 2em;+}++#module-list li {+  clear: right;+}++#module-list span.collapser,+#module-list span.expander {+  background-position: 0 0.3em;+}++#module-list .package {+  float: right;+}++/* @end */
+ docs/plus.gif view

binary file changed (absent → 59 bytes)

+ docs/synopsis.png view

binary file changed (absent → 11327 bytes)

example.hs view
@@ -3,14 +3,14 @@ module Main where
 
 import qualified Data.ByteString as B
-import qualified Data.Map as M
+import           Ketchup.Auth
 import           Ketchup.Httpd
 import           Ketchup.Routing
 import           Ketchup.Utils
 import           Ketchup.Chunked
 import           Ketchup.Static
 
-handle hnd req params =
+handle hnd req =
     sendReply hnd 200 [("Content-Type", ["text/html"])] response
     where
     response = B.concat ["<center>You requested <b>", url, "</b></center>"]
@@ -19,26 +19,25 @@ greet hnd req params =
     sendReply hnd 200 [("Content-Type", ["text/html"])] response
     where
-    response = B.concat ["<h1>Hi ", getName name, "!</h1>"]
-    getName (Just x) = x
-    getName Nothing  = "Anonymous"
-    name = M.lookup "user" params
+    response = B.concat ["<h1>Hi ", name, "!</h1>"]
+    name = fallback (params "user") "Anonymous"
 
-chunked hnd req params = do
+chunked hnd req = do
     chunkHeaders hnd 200 [("Content-Type",["text/plain"])]
     chunk hnd "PUTIFERIO"
     chunk hnd "AAAAAAAAAHHH"
     endchunk hnd
 
-post hnd req params = do
+post hnd req = do
     print $ parseBody $ body req
     sendReply hnd 200 [("Content-Type", ["text/html"])] "OK!"
 
-router = route [ ("/"            , handle  )
-               , ("/greet/:user" , greet   )
-               , ("/chunk"       , chunked )
-               , ("/post"        , post    )
+router = route [ ("/"            , useHandler $ handle     )
+               , ("/greet/:user" , greet                   )
+               , ("/chunk"       , useHandler $ chunked    )
+               , ("/post"        , useHandler $ post       )
                , ("/Ketchup/(.*)", useHandler $ static "." )
+               , ("/auth"        , useHandler $ basicAuth [("a","b")] "test" handle )
                ]
 
 main = do listenHTTP "*" 8080 router
gendocs.sh view
@@ -1,2 +1,1 @@-mkdir docs-haddock --html --hoogle -U -o docs Ketchup/Chunked.hs Ketchup/Httpd.hs Ketchup/Routing.hs Ketchup/Static.hs Ketchup/Utils.hs+haddock --html --hoogle -U -o docs Ketchup/*.hs
+ gendocs.sh~ view
@@ -0,0 +1,1 @@+haddock --html --hoogle -U -o docs Ketchup/Chunked.hs Ketchup/Httpd.hs Ketchup/Routing.hs Ketchup/Static.hs Ketchup/Utils.hs