@webiny/handler 0.0.0-unstable.de38392959 → 0.0.0-unstable.df7a8bb475

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.
Files changed (89) hide show
  1. package/Context.d.ts +4 -3
  2. package/Context.js +6 -14
  3. package/Context.js.map +1 -1
  4. package/PreHandler/IPreHandler.d.ts +9 -0
  5. package/PreHandler/IPreHandler.js +7 -0
  6. package/PreHandler/IPreHandler.js.map +1 -0
  7. package/PreHandler/IfNotOptionsRequest.d.ts +9 -0
  8. package/PreHandler/IfNotOptionsRequest.js +21 -0
  9. package/PreHandler/IfNotOptionsRequest.js.map +1 -0
  10. package/PreHandler/IfOptionsRequest.d.ts +9 -0
  11. package/PreHandler/IfOptionsRequest.js +21 -0
  12. package/PreHandler/IfOptionsRequest.js.map +1 -0
  13. package/PreHandler/PreHandler.d.ts +9 -0
  14. package/PreHandler/PreHandler.js +17 -0
  15. package/PreHandler/PreHandler.js.map +1 -0
  16. package/PreHandler/ProcessBeforeHandlerPlugins.d.ts +10 -0
  17. package/PreHandler/ProcessBeforeHandlerPlugins.js +24 -0
  18. package/PreHandler/ProcessBeforeHandlerPlugins.js.map +1 -0
  19. package/PreHandler/ProcessContextPlugins.d.ts +10 -0
  20. package/PreHandler/ProcessContextPlugins.js +24 -0
  21. package/PreHandler/ProcessContextPlugins.js.map +1 -0
  22. package/PreHandler/ProcessHandlerOnRequestPlugins.d.ts +10 -0
  23. package/PreHandler/ProcessHandlerOnRequestPlugins.js +26 -0
  24. package/PreHandler/ProcessHandlerOnRequestPlugins.js.map +1 -0
  25. package/PreHandler/SendEarlyOptionsResponse.d.ts +9 -0
  26. package/PreHandler/SendEarlyOptionsResponse.js +31 -0
  27. package/PreHandler/SendEarlyOptionsResponse.js.map +1 -0
  28. package/PreHandler/SetDefaultHeaders.d.ts +9 -0
  29. package/PreHandler/SetDefaultHeaders.js +57 -0
  30. package/PreHandler/SetDefaultHeaders.js.map +1 -0
  31. package/README.md +10 -14
  32. package/ResponseHeaders.d.ts +6 -7
  33. package/ResponseHeaders.js +1 -8
  34. package/ResponseHeaders.js.map +1 -1
  35. package/abstractions/Reply.d.ts +5 -0
  36. package/abstractions/Reply.js +4 -0
  37. package/abstractions/Reply.js.map +1 -0
  38. package/abstractions/Request.d.ts +5 -0
  39. package/abstractions/Request.js +4 -0
  40. package/abstractions/Request.js.map +1 -0
  41. package/fastify.d.ts +6 -4
  42. package/fastify.js +177 -193
  43. package/fastify.js.map +1 -1
  44. package/index.d.ts +17 -12
  45. package/index.js +18 -126
  46. package/index.js.map +1 -1
  47. package/package.json +16 -24
  48. package/plugins/BeforeHandlerPlugin.d.ts +1 -1
  49. package/plugins/BeforeHandlerPlugin.js +3 -11
  50. package/plugins/BeforeHandlerPlugin.js.map +1 -1
  51. package/plugins/EventPlugin.d.ts +3 -3
  52. package/plugins/EventPlugin.js +3 -12
  53. package/plugins/EventPlugin.js.map +1 -1
  54. package/plugins/HandlerErrorPlugin.d.ts +1 -1
  55. package/plugins/HandlerErrorPlugin.js +3 -11
  56. package/plugins/HandlerErrorPlugin.js.map +1 -1
  57. package/plugins/HandlerOnRequestPlugin.d.ts +9 -8
  58. package/plugins/HandlerOnRequestPlugin.js +5 -12
  59. package/plugins/HandlerOnRequestPlugin.js.map +1 -1
  60. package/plugins/HandlerResultPlugin.d.ts +1 -1
  61. package/plugins/HandlerResultPlugin.js +3 -11
  62. package/plugins/HandlerResultPlugin.js.map +1 -1
  63. package/plugins/ModifyFastifyPlugin.d.ts +2 -2
  64. package/plugins/ModifyFastifyPlugin.js +3 -11
  65. package/plugins/ModifyFastifyPlugin.js.map +1 -1
  66. package/plugins/ModifyResponseHeadersPlugin.d.ts +3 -3
  67. package/plugins/ModifyResponseHeadersPlugin.js +3 -11
  68. package/plugins/ModifyResponseHeadersPlugin.js.map +1 -1
  69. package/plugins/OnRequestResponseSendPlugin.d.ts +26 -0
  70. package/plugins/OnRequestResponseSendPlugin.js +31 -0
  71. package/plugins/OnRequestResponseSendPlugin.js.map +1 -0
  72. package/plugins/OnRequestTimeoutPlugin.d.ts +12 -0
  73. package/plugins/OnRequestTimeoutPlugin.js +16 -0
  74. package/plugins/OnRequestTimeoutPlugin.js.map +1 -0
  75. package/plugins/RoutePlugin.d.ts +2 -2
  76. package/plugins/RoutePlugin.js +3 -11
  77. package/plugins/RoutePlugin.js.map +1 -1
  78. package/stringifyError.d.ts +5 -0
  79. package/stringifyError.js +20 -0
  80. package/stringifyError.js.map +1 -0
  81. package/suppressPunycodeWarnings.d.ts +1 -0
  82. package/suppressPunycodeWarnings.js +10 -0
  83. package/suppressPunycodeWarnings.js.map +1 -0
  84. package/types.d.ts +9 -7
  85. package/types.js +1 -19
  86. package/types.js.map +1 -1
  87. package/middleware.d.ts +0 -7
  88. package/middleware.js +0 -47
  89. package/middleware.js.map +0 -1
package/fastify.d.ts CHANGED
@@ -1,9 +1,11 @@
1
- /// <reference types="node" />
2
- import { PluginCollection, PluginsContainer } from "@webiny/plugins/types";
3
- import { FastifyServerOptions as ServerOptions } from "fastify";
1
+ import type { PluginCollection } from "@webiny/plugins/types.js";
2
+ import { PluginsContainer } from "@webiny/plugins/types.js";
3
+ import type { FastifyInstance, FastifyServerOptions as ServerOptions } from "fastify";
4
4
  export interface CreateHandlerParams {
5
5
  plugins: PluginCollection | PluginsContainer;
6
6
  options?: ServerOptions;
7
7
  debug?: boolean;
8
8
  }
9
- export declare const createHandler: (params: CreateHandlerParams) => import("fastify").FastifyInstance<import("fastify").RawServerDefault, import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>, import("fastify").FastifyBaseLogger, import("fastify").FastifyTypeProviderDefault> & PromiseLike<import("fastify").FastifyInstance<import("fastify").RawServerDefault, import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>, import("fastify").FastifyBaseLogger, import("fastify").FastifyTypeProviderDefault>>;
9
+ export declare const createHandler: (params: CreateHandlerParams) => FastifyInstance<import("fastify").RawServerDefault, import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>, import("fastify").FastifyBaseLogger, import("fastify").FastifyTypeProviderDefault> & PromiseLike<FastifyInstance<import("fastify").RawServerDefault, import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>, import("fastify").FastifyBaseLogger, import("fastify").FastifyTypeProviderDefault>> & {
10
+ __linterBrands: "SafePromiseLike";
11
+ };
package/fastify.js CHANGED
@@ -1,84 +1,48 @@
1
- "use strict";
2
-
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
- Object.defineProperty(exports, "__esModule", {
5
- value: true
6
- });
7
- exports.createHandler = void 0;
8
- var _types = require("@webiny/plugins/types");
9
- var _fastify = _interopRequireDefault(require("fastify"));
10
- var _utils = require("@webiny/utils");
11
- var _Context = require("./Context");
12
- var _error = _interopRequireDefault(require("@webiny/error"));
13
- var _RoutePlugin = require("./plugins/RoutePlugin");
14
- var _handlerClient = require("@webiny/handler-client");
15
- var _cookie = _interopRequireDefault(require("@fastify/cookie"));
16
- var _compress = _interopRequireDefault(require("@fastify/compress"));
17
- var _middleware = require("./middleware");
18
- var _api = require("@webiny/api");
19
- var _BeforeHandlerPlugin = require("./plugins/BeforeHandlerPlugin");
20
- var _HandlerResultPlugin = require("./plugins/HandlerResultPlugin");
21
- var _HandlerErrorPlugin = require("./plugins/HandlerErrorPlugin");
22
- var _ModifyFastifyPlugin = require("./plugins/ModifyFastifyPlugin");
23
- var _HandlerOnRequestPlugin = require("./plugins/HandlerOnRequestPlugin");
24
- var _ResponseHeaders = require("./ResponseHeaders");
25
- var _ModifyResponseHeadersPlugin = require("./plugins/ModifyResponseHeadersPlugin");
26
- function createDefaultHeaders() {
27
- return _ResponseHeaders.ResponseHeaders.create({
28
- "content-type": "application/json; charset=utf-8",
29
- "cache-control": "no-store",
30
- "access-control-allow-origin": "*",
31
- "access-control-allow-headers": "*",
32
- "access-control-allow-methods": "OPTIONS,POST,GET,DELETE,PUT,PATCH",
33
- ...(0, _utils.getWebinyVersionHeaders)()
34
- });
35
- }
36
- const getDefaultOptionsHeaders = () => {
37
- return _ResponseHeaders.ResponseHeaders.create({
38
- "access-control-max-age": "86400",
39
- "cache-control": "public, max-age=86400"
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);
40
37
  });
41
- };
42
- const getDefaultHeaders = routes => {
43
- const headers = createDefaultHeaders();
44
38
 
45
- /**
46
- * If we are accepting all headers, just output that one.
47
- */
48
- const keys = Object.keys(routes);
49
- const all = keys.every(key => routes[key].length > 0);
50
- if (all) {
51
- headers.set("access-control-allow-methods", "*");
52
- } else {
53
- const allowedMethods = keys.filter(type => {
54
- if (!routes[type] || !Array.isArray(routes[type])) {
55
- return false;
56
- }
57
- return routes[type].length > 0;
58
- }).sort().join(",");
59
- headers.set("access-control-allow-methods", allowedMethods);
60
- }
61
- return headers;
62
- };
63
- const stringifyError = error => {
64
- const {
65
- name,
66
- message,
67
- code,
68
- stack,
69
- data
70
- } = error;
71
- return JSON.stringify({
72
- ...error,
73
- constructorName: error.constructor?.name || "UnknownError",
74
- name: name || "No error name",
75
- message: message || "No error message",
76
- code: code || "NO_CODE",
77
- data,
78
- stack: process.env.DEBUG === "true" ? stack : "Turn on the debug flag to see the stack."
79
- });
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);
80
44
  };
81
- const createHandler = params => {
45
+ export const createHandler = params => {
82
46
  const definedRoutes = {
83
47
  POST: [],
84
48
  GET: [],
@@ -95,11 +59,14 @@ const createHandler = params => {
95
59
  PROPPATCH: [],
96
60
  SEARCH: [],
97
61
  TRACE: [],
98
- UNLOCK: []
62
+ UNLOCK: [],
63
+ REPORT: [],
64
+ MKCALENDAR: []
99
65
  };
100
66
  const throwOnDefinedRoute = (type, path, options) => {
101
67
  if (type === "ALL") {
102
- const all = Object.keys(definedRoutes).find(key => {
68
+ const all = Object.keys(definedRoutes).find(k => {
69
+ const key = k.toUpperCase();
103
70
  const routes = definedRoutes[key];
104
71
  return routes.includes(path);
105
72
  });
@@ -108,7 +75,7 @@ const createHandler = params => {
108
75
  }
109
76
  console.error(`Error while registering onAll route. One of the routes is already defined.`);
110
77
  console.error(JSON.stringify(all));
111
- throw new _error.default(`You cannot override a route with onAll() method, please remove unnecessary route from the system.`, "OVERRIDE_ROUTE_ERROR", {
78
+ throw new WebinyError(`You cannot override a route with onAll() method, please remove unnecessary route from the system.`, "OVERRIDE_ROUTE_ERROR", {
112
79
  type,
113
80
  path
114
81
  });
@@ -118,12 +85,13 @@ const createHandler = params => {
118
85
  return;
119
86
  }
120
87
  console.error(`Error while trying to override route: [${type}] ${path}`);
121
- throw new _error.default(`When you are trying to override existing route, you must send "override" parameter when adding that route.`, "OVERRIDE_ROUTE_ERROR", {
88
+ throw new WebinyError(`When you are trying to override existing route, you must send "override" parameter when adding that route.`, "OVERRIDE_ROUTE_ERROR", {
122
89
  type,
123
90
  path
124
91
  });
125
92
  };
126
- const addDefinedRoute = (type, path) => {
93
+ const addDefinedRoute = (input, path) => {
94
+ const type = input.toUpperCase();
127
95
  if (!definedRoutes[type]) {
128
96
  return;
129
97
  } else if (definedRoutes[type].includes(path)) {
@@ -131,16 +99,20 @@ const createHandler = params => {
131
99
  }
132
100
  definedRoutes[type].push(path);
133
101
  };
102
+
134
103
  /**
135
104
  * We must attach the server to our internal context if we want to have it accessible.
136
105
  */
137
- const app = (0, _fastify.default)({
138
- bodyLimit: 10485760,
139
- // 10MB
106
+ const app = fastify({
107
+ bodyLimit: 536870912,
108
+ // 512MB
109
+ disableRequestLogging: true,
110
+ allowErrorHandlerOverride: true,
140
111
  ...(params.options || {})
141
112
  });
113
+
142
114
  /**
143
- * We need to register routes in our system so we can output headers later on and dissallow overriding routes.
115
+ * We need to register routes in our system to output headers later on, and disallow route overriding.
144
116
  */
145
117
  app.addHook("onRoute", route => {
146
118
  const method = route.method;
@@ -161,7 +133,7 @@ const createHandler = params => {
161
133
  *
162
134
  * https://github.com/fastify/fastify-cookie
163
135
  */
164
- app.register(_cookie.default, {
136
+ app.register(fastifyCookie, {
165
137
  parseOptions: {} // options for parsing cookies
166
138
  });
167
139
  /**
@@ -169,7 +141,7 @@ const createHandler = params => {
169
141
  *
170
142
  * https://github.com/fastify/fastify-compress
171
143
  */
172
- app.register(_compress.default, {
144
+ app.register(fastifyCompress, {
173
145
  global: true,
174
146
  threshold: 1024,
175
147
  onUnsupportedEncoding: (encoding, _, reply) => {
@@ -217,15 +189,15 @@ const createHandler = params => {
217
189
  }
218
190
  };
219
191
  let context;
220
- const plugins = new _types.PluginsContainer([
192
+ const plugins = new PluginsContainer([
221
193
  /**
222
194
  * We must have handlerClient by default.
223
195
  * And it must be one of the first context plugins applied.
224
196
  */
225
- (0, _handlerClient.createHandlerClient)()]);
197
+ createHandlerClient()]);
226
198
  plugins.merge(params.plugins || []);
227
199
  try {
228
- context = new _Context.Context({
200
+ context = new Context({
229
201
  plugins,
230
202
  /**
231
203
  * Inserted via webpack at build time.
@@ -245,94 +217,68 @@ const createHandler = params => {
245
217
  app.decorate("webiny", context);
246
218
 
247
219
  /**
248
- * On every request we add default headers, which can be changed later.
249
- * Also, if it is an options request, we skip everything after this hook and output options headers.
220
+ * To prevent Unsupported Media Type errors on OPTIONS requests with a body,
221
+ * we need to have a custom parser
250
222
  */
251
- app.addHook("onRequest", async (request, reply) => {
252
- const isOptionsRequest = request.method === "OPTIONS";
253
- /**
254
- * Our default headers are always set. Users can override them.
255
- */
256
- const defaultHeaders = getDefaultHeaders(definedRoutes);
257
- const initialHeaders = isOptionsRequest ? defaultHeaders.merge(getDefaultOptionsHeaders()) : defaultHeaders;
258
- reply.headers(initialHeaders.getHeaders());
259
- /**
260
- * Users can define their own custom handlers for the onRequest event - so let's run them first.
261
- */
262
- const plugins = app.webiny.plugins.byType(_HandlerOnRequestPlugin.HandlerOnRequestPlugin.type);
263
- let name;
264
- try {
265
- for (const plugin of plugins) {
266
- name = plugin.name;
267
- const result = await plugin.exec(request, reply);
268
- if (result === false) {
269
- return;
270
- }
271
- }
272
- } catch (ex) {
273
- console.error(`Error while running the "HandlerOnRequestPlugin" ${name ? `(${name})` : ""} plugin in the onRequest hook.`);
274
- console.error(stringifyError(ex));
275
- throw ex;
276
- }
277
- /**
278
- * 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.
279
- *
280
- * Users can prevent this by creating their own HandlerOnRequestPlugin and returning false as the result of the callable.
281
- */
282
- if (!isOptionsRequest) {
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);
283
229
  return;
284
230
  }
285
- if (reply.sent) {
286
- /**
287
- * At this point throwing an exception will not do anything with the response. So just log it.
288
- */
289
- console.error(JSON.stringify({
290
- message: `Output was already sent. Please check custom plugins of type "HandlerOnRequestPlugin".`,
291
- explanation: "This error can happen if the user plugin ended the reply, but did not return false as response."
292
- }));
293
- return;
294
- }
295
- reply.code(204).send("").hijack();
296
- });
297
- app.addHook("preParsing", async (request, reply) => {
298
- app.webiny.request = request;
299
- app.webiny.reply = reply;
300
- const plugins = app.webiny.plugins.byType(_api.ContextPlugin.type);
301
- let name;
302
231
  try {
303
- for (const plugin of plugins) {
304
- name = plugin.name;
305
- await plugin.apply(app.webiny);
306
- }
307
- } catch (ex) {
308
- console.error(`Error while running the "ContextPlugin" ${name ? `(${name})` : ""} plugin in the preParsing hook.`);
309
- console.error(stringifyError(ex));
310
- throw ex;
232
+ const json = typeof body === "string" ? body : body.toString("utf8");
233
+ done(null, JSON.parse(json));
234
+ } catch (err) {
235
+ done(err);
311
236
  }
312
237
  });
238
+
313
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.
314
242
  *
243
+ * @see https://fastify.dev/docs/latest/Reference/ContentTypeParser/#content-type-parser
315
244
  */
316
- app.addHook("preHandler", async () => {
317
- const plugins = app.webiny.plugins.byType(_BeforeHandlerPlugin.BeforeHandlerPlugin.type);
318
- let name;
319
- try {
320
- for (const plugin of plugins) {
321
- name = plugin.name;
322
- await plugin.apply(app.webiny);
323
- }
324
- } catch (ex) {
325
- console.error(`Error while running the "BeforeHandlerPlugin" ${name ? `(${name})` : ""} plugin in the preHandler hook.`);
326
- console.error(stringifyError(ex));
327
- throw ex;
245
+ app.addHook("onRequest", async request => {
246
+ if (request.method === "OPTIONS" && request.body === undefined) {
247
+ request.headers["content-type"] = undefined;
328
248
  }
329
249
  });
330
250
 
331
251
  /**
332
- *
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`
333
258
  */
334
- const preSerialization = async (_, __, payload) => {
335
- const plugins = app.webiny.plugins.byType(_HandlerResultPlugin.HandlerResultPlugin.type);
259
+ app.addHook("preHandler", async (request, reply) => {
260
+ app.webiny.request = request;
261
+ app.webiny.reply = reply;
262
+
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);
336
282
  let name;
337
283
  try {
338
284
  for (const plugin of plugins) {
@@ -345,9 +291,31 @@ const createHandler = params => {
345
291
  throw ex;
346
292
  }
347
293
  return payload;
348
- };
349
- app.addHook("preSerialization", preSerialization);
350
- app.setErrorHandler(async (error, request, reply) => {
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
+ }
351
319
  return reply.status(500).headers({
352
320
  "Cache-Control": "no-store"
353
321
  }).send(
@@ -361,24 +329,37 @@ const createHandler = params => {
361
329
  }));
362
330
  });
363
331
  app.addHook("onError", async (_, reply, error) => {
364
- const plugins = app.webiny.plugins.byType(_HandlerErrorPlugin.HandlerErrorPlugin.type);
332
+ const plugins = app.webiny.plugins.byType(HandlerErrorPlugin.type);
365
333
  /**
366
334
  * Log error to cloud, as these can be extremely annoying to debug!
367
335
  */
368
- console.error("@webiny/handler");
369
- console.error(stringifyError(error));
370
- reply.status(500).headers({
371
- "Cache-Control": "no-store"
372
- }).send(
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
+ }
373
344
  /**
374
- * When we are sending the error in the response, we cannot send the whole error object, as it might contain some sensitive data.
345
+ * IMPORTANT! Do not send anything if reply was already sent.
375
346
  */
376
- JSON.stringify({
377
- message: error.message,
378
- code: error.code,
379
- data: error.data
380
- }));
381
- const handler = (0, _middleware.middleware)(plugins.map(pl => {
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 => {
382
363
  return (context, error, next) => {
383
364
  return pl.handle(context, error, next);
384
365
  };
@@ -390,13 +371,13 @@ const createHandler = params => {
390
371
  /**
391
372
  * Apply response headers modifier plugins.
392
373
  */
393
- app.addHook("onSend", async (request, reply, payload) => {
394
- const modifyHeaders = app.webiny.plugins.byType(_ModifyResponseHeadersPlugin.ModifyResponseHeadersPlugin.type);
395
- const headers = _ResponseHeaders.ResponseHeaders.create(reply.getHeaders());
396
- modifyHeaders.forEach(plugin => {
397
- plugin.modify(request, headers);
398
- });
399
- reply.headers(headers.getHeaders());
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
+ }
400
381
  return payload;
401
382
  });
402
383
 
@@ -406,14 +387,18 @@ const createHandler = params => {
406
387
  app.addHook("onResponse", async () => {
407
388
  await context.benchmark.output();
408
389
  });
409
- app.addHook("onTimeout", async () => {
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
+ }
410
395
  await context.benchmark.output();
411
396
  });
412
397
 
413
398
  /**
414
399
  * With these plugins we give users possibility to do anything they want on our fastify instance.
415
400
  */
416
- const modifyPlugins = app.webiny.plugins.byType(_ModifyFastifyPlugin.ModifyFastifyPlugin.type);
401
+ const modifyPlugins = app.webiny.plugins.byType(ModifyFastifyPlugin.type);
417
402
  let modifyFastifyPluginName;
418
403
  try {
419
404
  for (const plugin of modifyPlugins) {
@@ -433,7 +418,7 @@ const createHandler = params => {
433
418
  *
434
419
  * Routes are registered in fastify but events must be handled in package which implements cloud specific methods.
435
420
  */
436
- const routePlugins = app.webiny.plugins.byType(_RoutePlugin.RoutePlugin.type);
421
+ const routePlugins = app.webiny.plugins.byType(RoutePlugin.type);
437
422
 
438
423
  /**
439
424
  * Add routes to the system.
@@ -454,6 +439,5 @@ const createHandler = params => {
454
439
  }
455
440
  return app;
456
441
  };
457
- exports.createHandler = createHandler;
458
442
 
459
443
  //# sourceMappingURL=fastify.js.map