web-mongrel2-0.0.2: src/Web/Mongrel2/Parsing.hs
module Web.Mongrel2.Parsing (m2_parse) where
import Control.Applicative hiding (many)
import Text.ParserCombinators.Parsec hiding ((<|>))
import Data.Default
import Text.JSON
import Char (toLower)
import Web.Mongrel2.Types
m2_parse :: String -> Either String Request
m2_parse request =
case parse request_split "" request of
Right (uui,seqq,pat,blk) ->
case request_env blk of
Left e -> Left e
Right req ->
Right req { request_uuid = uui
, request_id = seqq
, request_path = pat }
Left a -> Left $ show a
where
request_split :: Parser (String,String,String,String)
request_split = do
uui <- many $ noneOf " "
_ <- space
iid <- many $ noneOf " "
_ <- space
path <- many $ noneOf " "
_ <- space
rest <- many anyToken
return (uui,iid,path,rest)
request_env :: String -> Either String Request
request_env request_body =
case parse qstr "" request_body of
Left x -> Left $ show x
Right (headers_,query_string_) ->
case decode headers_ of
Ok (JSObject json) -> do
let unjs = concat $
map (\(x,JSString y) -> do
[(x,fromJSString y)]
) $ fromJSObject json
Right $ def { request_path = ml "PATH" json
, request_method = ml "METHOD" json
, request_version = ml "VERSION" json
, request_uri = ml "URI" json
, request_headers = unjs
, request_pattern = ml "PATTERN" json
, request_accept = ml "Accept" json
, request_host = ml "Host" json
, request_user_agent = ml "User-Agent" json
, request_query_string = query_string_
}
_ -> Left "error parsing the headers."
ml :: String -> JSObject JSValue -> String
ml k b = maybe "" id $ mlookup k b
qstr :: Parser (String,String)
qstr = do
n <- number
_ <- char ':'
x <- count n anyChar
_ <- char ','
nx <- number
_ <- char ':'
xy <- count nx anyChar
return (x,xy)
number :: Parser Int
number = do
b <- many1 digit
return $ read b
mlookup :: String -> JSObject JSValue -> Maybe String
mlookup key bndl =
-- TODO: Not so sure that the alternate toLower is needed.
mlookup' key bndl <|> mlookup' (map toLower key) bndl
where
mlookup' :: String -> JSObject JSValue -> Maybe String
mlookup' k b =
case valFromObj k b of
Ok v -> Just $ fromJSString v
_ -> Nothing