{-# 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)]