1 |
|
2 | var log = require("../lib/log")("app:cookie")
|
3 | , valueEsc = /[^!#-~]|[%,;\\]/g
|
4 |
|
5 | exports.get = getCookie
|
6 | exports.set = setCookie
|
7 | exports.escape = escapeCookie
|
8 |
|
9 | function getCookie(name, opts) {
|
10 | if (typeof name === "object") {
|
11 | opts = name
|
12 | name = opts.name
|
13 | } else {
|
14 | opts = opts || {}
|
15 | }
|
16 |
|
17 | var req = this
|
18 | , junks = ("; " + req.headers.cookie).split("; " + name + "=")
|
19 |
|
20 | if (junks.length > 2) {
|
21 | ;(opts.path || "").split("/").map(function(val, key, arr) {
|
22 | var path = arr.slice(0, key+1).join("/")
|
23 | , domain = opts.domain
|
24 | req.res.cookie(name, "", {ttl: -1, path: path})
|
25 | if (domain) {
|
26 | req.res.cookie(name, "", {ttl: -1, path: path, domain: domain})
|
27 |
|
28 | if (domain !== (domain = domain.replace(/^[^.]+/, "*"))) {
|
29 | req.res.cookie(name, "", {ttl: -1, path: path, domain: domain})
|
30 | }
|
31 | }
|
32 | })
|
33 | log.warn("Cookie fixation detected: %s", req.headers.cookie)
|
34 | return
|
35 | }
|
36 |
|
37 | try {
|
38 | return decodeURIComponent((junks[1] || "").split(";")[0])
|
39 | } catch(e) {
|
40 | log.warn("Invalid cookie '%s' in: %s", name, req.headers.cookie)
|
41 | }
|
42 | }
|
43 |
|
44 | function setCookie(name, value, opts) {
|
45 | var res = this
|
46 | , existing = (res._headers || setCookie)["set-cookie"]
|
47 | , cookie = (
|
48 | typeof name === "object" ? (opts = name).name : name
|
49 | ) + "=" + escapeCookie(value)
|
50 |
|
51 | if (opts) {
|
52 | cookie +=
|
53 |
|
54 |
|
55 |
|
56 | (opts.ttl ? "; Expires=" + new Date(opts.ttl > 0 ? Date.now() + (opts.ttl*1000) : 0).toUTCString() : "") +
|
57 | (opts.path ? "; Path=" + opts.path : "") +
|
58 | (opts.domain ? "; Domain=" + opts.domain : "") +
|
59 | (opts.secure ? "; Secure" : "") +
|
60 | (opts.httpOnly ? "; HttpOnly" : "") +
|
61 | (opts.sameSite ? "; SameSite=" + opts.sameSite : "")
|
62 | }
|
63 |
|
64 | if (!Array.isArray(existing)) {
|
65 | res.setHeader("Set-Cookie", (
|
66 | existing === void 0 ? cookie : [existing, cookie]
|
67 | ))
|
68 | } else {
|
69 | existing.push(cookie)
|
70 | }
|
71 | log.debug("Set-Cookie: %s", cookie)
|
72 | }
|
73 |
|
74 | function escapeCookie(value) {
|
75 | return typeof value === "string" ? value.replace(valueEsc, encodeURIComponent) : ""
|
76 | }
|
77 |
|