diff options
| author | Andrew <saintruler@gmail.com> | 2020-11-26 16:51:52 +0400 |
|---|---|---|
| committer | Andrew <saintruler@gmail.com> | 2020-11-26 16:51:52 +0400 |
| commit | 6907a35ac265c4d4eeb127befea481a84e59ad4a (patch) | |
| tree | c115faf536fe82d0e2a998a4b8a1529e3b6ccf16 /Utils.hs | |
| parent | 446602fe336ad1c2a23e3d50d7cd1d1356fcc9de (diff) | |
Added Http parsing
Diffstat (limited to 'Utils.hs')
| -rw-r--r-- | Utils.hs | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/Utils.hs b/Utils.hs new file mode 100644 index 0000000..94ad0fb --- /dev/null +++ b/Utils.hs @@ -0,0 +1,75 @@ +module Utils (parseQs, parseHttp) where + +import Network.HTTP.Types.URI as URI +import qualified Data.ByteString as S +import Data.ByteString (ByteString) + +import qualified Data.Text as T +import Data.Text.Encoding (encodeUtf8, decodeUtf8) +import Data.Text (Text) + +-- Query string parser + +decodeUrl :: Text -> Text +decodeUrl = decodeUtf8 . URI.urlDecode True . encodeUtf8 + +parseQs :: Text -> (Text, [(Text, Text)]) +parseQs url = + let + decoded = decodeUrl url + path = T.takeWhile (\c -> c /= '?') decoded + rest = T.dropWhile (\c -> c /= '?') decoded + + parsePair :: Text -> Maybe (Text, Text) + parsePair s + | T.any ((==) '=') s = Just (a, b) + | otherwise = Nothing + where a : b : _ = T.splitOn (T.pack "=") s + + get (Just p : rest) = p : get rest + get (Nothing : rest) = get rest + get [] = [] + + pairs = + if T.null rest + then [] + else get $ map parsePair $ T.splitOn (T.pack "&") $ T.tail rest + + in (path, pairs) + +-- HTTP Parser + +rev :: [a] -> [a] +rev = foldl (flip (:)) [] + +parseFirstLine :: Text -> (Text, Text) +parseFirstLine l = (method, url) + where [method, url, _] = T.words l + +parseHeader :: Text -> (Text, Text) +parseHeader line = + (T.takeWhile p line, T.strip $ T.tail + $ T.dropWhile p line) + where p = (\c -> c /= ':') + +parseHeaders :: [Text] -> [(Text, Text)] +parseHeaders = map parseHeader + +parseHttp :: Text -> ((Text, Text, [(Text, Text)]), [(Text, Text)], [Text]) +parseHttp text = + let + lines = T.splitOn (T.pack "\r\n") text + + getFirstLine (l : rest) = (l, rest) + + getHeaders (l : rest) acc + | T.null l = (rev acc, rest) + | otherwise = getHeaders rest (l : acc) + + (fl, rest1) = getFirstLine lines + (headers, rest2) = getHeaders rest1 [] + + (method, url) = parseFirstLine fl + (path, query) = parseQs url + in + ((method, path, query), parseHeaders headers, rest2) |