summaryrefslogtreecommitdiff
path: root/mini-http-server/Network/HTTP/Server/Mini/URI.hs
diff options
context:
space:
mode:
Diffstat (limited to 'mini-http-server/Network/HTTP/Server/Mini/URI.hs')
-rw-r--r--mini-http-server/Network/HTTP/Server/Mini/URI.hs44
1 files changed, 44 insertions, 0 deletions
diff --git a/mini-http-server/Network/HTTP/Server/Mini/URI.hs b/mini-http-server/Network/HTTP/Server/Mini/URI.hs
new file mode 100644
index 0000000..13d7c35
--- /dev/null
+++ b/mini-http-server/Network/HTTP/Server/Mini/URI.hs
@@ -0,0 +1,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)]