Add cookie parser.

This commit is contained in:
Dillon Kearns 2021-12-22 14:42:35 -08:00
parent fc00121c27
commit 6df0ce9987
4 changed files with 171 additions and 2 deletions

View File

@ -36,6 +36,7 @@
"elm/html": "1.0.0 <= v < 2.0.0",
"elm/http": "2.0.0 <= v < 3.0.0",
"elm/json": "1.1.3 <= v < 2.0.0",
"elm/parser": "1.1.0 <= v < 2.0.0",
"elm/regex": "1.0.0 <= v < 2.0.0",
"elm/url": "1.0.0 <= v < 2.0.0",
"elm/virtual-dom": "1.0.2 <= v < 2.0.0",
@ -54,4 +55,4 @@
"avh4/elm-program-test": "3.1.0 <= v < 4.0.0",
"elm-explorations/test": "1.2.2 <= v < 2.0.0"
}
}
}

View File

@ -20,6 +20,7 @@
"elm/html": "1.0.0",
"elm/http": "2.0.0",
"elm/json": "1.1.3",
"elm/parser": "1.1.0",
"elm/regex": "1.0.0",
"elm/time": "1.0.0",
"elm/url": "1.0.0",
@ -42,7 +43,6 @@
"danfishgold/base64-bytes": "1.1.0",
"elm/bytes": "1.0.8",
"elm/file": "1.0.5",
"elm/parser": "1.1.0",
"elm/random": "1.0.0",
"fredcy/elm-parseint": "2.0.1",
"mgold/elm-nonempty-list": "4.2.0",

84
src/CookieParser.elm Normal file
View File

@ -0,0 +1,84 @@
module CookieParser exposing (parse)
import Dict exposing (Dict)
import Parser exposing (..)
import Url
parse : String -> Dict String String
parse input =
Parser.run parser input
|> Result.withDefault Dict.empty
parser : Parser (Dict String String)
parser =
loop [] keyValuePair
|> Parser.map Dict.fromList
keyValuePair : List ( String, String ) -> Parser (Step (List ( String, String )) (List ( String, String )))
keyValuePair revChunks =
oneOf
[ end
|> map (\_ -> Done (List.reverse revChunks))
, succeed (Loop revChunks)
|. chompIf isSpace
|. chompWhile isSpace
, succeed Tuple.pair
|= parseKey
|= oneOf
[ succeed Nothing
|. token ";"
, succeed Just
|. token "="
|= valueParser
|. oneOf
[ token ";"
, succeed ()
]
]
|> andThen
(\( key, maybeValue ) ->
case maybeValue of
Just value ->
succeed (Loop (( key, value ) :: revChunks))
Nothing ->
succeed (Loop revChunks)
)
]
valueParser : Parser String
valueParser =
succeed identity
|. chompWhile isSpace
|= oneOf
[ succeed ""
|. token ";"
, succeed identity
|. token "\""
|= (chompUntil "\""
|> getChompedString
)
|. token "\""
, chompWhile (\c -> c /= ';')
|> getChompedString
]
|> map String.trim
|> map (\value -> value |> Url.percentDecode |> Maybe.withDefault "")
parseKey : Parser String
parseKey =
succeed identity
|= (chompWhile (\c -> c /= '=' && c /= ';')
|> getChompedString
|> map String.trim
)
isSpace : Char -> Bool
isSpace c =
c == ' '

84
tests/CookieTest.elm Normal file
View File

@ -0,0 +1,84 @@
module CookieTest exposing (all)
import CookieParser
import Dict
import Expect
import Test exposing (Test, describe, test)
-- source: https://github.com/jshttp/cookie/blob/0b519534a5d0bea176f8422aeb93f7d9fce8d683/test/parse.js
all : Test
all =
describe "Cookie"
[ test "no special characters or spaces" <|
\() ->
"foo=bar"
|> CookieParser.parse
|> Expect.equalDicts
(Dict.fromList
[ ( "foo", "bar" )
]
)
, test "no special characters or spaces, numeric value" <|
\() ->
"foo=123"
|> CookieParser.parse
|> Expect.equalDicts
(Dict.fromList
[ ( "foo", "123" )
]
)
, test "with spaces" <|
\() ->
"FOO = bar; baz = raz"
|> CookieParser.parse
|> Expect.equalDicts
(Dict.fromList
[ ( "FOO", "bar" )
, ( "baz", "raz" )
]
)
, test "quoted value" <|
\() ->
"foo=\"bar=123456789&name=Magic+Mouse\""
|> CookieParser.parse
|> Expect.equalDicts
(Dict.fromList
[ ( "foo", "bar=123456789&name=Magic+Mouse" )
]
)
, test "escaped characters" <|
\() ->
"email=%20%22%2c%3b%2f"
|> CookieParser.parse
|> Expect.equalDicts
(Dict.fromList
[ ( "email", " \",;/" )
]
)
, test "dates" <|
\() ->
"priority=true; expires=Wed, 29 Jan 2014 17:43:25 GMT; Path=/"
|> CookieParser.parse
|> Expect.equalDicts
(Dict.fromList
[ ( "priority", "true" )
, ( "Path", "/" )
, ( "expires", "Wed, 29 Jan 2014 17:43:25 GMT" )
]
)
, test "missing value" <|
\() ->
"foo; bar=1; fizz= ; buzz=2"
|> CookieParser.parse
|> Expect.equalDicts
(Dict.fromList
[ ( "bar", "1" )
, ( "fizz", "" )
, ( "buzz", "2" )
]
)
]