module Hack.Frontend.MonadCGI ( cgiToApp , cgiToAppGeneric ) where import Hack import Network.CGI.Monad import Network.CGI.Protocol import qualified Data.Map as Map import qualified Data.ByteString.Lazy as BS import Control.Arrow (first) import Data.Char (toUpper) safeRead :: Read a => a -> String -> a safeRead d s = case reads s of ((x, _):_) -> x _ -> d cgiToApp :: CGI CGIResult -> Application cgiToApp = cgiToAppGeneric id cgiToAppGeneric :: Monad m => (m (Headers, CGIResult) -> IO (Headers, CGIResult)) -> CGIT m CGIResult -> Application cgiToAppGeneric toIO cgi env = do let vars = map (first fixVarName) (http env)++ getCgiVars env input = hackInput env (inputs, body') = decodeInput vars input req = CGIRequest { cgiVars = Map.fromList $ vars , cgiInputs = inputs , cgiRequestBody = body' } (headers'', output') <- toIO $ runCGIT cgi req let output = case output' of CGIOutput bs -> bs CGINothing -> BS.empty let headers' = map (\(HeaderName x, y) -> (x, y)) headers'' let status' = case lookup "Status" headers' of Nothing -> 200 Just s -> safeRead 200 s return $ Response status' headers' output fixVarName :: String -> String fixVarName = ((++) $ "HTTP_") . map fixVarNameChar fixVarNameChar :: Char -> Char fixVarNameChar '-' = '_' fixVarNameChar c = toUpper c getCgiVars :: Env -> [(String, String)] getCgiVars e = [ ("PATH_INFO", pathInfo e) , ("REQUEST_METHOD", show $ requestMethod e) , ("SCRIPT_NAME", scriptName e) , ("QUERY_STRING", queryString e) , ("SERVER_NAME", serverName e) , ("SERVER_PORT", show $ serverPort e) ]