This repository was archived by the owner on Mar 6, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 197
/
Copy pathcors.js
164 lines (142 loc) · 4.94 KB
/
cors.js
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
"use strict";
module.exports = CORS;
const util = require("./helpers/util");
const swaggerMethods = require("@apidevtools/swagger-methods");
const _ = require("lodash");
// The CORS headers
let accessControl = {
allowOrigin: "access-control-allow-origin",
allowMethods: "access-control-allow-methods",
allowHeaders: "access-control-allow-headers",
allowCredentials: "access-control-allow-credentials",
maxAge: "access-control-max-age"
};
/**
* Handles CORS preflight requests and sets CORS headers for all requests according the Swagger API definition.
*
* @returns {function[]}
*/
function CORS () {
return [corsHeaders, corsPreflight];
}
/**
* Sets the CORS headers. If default values are specified in the Swagger API, then those values are used.
* Otherwise, sensible defaults are used.
*/
function corsHeaders (req, res, next) {
// Get the default CORS response headers as specified in the Swagger API
let responseHeaders = getResponseHeaders(req);
// Set each CORS header
_.each(accessControl, (header) => {
if (responseHeaders[header] !== undefined) {
// Set the header to the default value from the Swagger API
res.set(header, responseHeaders[header]);
}
else {
// Set the header to a sensible default
switch (header) {
case accessControl.allowOrigin:
// By default, allow the origin host. Fallback to wild-card.
res.set(header, req.get("Origin") || "*");
break;
case accessControl.allowMethods:
if (req.swagger && req.swagger.path) {
// Return the allowed methods for this Swagger path
res.set(header, util.getAllowedMethods(req.swagger.path));
}
else {
// By default, allow all of the requested methods. Fallback to ALL methods.
res.set(header, req.get("Access-Control-Request-Method") || swaggerMethods.join(", ").toUpperCase());
}
break;
case accessControl.allowHeaders:
// By default, allow all of the requested headers
res.set(header, req.get("Access-Control-Request-Headers") || "");
break;
case accessControl.allowCredentials:
// By default, allow credentials
res.set(header, true);
break;
case accessControl.maxAge:
// By default, access-control expires immediately.
res.set(header, 0);
break;
}
}
});
if (res.get(accessControl.allowOrigin) === "*") {
// If Access-Control-Allow-Origin is wild-carded, then Access-Control-Allow-Credentials must be false
res.set("Access-Control-Allow-Credentials", "false");
}
else {
// If Access-Control-Allow-Origin is set (not wild-carded), then "Vary: Origin" must be set
res.vary("Origin");
}
next();
}
/**
* Handles CORS preflight requests.
*/
function corsPreflight (req, res, next) {
if (req.method === "OPTIONS") {
util.debug("OPTIONS %s is a CORS preflight request. Sending HTTP 200 response.", req.path);
res.send();
}
else {
next();
}
}
/**
* Returns an object containing the CORS response headers that are defined in the Swagger API.
* If the same CORS header is defined for multiple responses, then the first one wins.
*
* @param {Request} req
* @returns {object}
*/
function getResponseHeaders (req) {
let corsHeaders = {};
if (req.swagger) {
let headers = [];
if (req.method !== "OPTIONS") {
// This isn't a preflight request, so the operation's response headers take precedence over the OPTIONS headers
headers = getOperationResponseHeaders(req.swagger.operation);
}
if (req.swagger.path) {
// Regardless of whether this is a preflight request, append the OPTIONS response headers
headers = headers.concat(getOperationResponseHeaders(req.swagger.path.options));
}
// Add the headers to the `corsHeaders` object. First one wins.
headers.forEach((header) => {
if (corsHeaders[header.name] === undefined) {
corsHeaders[header.name] = header.value;
}
});
}
return corsHeaders;
}
/**
* Returns all response headers for the given Swagger operation, sorted by HTTP response code.
*
* @param {object} operation - The Operation object from the Swagger API
* @returns {{responseCode: integer, name: string, value: string}[]}
*/
function getOperationResponseHeaders (operation) {
let headers = [];
if (operation) {
_.each(operation.responses, (response, responseCode) => {
// Convert responseCode to a numeric value for sorting ("default" comes last)
responseCode = parseInt(responseCode) || 999;
_.each(response.headers, (header, name) => {
// We only care about headers that have a default value defined
if (header.default !== undefined) {
headers.push({
order: responseCode,
name: name.toLowerCase(),
value: header.default
});
}
});
});
}
return _.sortBy(headers, "order");
}