hack 2009.4.21 → 2009.4.22
raw patch · 10 files changed
+166/−77 lines, 10 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Hack: instance Default Bool
- Hack.SimpleRoute: route :: [RoutePath] -> Application -> Application
- Hack.SimpleRoute: type RoutePath = (String, Application)
+ Hack.Contrib.ContentType: content_type :: String -> MiddleWare
+ Hack.Contrib.RawRouter: route :: [RoutePath] -> MiddleWare
+ Hack.Contrib.RawRouter: type RoutePath = (String, Application)
+ Hack.Contrib.SimpleRouter: route :: [RoutePath] -> MiddleWare
+ Hack.Contrib.SimpleRouter: type RoutePath = (String, Application)
+ Hack.Handler.Kibro: run :: Application -> IO ()
+ Hack.Utils: not_found :: String -> IO Response
+ Hack.Utils: not_found_app :: Application
+ Hack.Utils: use :: [MiddleWare] -> MiddleWare
- Hack: Env :: RequestMethod -> String -> String -> String -> String -> Int -> Map -> [Int] -> Hack_UrlScheme -> String -> String -> String -> String -> String -> Map -> Env
+ Hack: Env :: RequestMethod -> String -> String -> String -> String -> Int -> Map -> [Int] -> Hack_UrlScheme -> String -> String -> Bool -> Bool -> Bool -> Map -> Env
- Hack: hack_multiprocess :: Env -> String
+ Hack: hack_multiprocess :: Env -> Bool
- Hack: hack_multithread :: Env -> String
+ Hack: hack_multithread :: Env -> Bool
- Hack: hack_run_once :: Env -> String
+ Hack: hack_run_once :: Env -> Bool
Files
- changelog.md +7/−0
- hack.cabal +4/−2
- readme.md +39/−3
- src/Hack.hs +30/−33
- src/Hack/Contrib/ContentType.hs +19/−0
- src/Hack/Contrib/RawRouter.hs +18/−0
- src/Hack/Contrib/SimpleRouter.hs +25/−0
- src/Hack/Handler/Kibro.hs +8/−7
- src/Hack/SimpleRoute.hs +0/−25
- src/Hack/Utils.hs +16/−7
changelog.md view
@@ -1,3 +1,10 @@+2009.4.22+---------++### Feature++* more middleware: RawRouter, ContentType+ 2009.4.21 ------------
hack.cabal view
@@ -1,5 +1,5 @@ Name: hack-Version: 2009.4.21+Version: 2009.4.22 Build-type: Simple Synopsis: a sexy Haskell Webserver Interface Description: a sexy Haskell Webserver Interface@@ -20,5 +20,7 @@ exposed-modules: Hack Hack.Handler.Kibro- Hack.SimpleRoute+ Hack.Contrib.SimpleRouter+ Hack.Contrib.RawRouter+ Hack.Contrib.ContentType Hack.Utils
readme.md view
@@ -1,8 +1,8 @@ ## Hack: a sexy Haskell Webserver Interface -Hack is a lazy port of [Rack](http://rack.rubyforge.org/): the ruby webserver interface.+Hack is a brain-dead port of the brilliant Ruby [Rack](http://rack.rubyforge.org/) webserver interface. -### What does a hack app look like+### What does a Hack app look like module Main where @@ -71,8 +71,16 @@ ### demo usage of middle-ware - import Hack.SimpleRoute+ module Main where++ import Hack import Hack.Utils+ import Hack.SimpleRoute+ import Hack.Handler.Kibro++ import Data.Default+ import MPS+ import Prelude hiding ((.)) hello :: Application hello = \env -> def {body = env.show} .return@@ -93,3 +101,31 @@ Params -> Application -> Application just pass an applied middle-ware into a chain.++finally the source code of SimpleRoute.hs:++ {-# LANGUAGE NoMonomorphismRestriction#-}+ {-# LANGUAGE QuasiQuotes #-}++ module Hack.SimpleRoute where++ import Hack+ import Hack.Utils+ import List (find)+ import Prelude hiding ((.), (^), (>))+ import MPS+ + type RoutePath = (String, Application)++ route :: [RoutePath] -> Application -> Application+ route h _ = \env ->+ let path = env.path_info+ script = env.script_name+ mod_env location = env + { script_name = script ++ location+ , path_info = path.drop (location.length)+ }+ in+ case h.find (fst > flip starts_with path) of+ Nothing -> not_found [$here|Not Found: #{path}|]+ Just (location, app) -> app (mod_env location)
src/Hack.hs view
@@ -2,44 +2,44 @@ import Data.Default -data RequestMethod = - OPTIONS- | GET- | HEAD- | POST- | PUT- | DELETE- | TRACE- | CONNECT+data RequestMethod =+ OPTIONS+ | GET+ | HEAD+ | POST+ | PUT+ | DELETE+ | TRACE+ | CONNECT deriving (Show, Read, Eq) data Hack_UrlScheme = HTTP | HTTPS deriving (Show, Eq) type Map = [(String, String)] -data Env = Env {- request_method :: RequestMethod,- script_name :: String,- path_info :: String,- query_string :: String,- server_name :: String,- server_port :: Int,- http_ :: Map,- hack_version :: [Int],- hack_url_scheme :: Hack_UrlScheme,- hack_input :: String,- hack_errors :: String,- hack_multithread :: String,- hack_multiprocess :: String,- hack_run_once :: String,- custom :: Map+data Env = Env + { request_method :: RequestMethod+ , script_name :: String+ , path_info :: String+ , query_string :: String+ , server_name :: String+ , server_port :: Int+ , http_ :: Map+ , hack_version :: [Int]+ , hack_url_scheme :: Hack_UrlScheme+ , hack_input :: String+ , hack_errors :: String+ , hack_multithread :: Bool+ , hack_multiprocess :: Bool+ , hack_run_once :: Bool+ , custom :: Map } deriving (Show) -data Response = Response {- status :: Int,- headers :: Map,- body :: String+data Response = Response + { status :: Int+ , headers :: Map+ , body :: String } deriving (Show) @@ -49,14 +49,11 @@ instance Default Hack_UrlScheme where def = HTTP -instance Default Bool where- def = False- instance Default Response where def = Response def def def instance Default Env where- def = Env def def def def def def def def def def def def def def def+ def = Env def def def def def def def def def def def False False False def type Application = Env -> IO Response
+ src/Hack/Contrib/ContentType.hs view
@@ -0,0 +1,19 @@+module Hack.Contrib.ContentType where++import Hack+import Hack.Utils+import Prelude hiding ((.), (^), (>))+import MPS++content_type :: String -> MiddleWare+content_type s app = \env -> do+ response <- app env+ case response.headers+ .filter (fst > is "Content-Type")+ .reject (snd > empty) of++ [] -> response + { headers = response.headers ++ [("Content-Type", s)] }+ .return++ otherwise -> response .return
+ src/Hack/Contrib/RawRouter.hs view
@@ -0,0 +1,18 @@+module Hack.Contrib.RawRouter where++import Hack+import Hack.Utils+import List (find)+import Prelude hiding ((.), (^), (>))+import MPS+import Data.Maybe (isJust)++type RoutePath = (String, Application)++route :: [RoutePath] -> MiddleWare+route h app = \env ->+ let path = env.path_info+ in+ case h.find (fst > flip match path > isJust) of+ Nothing -> app env+ Just (_, found_app) -> found_app env
+ src/Hack/Contrib/SimpleRouter.hs view
@@ -0,0 +1,25 @@+{-# LANGUAGE NoMonomorphismRestriction#-}+{-# LANGUAGE QuasiQuotes #-}++module Hack.Contrib.SimpleRouter where++import Hack+import Hack.Utils+import List (find)+import Prelude hiding ((.), (^), (>))+import MPS++type RoutePath = (String, Application)++route :: [RoutePath] -> MiddleWare+route h _ = \env ->+ let path = env.path_info+ script = env.script_name+ mod_env location = env + { script_name = script ++ location+ , path_info = path.drop (location.length)+ }+ in+ case h.find (fst > flip starts_with path) of+ Nothing -> not_found [$here|Not Found: #{path}|]+ Just (location, app) -> app (mod_env location)
src/Hack/Handler/Kibro.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE NoMonomorphismRestriction#-} -module Hack.Handler.Kibro where+module Hack.Handler.Kibro (run) where import Hack import Kibro@@ -22,12 +22,12 @@ def { request_method = request_method'.read- , script_name = script_name'- , path_info = path_info'- , query_string = query_string'.remove_question_mark- , server_name = server_name'- , server_port = server_port'- , hack_input = hack_input'+ , script_name = script_name'+ , path_info = path_info'+ , query_string = query_string'.remove_question_mark+ , server_name = server_name'+ , server_port = server_port'+ , hack_input = hack_input' } .return where @@ -42,4 +42,5 @@ response.status.show.setHeader "Status" response.body.output +run :: Application -> IO () run app = startKibro [("", handle app)]
− src/Hack/SimpleRoute.hs
@@ -1,25 +0,0 @@-{-# LANGUAGE NoMonomorphismRestriction#-}-{-# LANGUAGE QuasiQuotes #-}--module Hack.SimpleRoute where--import Hack-import Hack.Utils-import List (find)-import Prelude hiding ((.), (^), (>))-import MPS--type RoutePath = (String, Application)--route :: [RoutePath] -> Application -> Application-route h _ = \env ->- let path = env.path_info- script = env.script_name- mod_env location = env - { script_name = script ++ location- , path_info = path.drop (location.length)- }- in- case h.find (fst > flip starts_with path) of- Nothing -> not_found [$here|Not Found: #{path}|]- Just (location, app) -> app (mod_env location)
src/Hack/Utils.hs view
@@ -1,6 +1,6 @@-{-# LANGUAGE NoMonomorphismRestriction#-}-{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE NoMonomorphismRestriction #-} {-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TypeSynonymInstances #-} module Hack.Utils where @@ -8,18 +8,27 @@ import Network.CGI hiding (Html) import Network.URI import Data.Default+import Data.Monoid import Prelude hiding ((.), (^), (>)) import MPS-import Control.Arrow ((>>>))+import Control.Arrow ((>>>), (<<<)) (>) = (>>>) infixl 8 >- ++not_found :: String -> IO Response not_found x = return $ Response- { status = 404- , headers = [("Content-Type", "text/plain")]- , body = x+ { status = 404+ , headers = [("Content-Type", "text/plain")]+ , body = x } empty_app :: Application empty_app = return def++-- usage: app.use [content_type, cache]+use :: [MiddleWare] -> MiddleWare+use = reduce (<<<)++not_found_app :: Application+not_found_app = \env -> not_found [$here|Not Found: #{env.path_info}|]