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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
module Cipher = Dream__cipher.Cipher
module Formats = Dream_pure.Formats
module Message = Dream_pure.Message
let all_cookies request =
Message.headers request "Cookie"
|> List.map Formats.from_cookie
|> List.flatten
let infer_cookie_prefix prefix domain path secure =
match prefix, domain, path, secure with
| Some (Some `Host), _, _, _ -> "__Host-"
| Some (Some `Secure), _, _, _ -> "__Secure-"
| Some None, _, _, _ -> ""
| None, None, Some "/", true -> "__Host-"
| None, _, _, true -> "__Secure-"
| None, _, _, _ -> ""
let cookie
?prefix:cookie_prefix
?decrypt:(decrypt_cookie = true)
?domain
?path
?secure
request
name =
let path =
match path with
| Some path -> path
| None -> Some (Router.prefix request)
in
let secure =
match secure with
| Some secure -> secure
| None -> Helpers.tls request
in
let cookie_prefix = infer_cookie_prefix cookie_prefix domain path secure in
let name = cookie_prefix ^ name in
let test = fun (name', _) -> name = name' in
match all_cookies request |> List.find_opt test with
| None -> None
| Some (_, value) ->
if not decrypt_cookie then
Some value
else
match Formats.from_base64url value with
| None ->
None
| Some value ->
Cipher.decrypt request value ~associated_data:("dream.cookie-" ^ name)
let set_cookie
?prefix:cookie_prefix
?encrypt:(encrypt_cookie = true)
?expires
?max_age
?domain
?path
?secure
?(http_only = true)
?same_site
response
request
name
value =
let path =
match path with
| Some path -> path
| None -> Some (Router.prefix request)
in
let secure =
match secure with
| Some secure -> secure
| None -> Helpers.tls request
in
let cookie_prefix = infer_cookie_prefix cookie_prefix domain path secure in
let same_site =
match same_site with
| None -> Some `Lax
| Some None -> None
| Some (Some `Strict) -> Some `Strict
| Some (Some `Lax) -> Some `Lax
| Some (Some `None) -> Some `None
in
let name = cookie_prefix ^ name in
let value =
if encrypt_cookie then
Cipher.encrypt request value ~associated_data:("dream.cookie-" ^ name)
|> Formats.to_base64url
else
value
in
let set_cookie =
Formats.to_set_cookie
?expires ?max_age ?domain ?path ~secure ~http_only ?same_site name value
in
Message.add_header response "Set-Cookie" set_cookie
let drop_cookie
?prefix ?domain ?path ?secure ?http_only ?same_site response request name =
set_cookie
?prefix ~encrypt:false ~expires:0. ?domain ?path ?secure ?http_only
?same_site response request name ""