1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
{-# LANGUAGE ViewPatterns #-}
module Network.HTTP.Server.Mini.URI where
import Data.ByteString (ByteString)
import Data.ByteString qualified as BS
import Network.HTTP.Server.Mini.Util
-- | (path components, query string)
--
-- TODO: percent-decode
parseURI :: ByteString -> ([ByteString], [(ByteString, ByteString)])
parseURI = \bs ->
case BS.uncons bs of
Just ((== ord8 '/') -> True, bs1) -> goPath id bs1
_ -> ([], [])
where
goPath f bs
| BS.null bs = (f [], [])
| otherwise =
let (comp, bs1) = BS.span (\c -> c /= ord8 '/' && c /= ord8 '?') bs
in case BS.uncons bs1 of
Just ((== ord8 '/') -> True, bs2) ->
goPath (f . (comp:)) bs2
Just ((== ord8 '?') -> True, bs2) ->
(f [comp], goQuery bs2)
_ -> (f [comp], [])
goQuery bs
| BS.null bs = []
| Just ((== ord8 '&') -> True, bs1) <- BS.uncons bs = goQuery bs1
| otherwise =
let (key, bs1) = BS.span (\c -> c /= ord8 '=' && c /= ord8 '&') bs
in case BS.uncons bs1 of
Just ((== ord8 '=') -> True, bs2) ->
let (val, bs3) = BS.span (\c -> c /= ord8 '&') bs2
in case BS.uncons bs3 of
Just (_, bs4) -> (key, val) : goQuery bs4
Nothing -> [(key, val)]
Just ((== ord8 '&') -> True, bs2) ->
(key, BS.empty) : goQuery bs2
_ ->
[(key, BS.empty)]
|