-
Notifications
You must be signed in to change notification settings - Fork 27
Expand file tree
/
Copy pathUrlencoded.purs
More file actions
48 lines (42 loc) · 1.5 KB
/
Urlencoded.purs
File metadata and controls
48 lines (42 loc) · 1.5 KB
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
45
46
47
48
-- | Parser for the `application/x-www-form-urlencoded` format, commonly used
-- | for query strings and POST request bodies.
module Hyper.Form.Urlencoded
( defaultOptions
, Options
, parseUrlencoded
) where
import Prelude
import Control.Monad.Error.Class (throwError)
import Data.Array as Array
import Data.Either (Either)
import Data.Maybe (Maybe(Just, Nothing))
import Data.String (Pattern(..), Replacement(..), joinWith, replaceAll, split)
import Data.Traversable (sequence)
import Data.Tuple (Tuple(Tuple))
import Global (decodeURIComponent)
toTuple :: Options -> Array String -> Either String (Tuple String (Maybe String))
toTuple opts kv =
case kv of
[key] ->
pure (Tuple (decodeURIComponent key) Nothing)
[key, value] ->
let
value' =
if opts.replacePlus
then
replaceAll (Pattern "+") (Replacement " ") value
else
value
in
pure (Tuple (decodeURIComponent key) (Just (decodeURIComponent value')))
parts ->
throwError ("Invalid form key-value pair: " <> joinWith " " parts)
type Options = { replacePlus :: Boolean }
defaultOptions :: Options
defaultOptions = { replacePlus: true }
parseUrlencoded :: Options -> String -> Either String (Array (Tuple String (Maybe String)))
parseUrlencoded opts = split (Pattern "&")
>>> Array.filter (_ /= "")
>>> map (split (Pattern "="))
>>> map (toTuple opts)
>>> sequence