/
index.ts
73 lines (63 loc) · 1.73 KB
/
index.ts
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
import { IncomingMessage, ServerResponse } from "http";
type ReferrerPolicyToken =
| "no-referrer"
| "no-referrer-when-downgrade"
| "same-origin"
| "origin"
| "strict-origin"
| "origin-when-cross-origin"
| "strict-origin-when-cross-origin"
| "unsafe-url"
| "";
export interface ReferrerPolicyOptions {
policy?: ReferrerPolicyToken | ReferrerPolicyToken[];
}
const ALLOWED_TOKENS = new Set<ReferrerPolicyToken>([
"no-referrer",
"no-referrer-when-downgrade",
"same-origin",
"origin",
"strict-origin",
"origin-when-cross-origin",
"strict-origin-when-cross-origin",
"unsafe-url",
"",
]);
function getHeaderValueFromOptions({
policy = ["no-referrer"],
}: Readonly<ReferrerPolicyOptions>): string {
const tokens = typeof policy === "string" ? [policy] : policy;
if (tokens.length === 0) {
throw new Error("Referrer-Policy received no policy tokens");
}
const tokensSeen = new Set<ReferrerPolicyToken>();
tokens.forEach((token) => {
if (!ALLOWED_TOKENS.has(token)) {
throw new Error(
`Referrer-Policy received an unexpected policy token ${JSON.stringify(
token
)}`
);
} else if (tokensSeen.has(token)) {
throw new Error(
`Referrer-Policy received a duplicate policy token ${JSON.stringify(
token
)}`
);
}
tokensSeen.add(token);
});
return tokens.join(",");
}
function referrerPolicy(options: Readonly<ReferrerPolicyOptions> = {}) {
const headerValue = getHeaderValueFromOptions(options);
return function referrerPolicyMiddleware(
_req: IncomingMessage,
res: ServerResponse,
next: () => void
) {
res.setHeader("Referrer-Policy", headerValue);
next();
};
}
export default referrerPolicy;