@webiny/handler 0.0.0-unstable.ecd8734205 → 0.0.0-unstable.f6dc066313
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Context.d.ts +18 -10
- package/Context.js +17 -22
- package/Context.js.map +1 -1
- package/PreHandler/IPreHandler.d.ts +9 -0
- package/PreHandler/IPreHandler.js +7 -0
- package/PreHandler/IPreHandler.js.map +1 -0
- package/PreHandler/IfNotOptionsRequest.d.ts +9 -0
- package/PreHandler/IfNotOptionsRequest.js +21 -0
- package/PreHandler/IfNotOptionsRequest.js.map +1 -0
- package/PreHandler/IfOptionsRequest.d.ts +9 -0
- package/PreHandler/IfOptionsRequest.js +21 -0
- package/PreHandler/IfOptionsRequest.js.map +1 -0
- package/PreHandler/PreHandler.d.ts +9 -0
- package/PreHandler/PreHandler.js +17 -0
- package/PreHandler/PreHandler.js.map +1 -0
- package/PreHandler/ProcessBeforeHandlerPlugins.d.ts +10 -0
- package/PreHandler/ProcessBeforeHandlerPlugins.js +24 -0
- package/PreHandler/ProcessBeforeHandlerPlugins.js.map +1 -0
- package/PreHandler/ProcessContextPlugins.d.ts +10 -0
- package/PreHandler/ProcessContextPlugins.js +24 -0
- package/PreHandler/ProcessContextPlugins.js.map +1 -0
- package/PreHandler/ProcessHandlerOnRequestPlugins.d.ts +10 -0
- package/PreHandler/ProcessHandlerOnRequestPlugins.js +26 -0
- package/PreHandler/ProcessHandlerOnRequestPlugins.js.map +1 -0
- package/PreHandler/SendEarlyOptionsResponse.d.ts +9 -0
- package/PreHandler/SendEarlyOptionsResponse.js +31 -0
- package/PreHandler/SendEarlyOptionsResponse.js.map +1 -0
- package/PreHandler/SetDefaultHeaders.d.ts +9 -0
- package/PreHandler/SetDefaultHeaders.js +57 -0
- package/PreHandler/SetDefaultHeaders.js.map +1 -0
- package/README.md +10 -14
- package/ResponseHeaders.d.ts +24 -0
- package/ResponseHeaders.js +39 -0
- package/ResponseHeaders.js.map +1 -0
- package/abstractions/Reply.d.ts +5 -0
- package/abstractions/Reply.js +4 -0
- package/abstractions/Reply.js.map +1 -0
- package/abstractions/Request.d.ts +5 -0
- package/abstractions/Request.js +4 -0
- package/abstractions/Request.js.map +1 -0
- package/fastify.d.ts +8 -5
- package/fastify.js +238 -278
- package/fastify.js.map +1 -1
- package/index.d.ts +17 -10
- package/index.js +20 -135
- package/index.js.map +1 -1
- package/package.json +16 -26
- package/plugins/BeforeHandlerPlugin.d.ts +1 -1
- package/plugins/BeforeHandlerPlugin.js +5 -24
- package/plugins/BeforeHandlerPlugin.js.map +1 -1
- package/plugins/EventPlugin.d.ts +3 -3
- package/plugins/EventPlugin.js +5 -22
- package/plugins/EventPlugin.js.map +1 -1
- package/plugins/HandlerErrorPlugin.d.ts +6 -3
- package/plugins/HandlerErrorPlugin.js +5 -23
- package/plugins/HandlerErrorPlugin.js.map +1 -1
- package/plugins/HandlerOnRequestPlugin.d.ts +9 -8
- package/plugins/HandlerOnRequestPlugin.js +13 -23
- package/plugins/HandlerOnRequestPlugin.js.map +1 -1
- package/plugins/HandlerResultPlugin.d.ts +1 -1
- package/plugins/HandlerResultPlugin.js +5 -23
- package/plugins/HandlerResultPlugin.js.map +1 -1
- package/plugins/ModifyFastifyPlugin.d.ts +2 -2
- package/plugins/ModifyFastifyPlugin.js +5 -23
- package/plugins/ModifyFastifyPlugin.js.map +1 -1
- package/plugins/ModifyResponseHeadersPlugin.d.ts +14 -0
- package/plugins/ModifyResponseHeadersPlugin.js +16 -0
- package/plugins/ModifyResponseHeadersPlugin.js.map +1 -0
- package/plugins/OnRequestResponseSendPlugin.d.ts +26 -0
- package/plugins/OnRequestResponseSendPlugin.js +31 -0
- package/plugins/OnRequestResponseSendPlugin.js.map +1 -0
- package/plugins/OnRequestTimeoutPlugin.d.ts +12 -0
- package/plugins/OnRequestTimeoutPlugin.js +16 -0
- package/plugins/OnRequestTimeoutPlugin.js.map +1 -0
- package/plugins/RoutePlugin.d.ts +2 -2
- package/plugins/RoutePlugin.js +5 -22
- package/plugins/RoutePlugin.js.map +1 -1
- package/stringifyError.d.ts +5 -0
- package/stringifyError.js +20 -0
- package/stringifyError.js.map +1 -0
- package/suppressPunycodeWarnings.d.ts +1 -0
- package/suppressPunycodeWarnings.js +10 -0
- package/suppressPunycodeWarnings.js.map +1 -0
- package/types.d.ts +10 -13
- package/types.js +2 -18
- package/types.js.map +1 -1
- package/middleware.d.ts +0 -4
- package/middleware.js +0 -51
- package/middleware.js.map +0 -1
package/fastify.js
CHANGED
|
@@ -1,102 +1,48 @@
|
|
|
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
|
-
var _ModifyFastifyPlugin = require("./plugins/ModifyFastifyPlugin");
|
|
39
|
-
|
|
40
|
-
var _HandlerOnRequestPlugin = require("./plugins/HandlerOnRequestPlugin");
|
|
41
|
-
|
|
42
|
-
const DEFAULT_HEADERS = (0, _objectSpread2.default)({
|
|
43
|
-
"Cache-Control": "no-store",
|
|
44
|
-
"Content-Type": "application/json; charset=utf-8",
|
|
45
|
-
"Access-Control-Allow-Origin": "*",
|
|
46
|
-
"Access-Control-Allow-Headers": "*",
|
|
47
|
-
"Access-Control-Allow-Methods": "OPTIONS,POST,GET,DELETE,PUT,PATCH"
|
|
48
|
-
}, (0, _utils.getWebinyVersionHeaders)());
|
|
49
|
-
|
|
50
|
-
const getDefaultHeaders = routes => {
|
|
51
|
-
/**
|
|
52
|
-
* If we are accepting all headers, just output that one.
|
|
53
|
-
*/
|
|
54
|
-
const keys = Object.keys(routes);
|
|
55
|
-
const all = keys.every(key => routes[key].length > 0);
|
|
56
|
-
|
|
57
|
-
if (all) {
|
|
58
|
-
return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, DEFAULT_HEADERS), {}, {
|
|
59
|
-
"Access-Control-Allow-Methods": "*"
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, DEFAULT_HEADERS), {}, {
|
|
64
|
-
"Access-Control-Allow-Methods": keys.filter(type => {
|
|
65
|
-
if (!routes[type] || Array.isArray(routes[type]) === false) {
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return routes[type].length > 0;
|
|
70
|
-
}).sort().join(",")
|
|
1
|
+
import { PluginsContainer } from "@webiny/plugins/types.js";
|
|
2
|
+
import fastify from "fastify";
|
|
3
|
+
import { middleware } from "@webiny/utils";
|
|
4
|
+
import { Context } from "./Context.js";
|
|
5
|
+
import WebinyError from "@webiny/error";
|
|
6
|
+
import { RoutePlugin } from "./plugins/RoutePlugin.js";
|
|
7
|
+
import { createHandlerClient } from "@webiny/handler-client";
|
|
8
|
+
import fastifyCookie from "@fastify/cookie";
|
|
9
|
+
import fastifyCompress from "@fastify/compress";
|
|
10
|
+
import { ContextPlugin } from "@webiny/api";
|
|
11
|
+
import { BeforeHandlerPlugin } from "./plugins/BeforeHandlerPlugin.js";
|
|
12
|
+
import { HandlerResultPlugin } from "./plugins/HandlerResultPlugin.js";
|
|
13
|
+
import { HandlerErrorPlugin } from "./plugins/HandlerErrorPlugin.js";
|
|
14
|
+
import { ModifyFastifyPlugin } from "./plugins/ModifyFastifyPlugin.js";
|
|
15
|
+
import { HandlerOnRequestPlugin } from "./plugins/HandlerOnRequestPlugin.js";
|
|
16
|
+
import { ResponseHeaders } from "./ResponseHeaders.js";
|
|
17
|
+
import { ModifyResponseHeadersPlugin } from "./plugins/ModifyResponseHeadersPlugin.js";
|
|
18
|
+
import { SetDefaultHeaders } from "./PreHandler/SetDefaultHeaders.js";
|
|
19
|
+
import { PreHandler } from "./PreHandler/PreHandler.js";
|
|
20
|
+
import { stringifyError } from "./stringifyError.js";
|
|
21
|
+
import { ProcessHandlerOnRequestPlugins } from "./PreHandler/ProcessHandlerOnRequestPlugins.js";
|
|
22
|
+
import { ProcessContextPlugins } from "./PreHandler/ProcessContextPlugins.js";
|
|
23
|
+
import { IfNotOptionsRequest } from "./PreHandler/IfNotOptionsRequest.js";
|
|
24
|
+
import { ProcessBeforeHandlerPlugins } from "./PreHandler/ProcessBeforeHandlerPlugins.js";
|
|
25
|
+
import { IfOptionsRequest } from "./PreHandler/IfOptionsRequest.js";
|
|
26
|
+
import { SendEarlyOptionsResponse } from "./PreHandler/SendEarlyOptionsResponse.js";
|
|
27
|
+
import { OnRequestTimeoutPlugin } from "./plugins/OnRequestTimeoutPlugin.js";
|
|
28
|
+
import { OnRequestResponseSendPlugin } from "./plugins/OnRequestResponseSendPlugin.js";
|
|
29
|
+
import { Request } from "./abstractions/Request.js";
|
|
30
|
+
import { Reply } from "./abstractions/Reply.js";
|
|
31
|
+
const modifyResponseHeaders = (app, request, reply) => {
|
|
32
|
+
const modifyHeaders = app.webiny.plugins.byType(ModifyResponseHeadersPlugin.type);
|
|
33
|
+
const replyHeaders = reply.getHeaders();
|
|
34
|
+
const headers = ResponseHeaders.create(replyHeaders);
|
|
35
|
+
modifyHeaders.forEach(plugin => {
|
|
36
|
+
plugin.modify(request, headers);
|
|
71
37
|
});
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
const stringifyError = error => {
|
|
75
|
-
var _error$constructor;
|
|
76
38
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
data
|
|
83
|
-
} = error;
|
|
84
|
-
return JSON.stringify((0, _objectSpread2.default)((0, _objectSpread2.default)({}, error), {}, {
|
|
85
|
-
constructorName: ((_error$constructor = error.constructor) === null || _error$constructor === void 0 ? void 0 : _error$constructor.name) || "UnknownError",
|
|
86
|
-
name: name || "No error name",
|
|
87
|
-
message: message || "No error message",
|
|
88
|
-
code: code || "NO_CODE",
|
|
89
|
-
data,
|
|
90
|
-
stack: process.env.DEBUG === "true" ? stack : "Turn on the debug flag to see the stack."
|
|
91
|
-
}));
|
|
39
|
+
// Exclude 'set-cookie' header to avoid duplication.
|
|
40
|
+
// Cookies are managed by @fastify/cookie and calling reply.headers() with 'set-cookie' duplicates them.
|
|
41
|
+
const headersToSet = headers.getHeaders();
|
|
42
|
+
delete headersToSet["set-cookie"];
|
|
43
|
+
reply.headers(headersToSet);
|
|
92
44
|
};
|
|
93
|
-
|
|
94
|
-
const OPTIONS_HEADERS = {
|
|
95
|
-
"Access-Control-Max-Age": "86400",
|
|
96
|
-
"Cache-Control": "public, max-age=86400"
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
const createHandler = params => {
|
|
45
|
+
export const createHandler = params => {
|
|
100
46
|
const definedRoutes = {
|
|
101
47
|
POST: [],
|
|
102
48
|
GET: [],
|
|
@@ -113,93 +59,89 @@ const createHandler = params => {
|
|
|
113
59
|
PROPPATCH: [],
|
|
114
60
|
SEARCH: [],
|
|
115
61
|
TRACE: [],
|
|
116
|
-
UNLOCK: []
|
|
62
|
+
UNLOCK: [],
|
|
63
|
+
REPORT: [],
|
|
64
|
+
MKCALENDAR: []
|
|
117
65
|
};
|
|
118
|
-
|
|
119
66
|
const throwOnDefinedRoute = (type, path, options) => {
|
|
120
67
|
if (type === "ALL") {
|
|
121
|
-
const all = Object.keys(definedRoutes).find(
|
|
68
|
+
const all = Object.keys(definedRoutes).find(k => {
|
|
69
|
+
const key = k.toUpperCase();
|
|
122
70
|
const routes = definedRoutes[key];
|
|
123
71
|
return routes.includes(path);
|
|
124
72
|
});
|
|
125
|
-
|
|
126
73
|
if (!all) {
|
|
127
74
|
return;
|
|
128
75
|
}
|
|
129
|
-
|
|
130
|
-
console.
|
|
131
|
-
|
|
132
|
-
throw new _error.default(`You cannot override a route with onAll() method, please remove unnecessary route from the system.`, "OVERRIDE_ROUTE_ERROR", {
|
|
76
|
+
console.error(`Error while registering onAll route. One of the routes is already defined.`);
|
|
77
|
+
console.error(JSON.stringify(all));
|
|
78
|
+
throw new WebinyError(`You cannot override a route with onAll() method, please remove unnecessary route from the system.`, "OVERRIDE_ROUTE_ERROR", {
|
|
133
79
|
type,
|
|
134
80
|
path
|
|
135
81
|
});
|
|
136
82
|
} else if (definedRoutes[type].includes(path) === false) {
|
|
137
83
|
return;
|
|
138
|
-
} else if (
|
|
84
|
+
} else if (options?.override === true) {
|
|
139
85
|
return;
|
|
140
86
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
throw new _error.default(`When you are trying to override existing route, you must send "override" parameter when adding that route.`, "OVERRIDE_ROUTE_ERROR", {
|
|
87
|
+
console.error(`Error while trying to override route: [${type}] ${path}`);
|
|
88
|
+
throw new WebinyError(`When you are trying to override existing route, you must send "override" parameter when adding that route.`, "OVERRIDE_ROUTE_ERROR", {
|
|
144
89
|
type,
|
|
145
90
|
path
|
|
146
91
|
});
|
|
147
92
|
};
|
|
148
|
-
|
|
149
|
-
|
|
93
|
+
const addDefinedRoute = (input, path) => {
|
|
94
|
+
const type = input.toUpperCase();
|
|
150
95
|
if (!definedRoutes[type]) {
|
|
151
96
|
return;
|
|
152
97
|
} else if (definedRoutes[type].includes(path)) {
|
|
153
98
|
return;
|
|
154
99
|
}
|
|
155
|
-
|
|
156
100
|
definedRoutes[type].push(path);
|
|
157
101
|
};
|
|
102
|
+
|
|
158
103
|
/**
|
|
159
104
|
* We must attach the server to our internal context if we want to have it accessible.
|
|
160
105
|
*/
|
|
106
|
+
const app = fastify({
|
|
107
|
+
bodyLimit: 536870912,
|
|
108
|
+
// 512MB
|
|
109
|
+
disableRequestLogging: true,
|
|
110
|
+
allowErrorHandlerOverride: true,
|
|
111
|
+
...(params.options || {})
|
|
112
|
+
});
|
|
161
113
|
|
|
162
|
-
|
|
163
|
-
const app = (0, _fastify.default)((0, _objectSpread2.default)({}, params.options || {}));
|
|
164
114
|
/**
|
|
165
|
-
* We need to register routes in our system
|
|
115
|
+
* We need to register routes in our system to output headers later on, and disallow route overriding.
|
|
166
116
|
*/
|
|
167
|
-
|
|
168
117
|
app.addHook("onRoute", route => {
|
|
169
118
|
const method = route.method;
|
|
170
|
-
|
|
171
119
|
if (Array.isArray(method)) {
|
|
172
120
|
for (const m of method) {
|
|
173
121
|
addDefinedRoute(m, route.path);
|
|
174
122
|
}
|
|
175
|
-
|
|
176
123
|
return;
|
|
177
124
|
}
|
|
178
|
-
|
|
179
125
|
addDefinedRoute(method, route.path);
|
|
180
126
|
});
|
|
181
127
|
/**
|
|
182
128
|
* ############################
|
|
183
129
|
* Register the Fastify plugins.
|
|
184
130
|
*/
|
|
185
|
-
|
|
186
131
|
/**
|
|
187
132
|
* Package @fastify/cookie
|
|
188
133
|
*
|
|
189
134
|
* https://github.com/fastify/fastify-cookie
|
|
190
135
|
*/
|
|
191
|
-
|
|
192
|
-
app.register(_cookie.default, {
|
|
136
|
+
app.register(fastifyCookie, {
|
|
193
137
|
parseOptions: {} // options for parsing cookies
|
|
194
|
-
|
|
195
138
|
});
|
|
196
139
|
/**
|
|
197
140
|
* Package @fastify/compress
|
|
198
141
|
*
|
|
199
142
|
* https://github.com/fastify/fastify-compress
|
|
200
143
|
*/
|
|
201
|
-
|
|
202
|
-
app.register(_compress.default, {
|
|
144
|
+
app.register(fastifyCompress, {
|
|
203
145
|
global: true,
|
|
204
146
|
threshold: 1024,
|
|
205
147
|
onUnsupportedEncoding: (encoding, _, reply) => {
|
|
@@ -211,7 +153,6 @@ const createHandler = params => {
|
|
|
211
153
|
/**
|
|
212
154
|
* Route helpers - mostly for users.
|
|
213
155
|
*/
|
|
214
|
-
|
|
215
156
|
const routes = {
|
|
216
157
|
defined: definedRoutes,
|
|
217
158
|
onPost: (path, handler, options) => {
|
|
@@ -248,178 +189,133 @@ const createHandler = params => {
|
|
|
248
189
|
}
|
|
249
190
|
};
|
|
250
191
|
let context;
|
|
251
|
-
|
|
192
|
+
const plugins = new PluginsContainer([
|
|
193
|
+
/**
|
|
194
|
+
* We must have handlerClient by default.
|
|
195
|
+
* And it must be one of the first context plugins applied.
|
|
196
|
+
*/
|
|
197
|
+
createHandlerClient()]);
|
|
198
|
+
plugins.merge(params.plugins || []);
|
|
252
199
|
try {
|
|
253
|
-
context = new
|
|
254
|
-
plugins
|
|
200
|
+
context = new Context({
|
|
201
|
+
plugins,
|
|
255
202
|
/**
|
|
256
|
-
*
|
|
257
|
-
* And it must be one of the first context plugins applied.
|
|
258
|
-
*/
|
|
259
|
-
(0, _handlerClient.createHandlerClient)(), ...(params.plugins || [])],
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Inserted via webpack on build time.
|
|
203
|
+
* Inserted via webpack at build time.
|
|
263
204
|
*/
|
|
264
205
|
WEBINY_VERSION: process.env.WEBINY_VERSION,
|
|
265
|
-
server: app,
|
|
266
206
|
routes
|
|
267
207
|
});
|
|
268
208
|
} catch (ex) {
|
|
269
|
-
console.
|
|
270
|
-
console.
|
|
209
|
+
console.error(`Error while constructing the Context.`);
|
|
210
|
+
console.error(stringifyError(ex));
|
|
271
211
|
throw ex;
|
|
272
212
|
}
|
|
213
|
+
|
|
273
214
|
/**
|
|
274
215
|
* We are attaching our custom context to webiny variable on the fastify app, so it is accessible everywhere.
|
|
275
216
|
*/
|
|
276
|
-
|
|
277
|
-
|
|
278
217
|
app.decorate("webiny", context);
|
|
279
|
-
/**
|
|
280
|
-
* We have few types of triggers:
|
|
281
|
-
* * Events - EventPlugin
|
|
282
|
-
* * Routes - RoutePlugin
|
|
283
|
-
*
|
|
284
|
-
* Routes are registered in fastify but events must be handled in package which implements cloud specific methods.
|
|
285
|
-
*/
|
|
286
218
|
|
|
287
|
-
const routePlugins = app.webiny.plugins.byType(_RoutePlugin.RoutePlugin.type);
|
|
288
219
|
/**
|
|
289
|
-
*
|
|
220
|
+
* To prevent Unsupported Media Type errors on OPTIONS requests with a body,
|
|
221
|
+
* we need to have a custom parser
|
|
290
222
|
*/
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
plugin.cb((0, _objectSpread2.default)((0, _objectSpread2.default)({}, app.webiny.routes), {}, {
|
|
298
|
-
context: app.webiny
|
|
299
|
-
}));
|
|
300
|
-
}
|
|
301
|
-
} catch (ex) {
|
|
302
|
-
console.log(`Error while running the "RoutePlugin" ${routePluginName ? `(${routePluginName})` : ""} plugin in the beginning of the "createHandler" callable.`);
|
|
303
|
-
console.log(stringifyError(ex));
|
|
304
|
-
throw ex;
|
|
305
|
-
}
|
|
306
|
-
/**
|
|
307
|
-
* On every request we add default headers, which can be changed later.
|
|
308
|
-
* Also, if it is an options request, we skip everything after this hook and output options headers.
|
|
309
|
-
*/
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
app.addHook("onRequest", async (request, reply) => {
|
|
313
|
-
/**
|
|
314
|
-
* Our default headers are always set. Users can override them.
|
|
315
|
-
*/
|
|
316
|
-
const defaultHeaders = getDefaultHeaders(definedRoutes);
|
|
317
|
-
reply.headers(defaultHeaders);
|
|
318
|
-
/**
|
|
319
|
-
* Users can define their own custom handlers for the onRequest event - so let's run them first.
|
|
320
|
-
*/
|
|
321
|
-
|
|
322
|
-
const plugins = app.webiny.plugins.byType(_HandlerOnRequestPlugin.HandlerOnRequestPlugin.type);
|
|
323
|
-
let name;
|
|
324
|
-
|
|
325
|
-
try {
|
|
326
|
-
for (const plugin of plugins) {
|
|
327
|
-
name = plugin.name;
|
|
328
|
-
const result = await plugin.exec(request, reply);
|
|
329
|
-
|
|
330
|
-
if (result === false) {
|
|
331
|
-
return;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
} catch (ex) {
|
|
335
|
-
console.log(`Error while running the "HandlerOnRequestPlugin" ${name ? `(${name})` : ""} plugin in the onRequest hook.`);
|
|
336
|
-
console.log(stringifyError(ex));
|
|
337
|
-
throw ex;
|
|
338
|
-
}
|
|
339
|
-
/**
|
|
340
|
-
* When we receive the OPTIONS request, we end it before it goes any further as there is no need for anything to run after this - at least for our use cases.
|
|
341
|
-
*
|
|
342
|
-
* Users can prevent this by creating their own HandlerOnRequestPlugin and returning false as the result of the callable.
|
|
343
|
-
*/
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
if (request.method !== "OPTIONS") {
|
|
223
|
+
app.addContentTypeParser("application/json", {
|
|
224
|
+
parseAs: "string",
|
|
225
|
+
bodyLimit: 1024 * 1024
|
|
226
|
+
}, (req, body, done) => {
|
|
227
|
+
if (req.method === "OPTIONS") {
|
|
228
|
+
done(null, undefined);
|
|
347
229
|
return;
|
|
348
230
|
}
|
|
349
|
-
|
|
350
|
-
if (reply.sent) {
|
|
351
|
-
/**
|
|
352
|
-
* At this point throwing an exception will not do anything with the response. So just log it.
|
|
353
|
-
*/
|
|
354
|
-
console.log(JSON.stringify({
|
|
355
|
-
message: `Output was already sent. Please check custom plugins of type "HandlerOnRequestPlugin".`,
|
|
356
|
-
explanation: "This error can happen if the user plugin ended the reply, but did not return false as response."
|
|
357
|
-
}));
|
|
358
|
-
return;
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
reply.headers((0, _objectSpread2.default)((0, _objectSpread2.default)({}, defaultHeaders), OPTIONS_HEADERS)).code(204).send("").hijack();
|
|
362
|
-
});
|
|
363
|
-
app.addHook("preParsing", async (request, reply) => {
|
|
364
|
-
app.webiny.request = request;
|
|
365
|
-
app.webiny.reply = reply;
|
|
366
|
-
const plugins = app.webiny.plugins.byType(_api.ContextPlugin.type);
|
|
367
|
-
let name;
|
|
368
|
-
|
|
369
231
|
try {
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
} catch (ex) {
|
|
375
|
-
console.log(`Error while running the "ContextPlugin" ${name ? `(${name})` : ""} plugin in the preParsing hook.`);
|
|
376
|
-
console.log(stringifyError(ex));
|
|
377
|
-
throw ex;
|
|
232
|
+
const json = typeof body === "string" ? body : body.toString("utf8");
|
|
233
|
+
done(null, JSON.parse(json));
|
|
234
|
+
} catch (err) {
|
|
235
|
+
done(err);
|
|
378
236
|
}
|
|
379
237
|
});
|
|
238
|
+
|
|
380
239
|
/**
|
|
240
|
+
* With this we ensure that an undefined request body is not parsed on OPTIONS requests,
|
|
241
|
+
* in case there's a `content-type` header set for whatever reason.
|
|
381
242
|
*
|
|
243
|
+
* @see https://fastify.dev/docs/latest/Reference/ContentTypeParser/#content-type-parser
|
|
382
244
|
*/
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
let name;
|
|
387
|
-
|
|
388
|
-
try {
|
|
389
|
-
for (const plugin of plugins) {
|
|
390
|
-
name = plugin.name;
|
|
391
|
-
await plugin.apply(app.webiny);
|
|
392
|
-
}
|
|
393
|
-
} catch (ex) {
|
|
394
|
-
console.log(`Error while running the "BeforeHandlerPlugin" ${name ? `(${name})` : ""} plugin in the preHandler hook.`);
|
|
395
|
-
console.log(stringifyError(ex));
|
|
396
|
-
throw ex;
|
|
245
|
+
app.addHook("onRequest", async request => {
|
|
246
|
+
if (request.method === "OPTIONS" && request.body === undefined) {
|
|
247
|
+
request.headers["content-type"] = undefined;
|
|
397
248
|
}
|
|
398
249
|
});
|
|
250
|
+
|
|
399
251
|
/**
|
|
400
|
-
*
|
|
252
|
+
* At this point, request body is properly parsed, and we can execute Webiny business logic.
|
|
253
|
+
* - set default headers
|
|
254
|
+
* - process `HandlerOnRequestPlugin`
|
|
255
|
+
* - if OPTIONS request, exit early
|
|
256
|
+
* - process `ContextPlugin`
|
|
257
|
+
* - process `BeforeHandlerPlugin`
|
|
401
258
|
*/
|
|
259
|
+
app.addHook("preHandler", async (request, reply) => {
|
|
260
|
+
app.webiny.request = request;
|
|
261
|
+
app.webiny.reply = reply;
|
|
402
262
|
|
|
403
|
-
|
|
404
|
-
|
|
263
|
+
// Bind request and reply to DI container for runtime access
|
|
264
|
+
if (app.webiny.container) {
|
|
265
|
+
app.webiny.container.registerInstance(Request, request);
|
|
266
|
+
app.webiny.container.registerInstance(Reply, reply);
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Default code to 200 - so we do not need to set it again.
|
|
270
|
+
* Usually we set errors manually when we use reply.send.
|
|
271
|
+
*/
|
|
272
|
+
reply.code(200);
|
|
273
|
+
const handlerOnRequestPlugins = app.webiny.plugins.byType(HandlerOnRequestPlugin.type);
|
|
274
|
+
const contextPlugins = app.webiny.plugins.byType(ContextPlugin.type);
|
|
275
|
+
const beforeHandlerPlugins = app.webiny.plugins.byType(BeforeHandlerPlugin.type);
|
|
276
|
+
const modifyHeadersPlugins = app.webiny.plugins.byType(ModifyResponseHeadersPlugin.type);
|
|
277
|
+
const preHandler = new PreHandler([new SetDefaultHeaders(definedRoutes), new ProcessHandlerOnRequestPlugins(handlerOnRequestPlugins), new IfNotOptionsRequest([new ProcessContextPlugins(app.webiny, contextPlugins), new ProcessBeforeHandlerPlugins(app.webiny, beforeHandlerPlugins)]), new IfOptionsRequest([new SendEarlyOptionsResponse(modifyHeadersPlugins)])]);
|
|
278
|
+
await preHandler.execute(request, reply, app.webiny);
|
|
279
|
+
});
|
|
280
|
+
app.addHook("preSerialization", async (_, __, payload) => {
|
|
281
|
+
const plugins = app.webiny.plugins.byType(HandlerResultPlugin.type);
|
|
405
282
|
let name;
|
|
406
|
-
|
|
407
283
|
try {
|
|
408
284
|
for (const plugin of plugins) {
|
|
409
285
|
name = plugin.name;
|
|
410
286
|
await plugin.handle(app.webiny, payload);
|
|
411
287
|
}
|
|
412
288
|
} catch (ex) {
|
|
413
|
-
console.
|
|
414
|
-
console.
|
|
289
|
+
console.error(`Error while running the "HandlerResultPlugin" ${name ? `(${name})` : ""} plugin in the preSerialization hook.`);
|
|
290
|
+
console.error(stringifyError(ex));
|
|
415
291
|
throw ex;
|
|
416
292
|
}
|
|
417
|
-
|
|
418
293
|
return payload;
|
|
419
|
-
};
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
294
|
+
});
|
|
295
|
+
app.setErrorHandler(async (error, _, reply) => {
|
|
296
|
+
/**
|
|
297
|
+
* IMPORTANT! Do not send anything if reply was already sent.
|
|
298
|
+
*/
|
|
299
|
+
if (reply.sent) {
|
|
300
|
+
console.warn("Reply already sent, cannot send the result (handler:setErrorHandler).");
|
|
301
|
+
return reply;
|
|
302
|
+
}
|
|
303
|
+
if (error.code?.startsWith("Authentication/")) {
|
|
304
|
+
return reply.status(401).headers({
|
|
305
|
+
"Cache-Control": "no-store"
|
|
306
|
+
}).send(JSON.stringify({
|
|
307
|
+
message: error.message,
|
|
308
|
+
code: error.code
|
|
309
|
+
}));
|
|
310
|
+
}
|
|
311
|
+
if (error.code === "Tenancy/TenantDisabled") {
|
|
312
|
+
return reply.status(503).headers({
|
|
313
|
+
"Cache-Control": "no-store"
|
|
314
|
+
}).send(JSON.stringify({
|
|
315
|
+
message: error.message,
|
|
316
|
+
code: error.code
|
|
317
|
+
}));
|
|
318
|
+
}
|
|
423
319
|
return reply.status(500).headers({
|
|
424
320
|
"Cache-Control": "no-store"
|
|
425
321
|
}).send(
|
|
@@ -433,25 +329,37 @@ const createHandler = params => {
|
|
|
433
329
|
}));
|
|
434
330
|
});
|
|
435
331
|
app.addHook("onError", async (_, reply, error) => {
|
|
436
|
-
const plugins = app.webiny.plugins.byType(
|
|
332
|
+
const plugins = app.webiny.plugins.byType(HandlerErrorPlugin.type);
|
|
437
333
|
/**
|
|
438
334
|
* Log error to cloud, as these can be extremely annoying to debug!
|
|
439
335
|
*/
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
"
|
|
445
|
-
|
|
336
|
+
console.error("Logging error in @webiny/handler");
|
|
337
|
+
try {
|
|
338
|
+
console.error(stringifyError(error));
|
|
339
|
+
} catch (ex) {
|
|
340
|
+
console.warn("Could not stringify error:");
|
|
341
|
+
console.log(error);
|
|
342
|
+
console.error("Stringify error:", ex);
|
|
343
|
+
}
|
|
446
344
|
/**
|
|
447
|
-
*
|
|
345
|
+
* IMPORTANT! Do not send anything if reply was already sent.
|
|
448
346
|
*/
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
347
|
+
if (!reply.sent) {
|
|
348
|
+
reply.status(500).headers({
|
|
349
|
+
"Cache-Control": "no-store"
|
|
350
|
+
}).send(
|
|
351
|
+
/**
|
|
352
|
+
* When we are sending the error in the response, we cannot send the whole error object, as it might contain some sensitive data.
|
|
353
|
+
*/
|
|
354
|
+
JSON.stringify({
|
|
355
|
+
message: error.message,
|
|
356
|
+
code: error.code,
|
|
357
|
+
data: error.data
|
|
358
|
+
}));
|
|
359
|
+
} else {
|
|
360
|
+
console.warn("Reply already sent, cannot send the result (handler:addHook:onError).");
|
|
361
|
+
}
|
|
362
|
+
const handler = middleware(plugins.map(pl => {
|
|
455
363
|
return (context, error, next) => {
|
|
456
364
|
return pl.handle(context, error, next);
|
|
457
365
|
};
|
|
@@ -459,25 +367,77 @@ const createHandler = params => {
|
|
|
459
367
|
await handler(app.webiny, error);
|
|
460
368
|
return reply;
|
|
461
369
|
});
|
|
370
|
+
|
|
462
371
|
/**
|
|
463
|
-
*
|
|
372
|
+
* Apply response headers modifier plugins.
|
|
464
373
|
*/
|
|
374
|
+
app.addHook("onSend", async (request, reply, input) => {
|
|
375
|
+
modifyResponseHeaders(app, request, reply);
|
|
376
|
+
const plugins = app.webiny.plugins.byType(OnRequestResponseSendPlugin.type);
|
|
377
|
+
let payload = input;
|
|
378
|
+
for (const plugin of plugins) {
|
|
379
|
+
payload = await plugin.exec(request, reply, payload);
|
|
380
|
+
}
|
|
381
|
+
return payload;
|
|
382
|
+
});
|
|
465
383
|
|
|
466
|
-
|
|
467
|
-
|
|
384
|
+
/**
|
|
385
|
+
* We need to output the benchmark results at the end of the request in both response and timeout cases
|
|
386
|
+
*/
|
|
387
|
+
app.addHook("onResponse", async () => {
|
|
388
|
+
await context.benchmark.output();
|
|
389
|
+
});
|
|
390
|
+
app.addHook("onTimeout", async (request, reply) => {
|
|
391
|
+
const plugins = app.webiny.plugins.byType(OnRequestTimeoutPlugin.type);
|
|
392
|
+
for (const plugin of plugins) {
|
|
393
|
+
await plugin.exec(request, reply);
|
|
394
|
+
}
|
|
395
|
+
await context.benchmark.output();
|
|
396
|
+
});
|
|
468
397
|
|
|
398
|
+
/**
|
|
399
|
+
* With these plugins we give users possibility to do anything they want on our fastify instance.
|
|
400
|
+
*/
|
|
401
|
+
const modifyPlugins = app.webiny.plugins.byType(ModifyFastifyPlugin.type);
|
|
402
|
+
let modifyFastifyPluginName;
|
|
469
403
|
try {
|
|
470
404
|
for (const plugin of modifyPlugins) {
|
|
471
405
|
modifyFastifyPluginName = plugin.name;
|
|
472
406
|
plugin.modify(app);
|
|
473
407
|
}
|
|
474
408
|
} catch (ex) {
|
|
475
|
-
console.
|
|
476
|
-
console.
|
|
409
|
+
console.error(`Error while running the "ModifyFastifyPlugin" ${modifyFastifyPluginName ? `(${modifyFastifyPluginName})` : ""} plugin in the end of the "createHandler" callable.`);
|
|
410
|
+
console.error(stringifyError(ex));
|
|
477
411
|
throw ex;
|
|
478
412
|
}
|
|
479
413
|
|
|
414
|
+
/**
|
|
415
|
+
* We have few types of triggers:
|
|
416
|
+
* * Events - EventPlugin
|
|
417
|
+
* * Routes - RoutePlugin
|
|
418
|
+
*
|
|
419
|
+
* Routes are registered in fastify but events must be handled in package which implements cloud specific methods.
|
|
420
|
+
*/
|
|
421
|
+
const routePlugins = app.webiny.plugins.byType(RoutePlugin.type);
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Add routes to the system.
|
|
425
|
+
*/
|
|
426
|
+
let routePluginName;
|
|
427
|
+
try {
|
|
428
|
+
for (const plugin of routePlugins) {
|
|
429
|
+
routePluginName = plugin.name;
|
|
430
|
+
plugin.cb({
|
|
431
|
+
...app.webiny.routes,
|
|
432
|
+
context: app.webiny
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
} catch (ex) {
|
|
436
|
+
console.error(`Error while running the "RoutePlugin" ${routePluginName ? `(${routePluginName})` : ""} plugin in the beginning of the "createHandler" callable.`);
|
|
437
|
+
console.error(stringifyError(ex));
|
|
438
|
+
throw ex;
|
|
439
|
+
}
|
|
480
440
|
return app;
|
|
481
441
|
};
|
|
482
442
|
|
|
483
|
-
|
|
443
|
+
//# sourceMappingURL=fastify.js.map
|