-- | Reading @application/x-www-form-urlencoded@ request bodies. module Todo.Form ( Fields , readFields , field ) where import Data.ByteString qualified as BS import Data.Text (Text) import Data.Text.Encoding qualified as T import Network.HTTP.Types.URI (parseSimpleQuery) import Network.Wai (Request, getRequestBodyChunk) type Fields = [(Text, Text)] -- | The body's fields, or 'Nothing' if it's bigger than @limit@ bytes. -- Bytes that aren't UTF-8 become U+FFFD rather than an error. readFields :: Int -> Request -> IO (Maybe Fields) readFields limit req = go 0 [] where go size chunks = do chunk <- getRequestBodyChunk req let size' = size + BS.length chunk if | BS.null chunk -> pure (Just (decode (BS.concat (reverse chunks)))) | size' > limit -> pure Nothing | otherwise -> go size' (chunk : chunks) decode body = [(text k, text v) | (k, v) <- parseSimpleQuery body] text = T.decodeUtf8Lenient field :: Text -> Fields -> Maybe Text field = lookup