Skip to content

Commit

Permalink
[stdlib] make cookies module modern (nim-lang#17116)
Browse files Browse the repository at this point in the history
* update cookies module
* introduce sameSite.Default

Co-authored-by: hlaaftana <[email protected]>
  • Loading branch information
ringabout and metagn committed Mar 22, 2021
1 parent 6b67073 commit 38b4cd7
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 14 deletions.
41 changes: 28 additions & 13 deletions lib/pure/cookies.nim
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,25 @@

## This module implements helper procs for parsing Cookies.

import strtabs, times
import std/[strtabs, times, options]


type
SameSite* {.pure.} = enum ## The SameSite cookie attribute.
## `Default` means that `setCookie`
## proc will not set `SameSite` attribute.
Default, None, Lax, Strict

proc parseCookies*(s: string): StringTableRef =
## parses cookies into a string table.
## Parses cookies into a string table.
##
## The proc is meant to parse the Cookie header set by a client, not the
## "Set-Cookie" header set by servers.
##
## Example:
##
## .. code-block::Nim
## doAssert parseCookies("a=1; foo=bar") == {"a": 1, "foo": "bar"}.newStringTable
runnableExamples:
import std/strtabs
let cookieJar = parseCookies("a=1; foo=bar")
assert cookieJar["a"] == "1"
assert cookieJar["foo"] == "bar"

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

proc setCookie*(key, value: string, domain = "", path = "",
expires = "", noName = false,
secure = false, httpOnly = false): string =
secure = false, httpOnly = false,
maxAge = none(int), sameSite = SameSite.Default): string =
## Creates a command in the format of
## ``Set-Cookie: key=value; Domain=...; ...``
## `Set-Cookie: key=value; Domain=...; ...`
result = ""
if not noName: result.add("Set-Cookie: ")
result.add key & "=" & value
Expand All @@ -50,12 +58,19 @@ proc setCookie*(key, value: string, domain = "", path = "",
if expires != "": result.add("; Expires=" & expires)
if secure: result.add("; Secure")
if httpOnly: result.add("; HttpOnly")
if maxAge.isSome: result.add("; Max-Age=" & $maxAge.unsafeGet)

if sameSite != SameSite.Default:
if sameSite == SameSite.None:
doAssert secure, "Cookies with SameSite=None must specify the Secure attribute!"
result.add("; SameSite=" & $sameSite)

proc setCookie*(key, value: string, expires: DateTime|Time,
domain = "", path = "", noName = false,
secure = false, httpOnly = false): string =
secure = false, httpOnly = false,
maxAge = none(int), sameSite = SameSite.Default): string =
## Creates a command in the format of
## ``Set-Cookie: key=value; Domain=...; ...``
return setCookie(key, value, domain, path,
## `Set-Cookie: key=value; Domain=...; ...`
result = setCookie(key, value, domain, path,
format(expires.utc, "ddd',' dd MMM yyyy HH:mm:ss 'GMT'"),
noname, secure, httpOnly)
noname, secure, httpOnly, maxAge, sameSite)
7 changes: 6 additions & 1 deletion tests/stdlib/tcookies.nim
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import cookies, times, strtabs
discard """
targets: "c js"
"""


import std/[cookies, times, strtabs]

let expire = fromUnix(0) + 1.seconds

Expand Down

0 comments on commit 38b4cd7

Please sign in to comment.