bird 0.0.3 → 0.0.6
raw patch · 5 files changed
+104/−25 lines, 5 filesdep +parsecdep +rallod
Dependencies added: parsec, rallod
Files
- bird.cabal +3/−3
- readme.markdown +12/−7
- src/Bird.hs +5/−5
- src/Bird/Request.hs +43/−10
- src/Bird/Request/QueryStringParser.hs +41/−0
bird.cabal view
@@ -1,5 +1,5 @@ Name: bird-Version: 0.0.3+Version: 0.0.6 Build-type: Simple Synopsis: A simple, sinatra-inspired web framework. Description: Bird is a hack-compatible framework for simple websites.@@ -18,6 +18,6 @@ hs-source-dirs: bin library- build-depends: haskell98, process, containers, bytestring, base >= 4.0 && < 5, hack >= 2009.10.30, hack-handler-happstack, data-default >= 0.2 - exposed-modules: Bird, Bird.Request, Bird.Reply, Bird.Reply.Codes+ build-depends: haskell98, process, containers, parsec >= 2.1.0.1, bytestring, base >= 4.0 && < 5, hack >= 2009.10.30, hack-handler-happstack, data-default >= 0.2, rallod + exposed-modules: Bird, Bird.Request, Bird.Reply, Bird.Reply.Codes, Bird.Request.QueryStringParser hs-source-dirs: src/
readme.markdown view
@@ -10,26 +10,26 @@ ## Install - $ cabal update && cabal install bird+ λ cabal update && cabal install bird Note: make sure $HOME/.cabal/bin is in your PATH. ## Create an app - $ bird MyApp + λ bird MyApp ## Compile your app - $ cd MyApp- $ bird nest + λ cd MyApp+ λ bird nest ## Start your app (runs on port 3000) - $ bird fly+ λ bird fly ## Try it out - $ curl http://localhost:3000+ λ curl http://localhost:3000 404 Not Found ## Improvise!@@ -41,12 +41,17 @@ get, post, put, delete :: Request -> IO Reply get Request { path = ("howdy":xs) } - = ok $ ("Howdy " ++) $ join ", " xs+ = ok $ "Howdy " ++ (join ", " xs) ++ "!" get _ = return notFound_ post _ = return notFound_ put _ = return notFound_ delete _ = return notFound_++now:++ λ curl http://localhost:3000/howdy/there/pardna+ Howdy there, pardna! ## Notes
src/Bird.hs view
@@ -1,9 +1,9 @@ module Bird(- module Hack, - module Data.Default, - module Bird.Reply,- module Bird.Request, - module Bird.Reply.Codes+ module Hack +, module Data.Default +, module Bird.Reply+, module Bird.Request +, module Bird.Reply.Codes ) where import Hack
src/Bird/Request.hs view
@@ -6,13 +6,17 @@ import Hack import Data.Default import Data.ByteString.Lazy.Char8 (pack)+import Rallod+import Text.ParserCombinators.Parsec+import Numeric+import Bird.Request.QueryStringParser import qualified Data.Map as Hash data Request = Request { verb :: RequestMethod, path :: [String],- params :: Hash.Map String String,+ params :: Hash.Map String (Maybe String), protocol :: Hack_UrlScheme, hackEnvironment :: Env } deriving (Show)@@ -25,19 +29,11 @@ Request { verb = requestMethod e, path = split '/' $ pathInfo e,- params = Hash.fromList $ buildParams (queryString e),+ params = Hash.fromList $ parseQueryString $ queryString e, protocol = hackUrlScheme e, hackEnvironment = e } -infixl 9 ==>-f ==> g = g $ f--buildParams "" = []-buildParams queryString = queryString ==> split '&' ==> map (split '=') ==> map tupleize--tupleize (a:b:[]) = (a,b)- split :: Char -> String -> [String] split d s | findSep == [] = []@@ -45,3 +41,40 @@ where (t, s'') = break (== d) findSep findSep = dropWhile (== d) s++-----+-- +-- parseQuery :: (String -> [(String, Maybe String)])+-- parseQuery q = +-- case (parse (keyValuePair `sepBy` char '&') "Exception: Invalid Query String" q) of+-- Left e -> error $ show e+-- Right queryMap -> queryMap+-- +-- keyValuePair = do+-- k <- many1 keyCharacters+-- v <- optionMaybe (char '=' >> many valueCharacters)+-- return (k, v)+-- +-- +-- keyCharacters :: CharParser () Char +-- keyCharacters = +-- oneOf urlBaseChars +-- <|> (char '+' >> return ' ') +-- <|> hexValue +-- +-- where +-- urlBaseChars = +-- ['a'..'z'] +++-- ['A'..'Z'] +++-- ['0'..'9'] +++-- "$-_.!*'()," +-- +-- valueCharacters = keyCharacters+-- +-- hexValue :: CharParser () Char +-- hexValue = do +-- char '%' +-- a <- hexDigit +-- b <- hexDigit +-- let ((d, _):_) = readHex [a,b] +-- return . toEnum $ d
+ src/Bird/Request/QueryStringParser.hs view
@@ -0,0 +1,41 @@+module Bird.Request.QueryStringParser(+ parseQueryString+) where++import Text.ParserCombinators.Parsec+import Numeric++parseQueryString :: String -> [(String, Maybe String)]+parseQueryString q = + case (parse (keyValuePair `sepBy` char '&') "Exception: Invalid Query String" q) of+ Left e -> error $ show e+ Right queryMap -> queryMap++keyValuePair = do+ k <- many1 keyCharacters+ v <- optionMaybe (char '=' >> many valueCharacters)+ return (k, v)+++keyCharacters :: CharParser () Char +keyCharacters = + oneOf urlBaseChars + <|> (char '+' >> return ' ') + <|> hexValue + + where + urlBaseChars = + ['a'..'z'] +++ ['A'..'Z'] +++ ['0'..'9'] +++ "$-_.!*'()," ++valueCharacters = keyCharacters++hexValue :: CharParser () Char +hexValue = do + char '%' + a <- hexDigit + b <- hexDigit + let ((d, _):_) = readHex [a,b] + return . toEnum $ d