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)
Files
- .git/COMMIT_EDITMSG +15/−1
- .git/index binary
- .git/logs/HEAD +4/−0
- .git/logs/refs/heads/master +4/−0
- .git/logs/refs/remotes/origin/master +2/−0
- .git/objects/0f/03ed98a2eba1beb8db11eb86edb34b2321a261 binary
- .git/objects/0f/d36c65d057f7ce244a4e9a335d698f075530e6 +3/−0
- .git/objects/13/9041d9f25f891c340cc0b858838f94306c9b93 +2/−0
- .git/objects/26/e2203e22a0c92e9fffb7c8d859af54bf1aa943 binary
- .git/objects/2d/61778b316db7774bc73d9c80cfa8d76e7b7a97 binary
- .git/objects/32/997e49181fa65740bdf9434d98e8f146601d75 binary
- .git/objects/35/5acd3fb38dd6a8565e8652aca975260ad9ebe4 binary
- .git/objects/37/e7da68243123c206a7b9b03e982cd2e1ffde61 binary
- .git/objects/38/b1abd98d5569fa06054273349167b45184cc6c binary
- .git/objects/3e/acc9c75ba313c63d9d9be3616d7b8b9f452975 binary
- .git/objects/41/c17d736e3d73852a7d08c691182692e793ab3f binary
- .git/objects/4a/10a87d8c968f4d836bca3a08d2f44c05060fad binary
- .git/objects/60/07e4f98c57a347a051cf7d7de71ca08fd85b8f binary
- .git/objects/78/b20a019fafabb14b2745db2c5912176729df2c binary
- .git/objects/82/8e849a50ad7d3abf4afe0cc48a2b68512310cb +1/−0
- .git/objects/84/bf304493959e3a08b3807bd704ec632a9fb8a9 binary
- .git/objects/8b/beae61080d264f5b69734128be1ecea8d6bfd4 binary
- .git/objects/9a/6ebc14c4c86e50b3654d62c33ed7d83351c524 binary
- .git/objects/b3/591481b033fac241826b9fc64a51d925d71175 binary
- .git/objects/b9/eb5d552bfc0adee1044e395991edcfd292826b binary
- .git/objects/c2/d02249f1afb2578f5af2fcdfab5bcfbdcdb2e4 binary
- .git/objects/d9/14ad60c2478c15e417bbfbae1ae6cbacfb8968 binary
- .git/objects/da/f5ffbd0e64b1c1405b2bc670dd396d9c544a14 binary
- .git/objects/de/93e13807a1416af9226a89e7292c83ca984bb0 binary
- .git/objects/eb/a023660b513baa6686d113b0d5108a83448e4a binary
- .git/objects/f6/1d5b2caadecbdcf54d2d0ad7b131ca2adcdc28 binary
- .git/refs/heads/master +1/−1
- .git/refs/remotes/origin/master +1/−1
- .gitignore +0/−1
- .gitignore~ +1/−0
- Ketchup.cabal +14/−4
- Ketchup/Auth.hs +28/−1
- Ketchup/Chunked.hs~ +0/−46
- Ketchup/Httpd.hs +2/−3
- Ketchup/Routing.hs +7/−9
- Ketchup/Utils.hs +9/−3
- README.md +9/−2
- docs/.git/COMMIT_EDITMSG +221/−0
- docs/.git/HEAD +1/−0
- docs/.git/config +11/−0
- docs/.git/config~ +11/−0
- docs/.git/description +1/−0
- docs/.git/hooks/applypatch-msg.sample +15/−0
- docs/.git/hooks/commit-msg.sample +24/−0
- docs/.git/hooks/post-update.sample +8/−0
- docs/.git/hooks/pre-applypatch.sample +14/−0
- docs/.git/hooks/pre-commit.sample +49/−0
- docs/.git/hooks/pre-push.sample +54/−0
- docs/.git/hooks/pre-rebase.sample +169/−0
- docs/.git/hooks/prepare-commit-msg.sample +36/−0
- docs/.git/hooks/update.sample +128/−0
- docs/.git/index binary
- docs/.git/info/exclude +6/−0
- docs/.git/logs/HEAD +3/−0
- docs/.git/logs/refs/heads/gh-pages +3/−0
- docs/.git/logs/refs/remotes/origin/HEAD +1/−0
- docs/.git/logs/refs/remotes/origin/gh-pages +2/−0
- docs/.git/objects/04/27491eaa020186e459934ed69cdb7d808501cd +4/−0
- docs/.git/objects/0e/f0bb4acb2a054328faea81aaa1b6ef08ab4324 binary
- docs/.git/objects/31/0e7b443f14a92b46059c540620e2e3ec9eeecf binary
- docs/.git/objects/33/d1dadf72d9a1c6217c5a6c7992dcdaaa343742 binary
- docs/.git/objects/4c/2353910734c89633d869f0ffccf8f565c93221 +2/−0
- docs/.git/objects/5c/7dd6782bd7103baeb041d69fd3e17410ab46dd binary
- docs/.git/objects/63/50f4f119a8325852c5279f96ae5b0c34cce55f binary
- docs/.git/objects/70/15cd0af9b0fc60257cff8d057cee6a475f44d8 binary
- docs/.git/objects/87/66065959fca5de5327f875dbb67559f69b52b6 +3/−0
- docs/.git/objects/a3/3f00a997926762956b66487bc763c7500b5912 binary
- docs/.git/objects/ad/296ab5c62662ad2f55c20cd75483c7014e3a9e binary
- docs/.git/objects/c8/298c807614715a3dd52fe3fddcd74b42d8dd51 binary
- docs/.git/objects/ca/7171c6a9384a3af595c1110538b011803b834c binary
- docs/.git/objects/cc/746e214c400d625c17bb704964d2490009dcd6 binary
- docs/.git/objects/da/b38cfd353bbdc462641543658ea8acd3eac19d binary
- docs/.git/objects/e5/dc6abf9873d9eaf80c4e5d308832b23e5b18cd binary
- docs/.git/objects/e8/a9b100db71a644cc6cf513f26b5f44a42d17ab binary
- docs/.git/objects/ec/a1b33fcd1c0373e31d108a81dca8be042fd89c binary
- docs/.git/objects/f8/b79cfde7e99e07a48a906d6b0f43517cdee2b3 binary
- docs/.git/objects/ff/6a9f5d733cd98051951968bb686e9766cf0a44 binary
- docs/.git/objects/pack/pack-91a33bcc9daf02ed2b87eb63c5967322fb125afb.idx binary
- docs/.git/objects/pack/pack-91a33bcc9daf02ed2b87eb63c5967322fb125afb.pack binary
- docs/.git/packed-refs +3/−0
- docs/.git/refs/heads/gh-pages +1/−0
- docs/.git/refs/remotes/origin/HEAD +1/−0
- docs/.git/refs/remotes/origin/gh-pages +1/−0
- docs/Ketchup-Auth.html +8/−0
- docs/Ketchup-Chunked.html +13/−0
- docs/Ketchup-Httpd.html +15/−0
- docs/Ketchup-Routing.html +9/−0
- docs/Ketchup-Static.html +7/−0
- docs/Ketchup-Utils.html +19/−0
- docs/doc-index.html +4/−0
- docs/frames.html +30/−0
- docs/haddock-util.js +344/−0
- docs/hslogo-16.png binary
- docs/index-frames.html +4/−0
- docs/index.html +4/−0
- docs/main.txt +87/−0
- docs/mini_Ketchup-Auth.html +4/−0
- docs/mini_Ketchup-Chunked.html +4/−0
- docs/mini_Ketchup-Httpd.html +4/−0
- docs/mini_Ketchup-Routing.html +4/−0
- docs/mini_Ketchup-Static.html +4/−0
- docs/mini_Ketchup-Utils.html +4/−0
- docs/minus.gif binary
- docs/ocean.css +546/−0
- docs/plus.gif binary
- docs/synopsis.png binary
- example.hs +11/−12
- gendocs.sh +1/−2
- gendocs.sh~ +1/−0
@@ -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~+#
binary file changed (976 → 1136 bytes)
@@ -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
@@ -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
@@ -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
binary file changed (absent → 160 bytes)
@@ -0,0 +1,3 @@+xA+Â0E]÷Ù$ÀýL2µ¥¦)5]ÔÓ+¸úðßðcÉyª+NuQÆOäZh"jG{ÖFú1¡À0$qдÉRJ} &`á ÄÆ2¶§½eSÊq$uýNó1÷W¦é}%ßXmµï÷ê¬Q뮵íZ¿¤î)Ûg*â=¯Ý÷¥BÆ
@@ -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
binary file changed (absent → 319 bytes)
binary file changed (absent → 980 bytes)
binary file changed (absent → 682 bytes)
binary file changed (absent → 918 bytes)
binary file changed (absent → 320 bytes)
binary file changed (absent → 682 bytes)
binary file changed (absent → 98 bytes)
binary file changed (absent → 320 bytes)
binary file changed (absent → 320 bytes)
binary file changed (absent → 1432 bytes)
binary file changed (absent → 179 bytes)
@@ -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êÉ´¡2F°á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èßuZ\cö@ÇoüöØjµJ%°æÞá'JäÏö3tØ Ñä÷.öub?é°¤J±|ýì´<:³:1VþBqzè¬<~ºéuxwÙ¤0Ú¯Ö¬ûíξ1´QÂ|ÿ Ú
binary file changed (absent → 905 bytes)
binary file changed (absent → 604 bytes)
binary file changed (absent → 762 bytes)
binary file changed (absent → 615 bytes)
binary file changed (absent → 978 bytes)
binary file changed (absent → 60 bytes)
binary file changed (absent → 320 bytes)
binary file changed (absent → 208 bytes)
binary file changed (absent → 1323 bytes)
binary file changed (absent → 207 bytes)
binary file changed (absent → 172 bytes)
@@ -1,1 +1,1 @@-4ad51f9dc87b6aa48cb614030521d957b8498622+0fd36c65d057f7ce244a4e9a335d698f075530e6
@@ -1,1 +1,1 @@-4ad51f9dc87b6aa48cb614030521d957b8498622+0fd36c65d057f7ce244a4e9a335d698f075530e6
@@ -3,4 +3,3 @@ example dist docs -gendocs.sh
@@ -3,3 +3,4 @@ example dist docs +gendocs.sh
@@ -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,
@@ -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
@@ -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"
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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"> </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> ∷ [(ByteString, ByteString)] → ByteString → <a href="Ketchup-Httpd.html#t:Handler">Handler</a> → <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">∷ [(ByteString, ByteString)]</td><td class="doc"><p>List of (Username, Password)++</p></td></tr><tr><td class="src">→ ByteString</td><td class="doc"><p>Authentication Realm++</p></td></tr><tr><td class="src">→ <a href="Ketchup-Httpd.html#t:Handler">Handler</a></td><td class="doc"><p>Success Handler++</p></td></tr><tr><td class="src">→ <a href="Ketchup-Httpd.html#t:Handler">Handler</a></td><td class="doc empty"> </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"> </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> ∷ ByteString</li><li><a href="#v:uri">uri</a> ∷ ByteString</li><li><a href="#v:httpver">httpver</a> ∷ ByteString</li><li><a href="#v:headers">headers</a> ∷ <a href="Ketchup-Httpd.html#t:Headers">Headers</a></li><li><a href="#v:body">body</a> ∷ 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 → <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a> → IO ()</li><li class="src short"><a href="#v:listenHTTP">listenHTTP</a> ∷ String → PortNumber → <a href="Ketchup-Httpd.html#t:Handler">Handler</a> → 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"> </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> ∷ ByteString</li><li><a href="#v:uri">uri</a> ∷ ByteString</li><li><a href="#v:httpver">httpver</a> ∷ ByteString</li><li><a href="#v:headers">headers</a> ∷ <a href="Ketchup-Httpd.html#t:Headers">Headers</a></li><li><a href="#v:body">body</a> ∷ 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 → <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a> → IO ()</li><li class="src short"><a href="#v:listenHTTP">listenHTTP</a> ∷ String → PortNumber → <a href="Ketchup-Httpd.html#t:Handler">Handler</a> → 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"> </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> ∷ 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> ∷ ByteString</dt><dd class="doc"><p>Get Request URI+ </p></dd><dt class="src"><a name="v:httpver" class="def">httpver</a> ∷ ByteString</dt><dd class="doc"><p>Get HTTP Version+ </p></dd><dt class="src"><a name="v:headers" class="def">headers</a> ∷ <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> ∷ 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"> </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 → <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a> → 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">∷ 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"> </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 → <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a> → 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">∷ String</td><td class="doc"><p>Address to bind (ie. <a href="*.html">*</a>)+ </p></td></tr><tr><td class="src">→ PortNumber</td><td class="doc"><p>Port to listen on+ </p></td></tr><tr><td class="src">→ <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">→ IO ()</td><td class="doc empty"> </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"> </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 → <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a> → <a href="Ketchup-Routing.html#t:Parameters">Parameters</a> → 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> ∷ [(ByteString, <a href="Ketchup-Routing.html#t:Route">Route</a>)] → <a href="Ketchup-Httpd.html#t:Handler">Handler</a></li><li class="src short"><a href="#v:useHandler">useHandler</a> ∷ <a href="Ketchup-Httpd.html#t:Handler">Handler</a> → <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 → <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a> → <a href="Ketchup-Routing.html#t:Parameters">Parameters</a> → 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">∷ [(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"> </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 → <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a> → (ByteString → Maybe ByteString) → IO ()</li><li class="src short"><a href="#v:route">route</a> ∷ [(ByteString, <a href="Ketchup-Routing.html#t:Route">Route</a>)] → <a href="Ketchup-Httpd.html#t:Handler">Handler</a></li><li class="src short"><a href="#v:useHandler">useHandler</a> ∷ <a href="Ketchup-Httpd.html#t:Handler">Handler</a> → <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 → <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a> → (ByteString → Maybe ByteString) → 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">∷ [(ByteString, <a href="Ketchup-Routing.html#t:Route">Route</a>)]</td><td class="doc"><p>Routes+ </p></td></tr><tr><td class="src">→ <a href="Ketchup-Httpd.html#t:Handler">Handler</a></td><td class="doc empty"> </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> ∷ <a href="Ketchup-Httpd.html#t:Handler">Handler</a> → <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"> </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> ∷ ByteString → ByteString</li><li class="src short"><a href="#v:breakBS">breakBS</a> ∷ ByteString → ByteString → (ByteString, ByteString)</li><li class="src short"><a href="#v:parseBody">parseBody</a> ∷ ByteString → Map ByteString ByteString</li><li class="src short"><a href="#v:sendReply">sendReply</a> ∷ Socket → Int → [(ByteString, [ByteString])] → ByteString → IO ()</li><li class="src short"><a href="#v:sendBadRequest">sendBadRequest</a> ∷ Socket → IO ()</li><li class="src short"><a href="#v:sendNotFound">sendNotFound</a> ∷ Socket → IO ()</li><li class="src short"><a href="#v:statusMsg">statusMsg</a> ∷ Int → ByteString</li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><a name="v:trim" class="def">trim</a> ∷ ByteString → 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"> </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> ∷ ByteString → ByteString</li><li class="src short"><a href="#v:breakBS">breakBS</a> ∷ ByteString → ByteString → (ByteString, ByteString)</li><li class="src short"><a href="#v:fallback">fallback</a> ∷ Maybe a → a → a</li><li class="src short"><a href="#v:parseBody">parseBody</a> ∷ ByteString → [(ByteString, ByteString)]</li><li class="src short"><a href="#v:sendReply">sendReply</a> ∷ Socket → Int → [(ByteString, [ByteString])] → ByteString → IO ()</li><li class="src short"><a href="#v:sendBadRequest">sendBadRequest</a> ∷ Socket → IO ()</li><li class="src short"><a href="#v:sendNotFound">sendNotFound</a> ∷ Socket → IO ()</li><li class="src short"><a href="#v:statusMsg">statusMsg</a> ∷ Int → ByteString</li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><a name="v:trim" class="def">trim</a> ∷ ByteString → 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> ∷ ByteString → ByteString → (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> ∷ ByteString → 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> ∷ Maybe a → a → a</p></div><div class="top"><p class="src"><a name="v:parseBody" class="def">parseBody</a> ∷ ByteString → [(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">∷ Socket</td><td class="doc"><p>Socket to write to+ </p></td></tr><tr><td class="src">→ Int</td><td class="doc"><p>Status Code to send+ </p></td></tr><tr><td class="src">→ [(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"> </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> </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"> </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> </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"> </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"> </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
@@ -0,0 +1,1 @@+ref: refs/heads/gh-pages
@@ -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
@@ -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
@@ -0,0 +1,1 @@+Unnamed repository; edit this file 'description' to name the repository.
@@ -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+"$@"}+:
@@ -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+}
@@ -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
@@ -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+"$@"}+:
@@ -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 --
@@ -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
@@ -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".
@@ -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"
@@ -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
binary file changed (absent → 1928 bytes)
@@ -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]+# *~
@@ -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
@@ -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
@@ -0,0 +1,1 @@+0000000000000000000000000000000000000000 4ad51f9dc87b6aa48cb614030521d957b8498622 Hamcha <zikyky@gmail.com> 1404003477 +0200 clone: from https://github.com/Hamcha/ketchup
@@ -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
@@ -0,0 +1,4 @@+xßOÛ0Ç÷Ì_aü0à!ñJ 4ÖÄ+L Á@´M×1M¨k{±Óö¿ïl(Ý&M}jz¾ûÜÝ×çI=B½þlûørX|¿:AJtuûñülpBÈ×þãâ};-.ÎQ/})[»Z+& 9ù®3Ïçé¼êfLk²ð¬î>·®Ä4ùS©lþJïðð0{WÁJM 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=AdÕûÌ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óø
binary file changed (absent → 1451 bytes)
binary file changed (absent → 918 bytes)
binary file changed (absent → 161 bytes)
@@ -0,0 +1,2 @@+xÎA+1@Q×=Eö$MǶ âÒxT´vëBOï\Áí_[cOiÕçR@%R$ÝJæå2äANg$JÈçÄAÝ$syv`62±Kôeq¢²Õ³75áÀ1x'ï~k3¥êM`÷ïûçp2>6Úê(`À#zX£GtK]Özù¹ÓdÒ5}Aov?¹C$
binary file changed (absent → 1552 bytes)
binary file changed (absent → 1142 bytes)
binary file changed (absent → 456 bytes)
@@ -0,0 +1,3 @@+x]oÓ0¹î¯ð|µ]$^5!QêD*éÐÝF*@Ó.\Ûk¼:vOVÿmPѾïsìsÎJÛÏß¾¡'óÛ,ÿ~w+(5º[~X|Êùz2ÏçèÛU~½@ãøå53N²iB.o0Â@õ¶mãö"¶õä÷dXã`¼rÆNioWjã¿PÆÉ¤7©d"¥¥æ_ U$4jàÌ¢|_Ix¿K0È@"^°ÚIHùÇèF$¥ @ËaÖÊlPQ˧[.¹sÕR'ØÁ^KWH 0;AçNðm°tXÇkUr5÷aBX¾P:~ö¸Wîg¶e½Öô«îè¡'Ù|ÏF2¶±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ÐÄwCOù):ý æ{.
binary file changed (absent → 529 bytes)
binary file changed (absent → 1002 bytes)
binary file changed (absent → 1169 bytes)
binary file changed (absent → 727 bytes)
binary file changed (absent → 554 bytes)
binary file changed (absent → 928 bytes)
binary file changed (absent → 1028 bytes)
binary file changed (absent → 972 bytes)
binary file changed (absent → 672 bytes)
binary file changed (absent → 507 bytes)
binary file changed (absent → 960 bytes)
binary file changed (absent → 5776 bytes)
binary file changed (absent → 49903 bytes)
@@ -0,0 +1,3 @@+# pack-refs with: peeled fully-peeled +4ac44b6241517d43310da25b086e175b3b9c0b49 refs/remotes/origin/gh-pages+4ad51f9dc87b6aa48cb614030521d957b8498622 refs/remotes/origin/master
@@ -0,0 +1,1 @@+4c2353910734c89633d869f0ffccf8f565c93221
@@ -0,0 +1,1 @@+ref: refs/remotes/origin/master
@@ -0,0 +1,1 @@+4c2353910734c89633d869f0ffccf8f565c93221
@@ -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"> </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> ∷ [(ByteString, ByteString)] → ByteString → <a href="Ketchup-Httpd.html#t:Handler">Handler</a> → <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">∷ [(ByteString, ByteString)]</td><td class="doc"><p>List of (Username, Password)+</p></td></tr><tr><td class="src">→ ByteString</td><td class="doc"><p>Authentication Realm+</p></td></tr><tr><td class="src">→ <a href="Ketchup-Httpd.html#t:Handler">Handler</a></td><td class="doc"><p>Success Handler+</p></td></tr><tr><td class="src">→ <a href="Ketchup-Httpd.html#t:Handler">Handler</a></td><td class="doc empty"> </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>
@@ -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"> </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> ∷ Socket → Int → [(ByteString, [ByteString])] → IO ()</li><li class="src short"><a href="#v:chunk">chunk</a> ∷ Socket → ByteString → IO ()</li><li class="src short"><a href="#v:endchunk">endchunk</a> ∷ Socket → 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">∷ Socket</td><td class="doc"><p>Socket to write to+</p></td></tr><tr><td class="src">→ Int</td><td class="doc"><p>Status code+</p></td></tr><tr><td class="src">→ [(ByteString, [ByteString])]</td><td class="doc"><p>Headers+</p></td></tr><tr><td class="src">→ IO ()</td><td class="doc empty"> </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">∷ Socket</td><td class="doc"><p>Socket to write to+</p></td></tr><tr><td class="src">→ ByteString</td><td class="doc"><p>Content to write+</p></td></tr><tr><td class="src">→ IO ()</td><td class="doc empty"> </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">∷ Socket</td><td class="doc"><p>Socket to write to+</p></td></tr><tr><td class="src">→ IO ()</td><td class="doc empty"> </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>
@@ -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"> </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> ∷ ByteString</li><li><a href="#v:uri">uri</a> ∷ ByteString</li><li><a href="#v:httpver">httpver</a> ∷ ByteString</li><li><a href="#v:headers">headers</a> ∷ <a href="Ketchup-Httpd.html#t:Headers">Headers</a></li><li><a href="#v:body">body</a> ∷ 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 → <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a> → IO ()</li><li class="src short"><a href="#v:listenHTTP">listenHTTP</a> ∷ String → PortNumber → <a href="Ketchup-Httpd.html#t:Handler">Handler</a> → 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"> </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> ∷ 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> ∷ ByteString</dt><dd class="doc"><p>Get Request URI+</p></dd><dt class="src"><a name="v:httpver" class="def">httpver</a> ∷ ByteString</dt><dd class="doc"><p>Get HTTP Version+</p></dd><dt class="src"><a name="v:headers" class="def">headers</a> ∷ <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> ∷ 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"> </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 → <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a> → 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">∷ String</td><td class="doc"><p>Address to bind (ie. <a href="*.html">*</a>)+</p></td></tr><tr><td class="src">→ PortNumber</td><td class="doc"><p>Port to listen on+</p></td></tr><tr><td class="src">→ <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">→ IO ()</td><td class="doc empty"> </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>
@@ -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"> </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 → <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a> → (ByteString → Maybe ByteString) → IO ()</li><li class="src short"><a href="#v:route">route</a> ∷ [(ByteString, <a href="Ketchup-Routing.html#t:Route">Route</a>)] → <a href="Ketchup-Httpd.html#t:Handler">Handler</a></li><li class="src short"><a href="#v:useHandler">useHandler</a> ∷ <a href="Ketchup-Httpd.html#t:Handler">Handler</a> → <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 → <a href="Ketchup-Httpd.html#t:HTTPRequest">HTTPRequest</a> → (ByteString → Maybe ByteString) → 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">∷ [(ByteString, <a href="Ketchup-Routing.html#t:Route">Route</a>)]</td><td class="doc"><p>Routes+</p></td></tr><tr><td class="src">→ <a href="Ketchup-Httpd.html#t:Handler">Handler</a></td><td class="doc empty"> </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> ∷ <a href="Ketchup-Httpd.html#t:Handler">Handler</a> → <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>
@@ -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"> </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> ∷ ByteString → <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">∷ ByteString</td><td class="doc"><p>Path to serve static files from+</p></td></tr><tr><td class="src">→ <a href="Ketchup-Httpd.html#t:Handler">Handler</a></td><td class="doc empty"> </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>
@@ -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"> </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> ∷ ByteString → ByteString</li><li class="src short"><a href="#v:breakBS">breakBS</a> ∷ ByteString → ByteString → (ByteString, ByteString)</li><li class="src short"><a href="#v:fallback">fallback</a> ∷ Maybe a → a → a</li><li class="src short"><a href="#v:parseBody">parseBody</a> ∷ ByteString → [(ByteString, ByteString)]</li><li class="src short"><a href="#v:sendReply">sendReply</a> ∷ Socket → Int → [(ByteString, [ByteString])] → ByteString → IO ()</li><li class="src short"><a href="#v:sendBadRequest">sendBadRequest</a> ∷ Socket → IO ()</li><li class="src short"><a href="#v:sendNotFound">sendNotFound</a> ∷ Socket → IO ()</li><li class="src short"><a href="#v:statusMsg">statusMsg</a> ∷ Int → ByteString</li></ul></div><div id="interface"><h1>Documentation</h1><div class="top"><p class="src"><a name="v:trim" class="def">trim</a> ∷ ByteString → 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> ∷ ByteString → ByteString → (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> ∷ Maybe a → a → a</p></div><div class="top"><p class="src"><a name="v:parseBody" class="def">parseBody</a> ∷ ByteString → [(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">∷ Socket</td><td class="doc"><p>Socket to write to+</p></td></tr><tr><td class="src">→ Int</td><td class="doc"><p>Status Code to send+</p></td></tr><tr><td class="src">→ [(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">→ ByteString</td><td class="doc"><p>Body+</p></td></tr><tr><td class="src">→ IO ()</td><td class="doc empty"> </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> ∷ Socket → 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> ∷ Socket → 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">∷ Int</td><td class="doc"><p>Status code (ex. 404)+</p></td></tr><tr><td class="src">→ 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>
@@ -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"> </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> </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>
@@ -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>
@@ -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 ▾</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();+}+
binary file changed (absent → 1684 bytes)
@@ -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>
@@ -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"> </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>
@@ -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
@@ -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>
@@ -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>
@@ -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>
@@ -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>
@@ -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>
@@ -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>
binary file changed (absent → 56 bytes)
@@ -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 */
binary file changed (absent → 59 bytes)
binary file changed (absent → 11327 bytes)
@@ -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
@@ -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
@@ -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