Skip to content

Commit 46bd222

Browse files
ringaboutmetagn
andauthored
[stdlib] make cookies module modern (#17116)
* update cookies module * introduce sameSite.Default Co-authored-by: hlaaftana <[email protected]>
1 parent b48a320 commit 46bd222

File tree

2 files changed

+34
-14
lines changed

2 files changed

+34
-14
lines changed

lib/pure/cookies.nim

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,25 @@
99

1010
## This module implements helper procs for parsing Cookies.
1111

12-
import strtabs, times
12+
import std/[strtabs, times, options]
13+
14+
15+
type
16+
SameSite* {.pure.} = enum ## The SameSite cookie attribute.
17+
## `Default` means that `setCookie`
18+
## proc will not set `SameSite` attribute.
19+
Default, None, Lax, Strict
1320

1421
proc parseCookies*(s: string): StringTableRef =
15-
## parses cookies into a string table.
22+
## Parses cookies into a string table.
1623
##
1724
## The proc is meant to parse the Cookie header set by a client, not the
1825
## "Set-Cookie" header set by servers.
19-
##
20-
## Example:
21-
##
22-
## .. code-block::Nim
23-
## doAssert parseCookies("a=1; foo=bar") == {"a": 1, "foo": "bar"}.newStringTable
26+
runnableExamples:
27+
import std/strtabs
28+
let cookieJar = parseCookies("a=1; foo=bar")
29+
assert cookieJar["a"] == "1"
30+
assert cookieJar["foo"] == "bar"
2431

2532
result = newStringTable(modeCaseInsensitive)
2633
var i = 0
@@ -39,9 +46,10 @@ proc parseCookies*(s: string): StringTableRef =
3946

4047
proc setCookie*(key, value: string, domain = "", path = "",
4148
expires = "", noName = false,
42-
secure = false, httpOnly = false): string =
49+
secure = false, httpOnly = false,
50+
maxAge = none(int), sameSite = SameSite.Default): string =
4351
## Creates a command in the format of
44-
## ``Set-Cookie: key=value; Domain=...; ...``
52+
## `Set-Cookie: key=value; Domain=...; ...`
4553
result = ""
4654
if not noName: result.add("Set-Cookie: ")
4755
result.add key & "=" & value
@@ -50,12 +58,19 @@ proc setCookie*(key, value: string, domain = "", path = "",
5058
if expires != "": result.add("; Expires=" & expires)
5159
if secure: result.add("; Secure")
5260
if httpOnly: result.add("; HttpOnly")
61+
if maxAge.isSome: result.add("; Max-Age=" & $maxAge.unsafeGet)
62+
63+
if sameSite != SameSite.Default:
64+
if sameSite == SameSite.None:
65+
doAssert secure, "Cookies with SameSite=None must specify the Secure attribute!"
66+
result.add("; SameSite=" & $sameSite)
5367

5468
proc setCookie*(key, value: string, expires: DateTime|Time,
5569
domain = "", path = "", noName = false,
56-
secure = false, httpOnly = false): string =
70+
secure = false, httpOnly = false,
71+
maxAge = none(int), sameSite = SameSite.Default): string =
5772
## Creates a command in the format of
58-
## ``Set-Cookie: key=value; Domain=...; ...``
59-
return setCookie(key, value, domain, path,
73+
## `Set-Cookie: key=value; Domain=...; ...`
74+
result = setCookie(key, value, domain, path,
6075
format(expires.utc, "ddd',' dd MMM yyyy HH:mm:ss 'GMT'"),
61-
noname, secure, httpOnly)
76+
noname, secure, httpOnly, maxAge, sameSite)

tests/stdlib/tcookies.nim

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import cookies, times, strtabs
1+
discard """
2+
targets: "c js"
3+
"""
4+
5+
6+
import std/[cookies, times, strtabs]
27

38
let expire = fromUnix(0) + 1.seconds
49

0 commit comments

Comments
 (0)