@webiny/handler 0.0.0-unstable.df6d94b531 → 0.0.0-unstable.e0bfc55d5a

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 (82) hide show
  1. package/Context.d.ts +18 -10
  2. package/Context.js +20 -17
  3. package/Context.js.map +1 -1
  4. package/PreHandler/IPreHandler.d.ts +9 -0
  5. package/PreHandler/IPreHandler.js +13 -0
  6. package/PreHandler/IPreHandler.js.map +1 -0
  7. package/PreHandler/IfNotOptionsRequest.d.ts +9 -0
  8. package/PreHandler/IfNotOptionsRequest.js +28 -0
  9. package/PreHandler/IfNotOptionsRequest.js.map +1 -0
  10. package/PreHandler/IfOptionsRequest.d.ts +9 -0
  11. package/PreHandler/IfOptionsRequest.js +28 -0
  12. package/PreHandler/IfOptionsRequest.js.map +1 -0
  13. package/PreHandler/PreHandler.d.ts +9 -0
  14. package/PreHandler/PreHandler.js +24 -0
  15. package/PreHandler/PreHandler.js.map +1 -0
  16. package/PreHandler/ProcessBeforeHandlerPlugins.d.ts +10 -0
  17. package/PreHandler/ProcessBeforeHandlerPlugins.js +31 -0
  18. package/PreHandler/ProcessBeforeHandlerPlugins.js.map +1 -0
  19. package/PreHandler/ProcessContextPlugins.d.ts +10 -0
  20. package/PreHandler/ProcessContextPlugins.js +31 -0
  21. package/PreHandler/ProcessContextPlugins.js.map +1 -0
  22. package/PreHandler/ProcessHandlerOnRequestPlugins.d.ts +10 -0
  23. package/PreHandler/ProcessHandlerOnRequestPlugins.js +33 -0
  24. package/PreHandler/ProcessHandlerOnRequestPlugins.js.map +1 -0
  25. package/PreHandler/SendEarlyOptionsResponse.d.ts +9 -0
  26. package/PreHandler/SendEarlyOptionsResponse.js +38 -0
  27. package/PreHandler/SendEarlyOptionsResponse.js.map +1 -0
  28. package/PreHandler/SetDefaultHeaders.d.ts +9 -0
  29. package/PreHandler/SetDefaultHeaders.js +64 -0
  30. package/PreHandler/SetDefaultHeaders.js.map +1 -0
  31. package/ResponseHeaders.d.ts +25 -0
  32. package/ResponseHeaders.js +46 -0
  33. package/ResponseHeaders.js.map +1 -0
  34. package/fastify.d.ts +6 -4
  35. package/fastify.js +168 -250
  36. package/fastify.js.map +1 -1
  37. package/index.d.ts +6 -1
  38. package/index.js +48 -32
  39. package/index.js.map +1 -1
  40. package/package.json +15 -24
  41. package/plugins/BeforeHandlerPlugin.d.ts +1 -1
  42. package/plugins/BeforeHandlerPlugin.js +3 -14
  43. package/plugins/BeforeHandlerPlugin.js.map +1 -1
  44. package/plugins/EventPlugin.d.ts +1 -1
  45. package/plugins/EventPlugin.js +4 -12
  46. package/plugins/EventPlugin.js.map +1 -1
  47. package/plugins/HandlerErrorPlugin.d.ts +6 -3
  48. package/plugins/HandlerErrorPlugin.js +3 -13
  49. package/plugins/HandlerErrorPlugin.js.map +1 -1
  50. package/plugins/HandlerOnRequestPlugin.d.ts +9 -8
  51. package/plugins/HandlerOnRequestPlugin.js +11 -14
  52. package/plugins/HandlerOnRequestPlugin.js.map +1 -1
  53. package/plugins/HandlerResultPlugin.d.ts +1 -1
  54. package/plugins/HandlerResultPlugin.js +3 -13
  55. package/plugins/HandlerResultPlugin.js.map +1 -1
  56. package/plugins/ModifyFastifyPlugin.d.ts +1 -1
  57. package/plugins/ModifyFastifyPlugin.js +3 -13
  58. package/plugins/ModifyFastifyPlugin.js.map +1 -1
  59. package/plugins/ModifyResponseHeadersPlugin.d.ts +14 -0
  60. package/plugins/ModifyResponseHeadersPlugin.js +24 -0
  61. package/plugins/ModifyResponseHeadersPlugin.js.map +1 -0
  62. package/plugins/OnRequestResponseSendPlugin.d.ts +26 -0
  63. package/plugins/OnRequestResponseSendPlugin.js +40 -0
  64. package/plugins/OnRequestResponseSendPlugin.js.map +1 -0
  65. package/plugins/OnRequestTimeoutPlugin.d.ts +12 -0
  66. package/plugins/OnRequestTimeoutPlugin.js +24 -0
  67. package/plugins/OnRequestTimeoutPlugin.js.map +1 -0
  68. package/plugins/RoutePlugin.d.ts +1 -1
  69. package/plugins/RoutePlugin.js +3 -12
  70. package/plugins/RoutePlugin.js.map +1 -1
  71. package/stringifyError.d.ts +5 -0
  72. package/stringifyError.js +27 -0
  73. package/stringifyError.js.map +1 -0
  74. package/suppressPunycodeWarnings.d.ts +4 -0
  75. package/suppressPunycodeWarnings.js +11 -0
  76. package/suppressPunycodeWarnings.js.map +1 -0
  77. package/types.d.ts +10 -13
  78. package/types.js +3 -7
  79. package/types.js.map +1 -1
  80. package/middleware.d.ts +0 -4
  81. package/middleware.js +0 -51
  82. package/middleware.js.map +0 -1
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.ResponseHeaders = void 0;
7
+ // Extract known standard headers, and remove all non-string keys.
8
+
9
+ function isFunction(setter) {
10
+ return typeof setter === "function";
11
+ }
12
+ class ResponseHeaders {
13
+ headers = new Map();
14
+ constructor(initialHeaders) {
15
+ if (initialHeaders) {
16
+ Object.keys(initialHeaders).forEach(key => {
17
+ this.headers.set(key, initialHeaders[key]);
18
+ });
19
+ }
20
+ }
21
+ set(header, setter) {
22
+ if (isFunction(setter)) {
23
+ const previousValue = this.headers.get(header);
24
+ const newValue = setter(previousValue);
25
+ this.headers.set(header, newValue);
26
+ return this;
27
+ }
28
+ this.headers.set(header, setter);
29
+ return this;
30
+ }
31
+ merge(headers) {
32
+ return ResponseHeaders.create({
33
+ ...this.getHeaders(),
34
+ ...headers.getHeaders()
35
+ });
36
+ }
37
+ getHeaders() {
38
+ return Object.fromEntries(this.headers);
39
+ }
40
+ static create(initialHeaders) {
41
+ return new ResponseHeaders(initialHeaders);
42
+ }
43
+ }
44
+ exports.ResponseHeaders = ResponseHeaders;
45
+
46
+ //# sourceMappingURL=ResponseHeaders.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["isFunction","setter","ResponseHeaders","headers","Map","constructor","initialHeaders","Object","keys","forEach","key","set","header","previousValue","get","newValue","merge","create","getHeaders","fromEntries","exports"],"sources":["ResponseHeaders.ts"],"sourcesContent":["import type * as http from \"http\";\n\ntype ExtraHeaders = {\n \"content-type\"?: string | undefined;\n \"x-webiny-version\"?: http.OutgoingHttpHeader | undefined;\n};\n\ntype AllHeaders = http.OutgoingHttpHeaders & ExtraHeaders;\n\nexport type StandardHeaderValue = http.OutgoingHttpHeader | undefined;\n\n// Extract known standard headers, and remove all non-string keys.\nexport type StandardHeaders = {\n [K in keyof AllHeaders as string extends K\n ? never\n : number extends K\n ? never\n : K]: http.OutgoingHttpHeaders[K];\n} & {\n [name: string]: StandardHeaderValue;\n};\n\nfunction isFunction<T>(setter: unknown): setter is (value: T) => T {\n return typeof setter === \"function\";\n}\n\ntype Setter<T> = ((value: T) => T) | T;\n\nexport class ResponseHeaders {\n private readonly headers = new Map<keyof StandardHeaders, StandardHeaderValue>();\n\n private constructor(initialHeaders?: StandardHeaders) {\n if (initialHeaders) {\n (Object.keys(initialHeaders) as Array<keyof StandardHeaders>).forEach(key => {\n this.headers.set(key, initialHeaders[key]);\n });\n }\n }\n\n set<T extends keyof StandardHeaders>(header: T, setter: Setter<StandardHeaders[T]>) {\n if (isFunction<StandardHeaders[T]>(setter)) {\n const previousValue = this.headers.get(header) as StandardHeaders[T];\n const newValue = setter(previousValue);\n this.headers.set(header, newValue);\n return this;\n }\n\n this.headers.set(header, setter);\n\n return this;\n }\n\n merge(headers: ResponseHeaders) {\n return ResponseHeaders.create({ ...this.getHeaders(), ...headers.getHeaders() });\n }\n\n getHeaders() {\n return Object.fromEntries(this.headers);\n }\n\n static create(initialHeaders?: StandardHeaders) {\n return new ResponseHeaders(initialHeaders);\n }\n}\n"],"mappings":";;;;;;AAWA;;AAWA,SAASA,UAAUA,CAAIC,MAAe,EAA6B;EAC/D,OAAO,OAAOA,MAAM,KAAK,UAAU;AACvC;AAIO,MAAMC,eAAe,CAAC;EACRC,OAAO,GAAG,IAAIC,GAAG,CAA6C,CAAC;EAExEC,WAAWA,CAACC,cAAgC,EAAE;IAClD,IAAIA,cAAc,EAAE;MACfC,MAAM,CAACC,IAAI,CAACF,cAAc,CAAC,CAAkCG,OAAO,CAACC,GAAG,IAAI;QACzE,IAAI,CAACP,OAAO,CAACQ,GAAG,CAACD,GAAG,EAAEJ,cAAc,CAACI,GAAG,CAAC,CAAC;MAC9C,CAAC,CAAC;IACN;EACJ;EAEAC,GAAGA,CAAkCC,MAAS,EAAEX,MAAkC,EAAE;IAChF,IAAID,UAAU,CAAqBC,MAAM,CAAC,EAAE;MACxC,MAAMY,aAAa,GAAG,IAAI,CAACV,OAAO,CAACW,GAAG,CAACF,MAAM,CAAuB;MACpE,MAAMG,QAAQ,GAAGd,MAAM,CAACY,aAAa,CAAC;MACtC,IAAI,CAACV,OAAO,CAACQ,GAAG,CAACC,MAAM,EAAEG,QAAQ,CAAC;MAClC,OAAO,IAAI;IACf;IAEA,IAAI,CAACZ,OAAO,CAACQ,GAAG,CAACC,MAAM,EAAEX,MAAM,CAAC;IAEhC,OAAO,IAAI;EACf;EAEAe,KAAKA,CAACb,OAAwB,EAAE;IAC5B,OAAOD,eAAe,CAACe,MAAM,CAAC;MAAE,GAAG,IAAI,CAACC,UAAU,CAAC,CAAC;MAAE,GAAGf,OAAO,CAACe,UAAU,CAAC;IAAE,CAAC,CAAC;EACpF;EAEAA,UAAUA,CAAA,EAAG;IACT,OAAOX,MAAM,CAACY,WAAW,CAAC,IAAI,CAAChB,OAAO,CAAC;EAC3C;EAEA,OAAOc,MAAMA,CAACX,cAAgC,EAAE;IAC5C,OAAO,IAAIJ,eAAe,CAACI,cAAc,CAAC;EAC9C;AACJ;AAACc,OAAA,CAAAlB,eAAA,GAAAA,eAAA","ignoreList":[]}
package/fastify.d.ts CHANGED
@@ -1,8 +1,10 @@
1
1
  /// <reference types="node" />
2
- import { PluginCollection } from "@webiny/plugins/types";
3
- import { FastifyServerOptions as ServerOptions } from "fastify";
2
+ import type { PluginCollection } from "@webiny/plugins/types";
3
+ import { PluginsContainer } from "@webiny/plugins/types";
4
+ import type { FastifyInstance, FastifyServerOptions as ServerOptions } from "fastify";
4
5
  export interface CreateHandlerParams {
5
- plugins: PluginCollection;
6
+ plugins: PluginCollection | PluginsContainer;
6
7
  options?: ServerOptions;
8
+ debug?: boolean;
7
9
  }
8
- 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>>;
10
+ 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>>;
package/fastify.js CHANGED
@@ -1,101 +1,47 @@
1
1
  "use strict";
2
2
 
3
3
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
-
5
4
  Object.defineProperty(exports, "__esModule", {
6
5
  value: true
7
6
  });
8
7
  exports.createHandler = void 0;
9
-
10
- var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
11
-
8
+ var _types = require("@webiny/plugins/types");
12
9
  var _fastify = _interopRequireDefault(require("fastify"));
13
-
14
10
  var _utils = require("@webiny/utils");
15
-
16
11
  var _Context = require("./Context");
17
-
18
12
  var _error = _interopRequireDefault(require("@webiny/error"));
19
-
20
13
  var _RoutePlugin = require("./plugins/RoutePlugin");
21
-
22
14
  var _handlerClient = require("@webiny/handler-client");
23
-
24
15
  var _cookie = _interopRequireDefault(require("@fastify/cookie"));
25
-
26
16
  var _compress = _interopRequireDefault(require("@fastify/compress"));
27
-
28
- var _middleware = require("./middleware");
29
-
30
17
  var _api = require("@webiny/api");
31
-
32
18
  var _BeforeHandlerPlugin = require("./plugins/BeforeHandlerPlugin");
33
-
34
19
  var _HandlerResultPlugin = require("./plugins/HandlerResultPlugin");
35
-
36
20
  var _HandlerErrorPlugin = require("./plugins/HandlerErrorPlugin");
37
-
38
21
  var _ModifyFastifyPlugin = require("./plugins/ModifyFastifyPlugin");
39
-
40
22
  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(",")
23
+ var _ResponseHeaders = require("./ResponseHeaders");
24
+ var _ModifyResponseHeadersPlugin = require("./plugins/ModifyResponseHeadersPlugin");
25
+ var _SetDefaultHeaders = require("./PreHandler/SetDefaultHeaders");
26
+ var _PreHandler = require("./PreHandler/PreHandler");
27
+ var _stringifyError = require("./stringifyError");
28
+ var _ProcessHandlerOnRequestPlugins = require("./PreHandler/ProcessHandlerOnRequestPlugins");
29
+ var _ProcessContextPlugins = require("./PreHandler/ProcessContextPlugins");
30
+ var _IfNotOptionsRequest = require("./PreHandler/IfNotOptionsRequest");
31
+ var _ProcessBeforeHandlerPlugins = require("./PreHandler/ProcessBeforeHandlerPlugins");
32
+ var _IfOptionsRequest = require("./PreHandler/IfOptionsRequest");
33
+ var _SendEarlyOptionsResponse = require("./PreHandler/SendEarlyOptionsResponse");
34
+ var _OnRequestTimeoutPlugin = require("./plugins/OnRequestTimeoutPlugin.js");
35
+ var _OnRequestResponseSendPlugin = require("./plugins/OnRequestResponseSendPlugin.js");
36
+ const modifyResponseHeaders = (app, request, reply) => {
37
+ const modifyHeaders = app.webiny.plugins.byType(_ModifyResponseHeadersPlugin.ModifyResponseHeadersPlugin.type);
38
+ const replyHeaders = reply.getHeaders();
39
+ const headers = _ResponseHeaders.ResponseHeaders.create(replyHeaders);
40
+ modifyHeaders.forEach(plugin => {
41
+ plugin.modify(request, headers);
71
42
  });
43
+ reply.headers(headers.getHeaders());
72
44
  };
73
-
74
- const stringifyError = error => {
75
- var _error$constructor;
76
-
77
- const {
78
- name,
79
- message,
80
- code,
81
- stack,
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
- }));
92
- };
93
-
94
- const OPTIONS_HEADERS = {
95
- "Access-Control-Max-Age": "86400",
96
- "Cache-Control": "public, max-age=86400"
97
- };
98
-
99
45
  const createHandler = params => {
100
46
  const definedRoutes = {
101
47
  POST: [],
@@ -113,20 +59,20 @@ 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(key => {
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
76
  console.error(`Error while registering onAll route. One of the routes is already defined.`);
131
77
  console.error(JSON.stringify(all));
132
78
  throw new _error.default(`You cannot override a route with onAll() method, please remove unnecessary route from the system.`, "OVERRIDE_ROUTE_ERROR", {
@@ -135,70 +81,65 @@ const createHandler = params => {
135
81
  });
136
82
  } else if (definedRoutes[type].includes(path) === false) {
137
83
  return;
138
- } else if ((options === null || options === void 0 ? void 0 : options.override) === true) {
84
+ } else if (options?.override === true) {
139
85
  return;
140
86
  }
141
-
142
87
  console.error(`Error while trying to override route: [${type}] ${path}`);
143
88
  throw new _error.default(`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
- const addDefinedRoute = (type, path) => {
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 = (0, _fastify.default)({
107
+ bodyLimit: 536870912,
108
+ // 512MB
109
+ disableRequestLogging: true,
110
+ ...(params.options || {})
111
+ });
161
112
 
162
-
163
- const app = (0, _fastify.default)((0, _objectSpread2.default)({}, params.options || {}));
164
113
  /**
165
- * We need to register routes in our system so we can output headers later on and dissallow overriding routes.
114
+ * We need to register routes in our system to output headers later on, and disallow route overriding.
166
115
  */
167
-
168
116
  app.addHook("onRoute", route => {
169
117
  const method = route.method;
170
-
171
118
  if (Array.isArray(method)) {
172
119
  for (const m of method) {
173
120
  addDefinedRoute(m, route.path);
174
121
  }
175
-
176
122
  return;
177
123
  }
178
-
179
124
  addDefinedRoute(method, route.path);
180
125
  });
181
126
  /**
182
127
  * ############################
183
128
  * Register the Fastify plugins.
184
129
  */
185
-
186
130
  /**
187
131
  * Package @fastify/cookie
188
132
  *
189
133
  * https://github.com/fastify/fastify-cookie
190
134
  */
191
-
192
135
  app.register(_cookie.default, {
193
136
  parseOptions: {} // options for parsing cookies
194
-
195
137
  });
196
138
  /**
197
139
  * Package @fastify/compress
198
140
  *
199
141
  * https://github.com/fastify/fastify-compress
200
142
  */
201
-
202
143
  app.register(_compress.default, {
203
144
  global: true,
204
145
  threshold: 1024,
@@ -211,7 +152,6 @@ const createHandler = params => {
211
152
  /**
212
153
  * Route helpers - mostly for users.
213
154
  */
214
-
215
155
  const routes = {
216
156
  defined: definedRoutes,
217
157
  onPost: (path, handler, options) => {
@@ -248,162 +188,71 @@ const createHandler = params => {
248
188
  }
249
189
  };
250
190
  let context;
251
-
191
+ const plugins = new _types.PluginsContainer([
192
+ /**
193
+ * We must have handlerClient by default.
194
+ * And it must be one of the first context plugins applied.
195
+ */
196
+ (0, _handlerClient.createHandlerClient)()]);
197
+ plugins.merge(params.plugins || []);
252
198
  try {
253
199
  context = new _Context.Context({
254
- plugins: [
200
+ plugins,
255
201
  /**
256
- * We must have handlerClient by default.
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.
202
+ * Inserted via webpack at build time.
263
203
  */
264
204
  WEBINY_VERSION: process.env.WEBINY_VERSION,
265
- server: app,
266
205
  routes
267
206
  });
268
207
  } catch (ex) {
269
208
  console.error(`Error while constructing the Context.`);
270
- console.error(stringifyError(ex));
209
+ console.error((0, _stringifyError.stringifyError)(ex));
271
210
  throw ex;
272
211
  }
212
+
273
213
  /**
274
214
  * We are attaching our custom context to webiny variable on the fastify app, so it is accessible everywhere.
275
215
  */
276
-
277
-
278
216
  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
-
287
- const routePlugins = app.webiny.plugins.byType(_RoutePlugin.RoutePlugin.type);
288
- /**
289
- * Add routes to the system.
290
- */
291
217
 
292
- let routePluginName;
293
-
294
- try {
295
- for (const plugin of routePlugins) {
296
- routePluginName = plugin.name;
297
- plugin.cb((0, _objectSpread2.default)((0, _objectSpread2.default)({}, app.webiny.routes), {}, {
298
- context: app.webiny
299
- }));
300
- }
301
- } catch (ex) {
302
- console.error(`Error while running the "RoutePlugin" ${routePluginName ? `(${routePluginName})` : ""} plugin in the beginning of the "createHandler" callable.`);
303
- console.error(stringifyError(ex));
304
- throw ex;
305
- }
306
218
  /**
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.
219
+ * With this we ensure that an undefined request body is not parsed on OPTIONS requests,
220
+ * in case there's a `content-type` header set for whatever reason.
221
+ *
222
+ * @see https://fastify.dev/docs/latest/Reference/ContentTypeParser/#content-type-parser
309
223
  */
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.error(`Error while running the "HandlerOnRequestPlugin" ${name ? `(${name})` : ""} plugin in the onRequest hook.`);
336
- console.error(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") {
347
- return;
224
+ app.addHook("onRequest", async request => {
225
+ if (request.method === "OPTIONS" && request.body === undefined) {
226
+ request.headers["content-type"] = undefined;
348
227
  }
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.error(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
228
  });
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
229
 
369
- try {
370
- for (const plugin of plugins) {
371
- name = plugin.name;
372
- await plugin.apply(app.webiny);
373
- }
374
- } catch (ex) {
375
- console.error(`Error while running the "ContextPlugin" ${name ? `(${name})` : ""} plugin in the preParsing hook.`);
376
- console.error(stringifyError(ex));
377
- throw ex;
378
- }
379
- });
380
230
  /**
381
- *
231
+ * At this point, request body is properly parsed, and we can execute Webiny business logic.
232
+ * - set default headers
233
+ * - process `HandlerOnRequestPlugin`
234
+ * - if OPTIONS request, exit early
235
+ * - process `ContextPlugin`
236
+ * - process `BeforeHandlerPlugin`
382
237
  */
383
-
384
- app.addHook("preHandler", async () => {
385
- const plugins = app.webiny.plugins.byType(_BeforeHandlerPlugin.BeforeHandlerPlugin.type);
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.error(`Error while running the "BeforeHandlerPlugin" ${name ? `(${name})` : ""} plugin in the preHandler hook.`);
395
- console.error(stringifyError(ex));
396
- throw ex;
397
- }
238
+ app.addHook("preHandler", async (request, reply) => {
239
+ app.webiny.request = request;
240
+ app.webiny.reply = reply;
241
+ /**
242
+ * Default code to 200 - so we do not need to set it again.
243
+ * Usually we set errors manually when we use reply.send.
244
+ */
245
+ reply.code(200);
246
+ const handlerOnRequestPlugins = app.webiny.plugins.byType(_HandlerOnRequestPlugin.HandlerOnRequestPlugin.type);
247
+ const contextPlugins = app.webiny.plugins.byType(_api.ContextPlugin.type);
248
+ const beforeHandlerPlugins = app.webiny.plugins.byType(_BeforeHandlerPlugin.BeforeHandlerPlugin.type);
249
+ const modifyHeadersPlugins = app.webiny.plugins.byType(_ModifyResponseHeadersPlugin.ModifyResponseHeadersPlugin.type);
250
+ const preHandler = new _PreHandler.PreHandler([new _SetDefaultHeaders.SetDefaultHeaders(definedRoutes), new _ProcessHandlerOnRequestPlugins.ProcessHandlerOnRequestPlugins(handlerOnRequestPlugins), new _IfNotOptionsRequest.IfNotOptionsRequest([new _ProcessContextPlugins.ProcessContextPlugins(app.webiny, contextPlugins), new _ProcessBeforeHandlerPlugins.ProcessBeforeHandlerPlugins(app.webiny, beforeHandlerPlugins)]), new _IfOptionsRequest.IfOptionsRequest([new _SendEarlyOptionsResponse.SendEarlyOptionsResponse(modifyHeadersPlugins)])]);
251
+ await preHandler.execute(request, reply, app.webiny);
398
252
  });
399
- /**
400
- *
401
- */
402
-
403
- const preSerialization = async (_, __, payload) => {
253
+ app.addHook("preSerialization", async (_, __, payload) => {
404
254
  const plugins = app.webiny.plugins.byType(_HandlerResultPlugin.HandlerResultPlugin.type);
405
255
  let name;
406
-
407
256
  try {
408
257
  for (const plugin of plugins) {
409
258
  name = plugin.name;
@@ -411,15 +260,19 @@ const createHandler = params => {
411
260
  }
412
261
  } catch (ex) {
413
262
  console.error(`Error while running the "HandlerResultPlugin" ${name ? `(${name})` : ""} plugin in the preSerialization hook.`);
414
- console.error(stringifyError(ex));
263
+ console.error((0, _stringifyError.stringifyError)(ex));
415
264
  throw ex;
416
265
  }
417
-
418
266
  return payload;
419
- };
420
-
421
- app.addHook("preSerialization", preSerialization);
422
- app.setErrorHandler(async (error, request, reply) => {
267
+ });
268
+ app.setErrorHandler(async (error, _, reply) => {
269
+ /**
270
+ * IMPORTANT! Do not send anything if reply was already sent.
271
+ */
272
+ if (reply.sent) {
273
+ console.warn("Reply already sent, cannot send the result (handler:setErrorHandler).");
274
+ return reply;
275
+ }
423
276
  return reply.status(500).headers({
424
277
  "Cache-Control": "no-store"
425
278
  }).send(
@@ -437,21 +290,33 @@ const createHandler = params => {
437
290
  /**
438
291
  * Log error to cloud, as these can be extremely annoying to debug!
439
292
  */
440
-
441
- console.error("@webiny/handler");
442
- console.error(stringifyError(error));
443
- reply.status(500).headers({
444
- "Cache-Control": "no-store"
445
- }).send(
293
+ console.error("Logging error in @webiny/handler");
294
+ try {
295
+ console.error((0, _stringifyError.stringifyError)(error));
296
+ } catch (ex) {
297
+ console.warn("Could not stringify error:");
298
+ console.log(error);
299
+ console.error("Stringify error:", ex);
300
+ }
446
301
  /**
447
- * When we are sending the error in the response, we cannot send the whole error object, as it might contain some sensitive data.
302
+ * IMPORTANT! Do not send anything if reply was already sent.
448
303
  */
449
- JSON.stringify({
450
- message: error.message,
451
- code: error.code,
452
- data: error.data
453
- }));
454
- const handler = (0, _middleware.middleware)(plugins.map(pl => {
304
+ if (!reply.sent) {
305
+ reply.status(500).headers({
306
+ "Cache-Control": "no-store"
307
+ }).send(
308
+ /**
309
+ * When we are sending the error in the response, we cannot send the whole error object, as it might contain some sensitive data.
310
+ */
311
+ JSON.stringify({
312
+ message: error.message,
313
+ code: error.code,
314
+ data: error.data
315
+ }));
316
+ } else {
317
+ console.warn("Reply already sent, cannot send the result (handler:addHook:onError).");
318
+ }
319
+ const handler = (0, _utils.middleware)(plugins.map(pl => {
455
320
  return (context, error, next) => {
456
321
  return pl.handle(context, error, next);
457
322
  };
@@ -459,13 +324,39 @@ const createHandler = params => {
459
324
  await handler(app.webiny, error);
460
325
  return reply;
461
326
  });
327
+
462
328
  /**
463
- * With these plugins we give users possibility to do anything they want on our fastify instance.
329
+ * Apply response headers modifier plugins.
464
330
  */
331
+ app.addHook("onSend", async (request, reply, input) => {
332
+ modifyResponseHeaders(app, request, reply);
333
+ const plugins = app.webiny.plugins.byType(_OnRequestResponseSendPlugin.OnRequestResponseSendPlugin.type);
334
+ let payload = input;
335
+ for (const plugin of plugins) {
336
+ payload = await plugin.exec(request, reply, payload);
337
+ }
338
+ return payload;
339
+ });
465
340
 
341
+ /**
342
+ * We need to output the benchmark results at the end of the request in both response and timeout cases
343
+ */
344
+ app.addHook("onResponse", async () => {
345
+ await context.benchmark.output();
346
+ });
347
+ app.addHook("onTimeout", async (request, reply) => {
348
+ const plugins = app.webiny.plugins.byType(_OnRequestTimeoutPlugin.OnRequestTimeoutPlugin.type);
349
+ for (const plugin of plugins) {
350
+ await plugin.exec(request, reply);
351
+ }
352
+ await context.benchmark.output();
353
+ });
354
+
355
+ /**
356
+ * With these plugins we give users possibility to do anything they want on our fastify instance.
357
+ */
466
358
  const modifyPlugins = app.webiny.plugins.byType(_ModifyFastifyPlugin.ModifyFastifyPlugin.type);
467
359
  let modifyFastifyPluginName;
468
-
469
360
  try {
470
361
  for (const plugin of modifyPlugins) {
471
362
  modifyFastifyPluginName = plugin.name;
@@ -473,11 +364,38 @@ const createHandler = params => {
473
364
  }
474
365
  } catch (ex) {
475
366
  console.error(`Error while running the "ModifyFastifyPlugin" ${modifyFastifyPluginName ? `(${modifyFastifyPluginName})` : ""} plugin in the end of the "createHandler" callable.`);
476
- console.error(stringifyError(ex));
367
+ console.error((0, _stringifyError.stringifyError)(ex));
477
368
  throw ex;
478
369
  }
479
370
 
371
+ /**
372
+ * We have few types of triggers:
373
+ * * Events - EventPlugin
374
+ * * Routes - RoutePlugin
375
+ *
376
+ * Routes are registered in fastify but events must be handled in package which implements cloud specific methods.
377
+ */
378
+ const routePlugins = app.webiny.plugins.byType(_RoutePlugin.RoutePlugin.type);
379
+
380
+ /**
381
+ * Add routes to the system.
382
+ */
383
+ let routePluginName;
384
+ try {
385
+ for (const plugin of routePlugins) {
386
+ routePluginName = plugin.name;
387
+ plugin.cb({
388
+ ...app.webiny.routes,
389
+ context: app.webiny
390
+ });
391
+ }
392
+ } catch (ex) {
393
+ console.error(`Error while running the "RoutePlugin" ${routePluginName ? `(${routePluginName})` : ""} plugin in the beginning of the "createHandler" callable.`);
394
+ console.error((0, _stringifyError.stringifyError)(ex));
395
+ throw ex;
396
+ }
480
397
  return app;
481
398
  };
399
+ exports.createHandler = createHandler;
482
400
 
483
- exports.createHandler = createHandler;
401
+ //# sourceMappingURL=fastify.js.map