@webiny/handler 0.0.0-unstable.fcdad0bc61 → 0.0.0-unstable.fdd9228b5d

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 -9
  2. package/Context.js +20 -15
  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 +244 -162
  36. package/fastify.js.map +1 -1
  37. package/index.d.ts +8 -1
  38. package/index.js +67 -25
  39. package/index.js.map +1 -1
  40. package/package.json +15 -23
  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 +21 -0
  51. package/plugins/HandlerOnRequestPlugin.js +31 -0
  52. package/plugins/HandlerOnRequestPlugin.js.map +1 -0
  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 +13 -0
  57. package/plugins/ModifyFastifyPlugin.js +24 -0
  58. package/plugins/ModifyFastifyPlugin.js.map +1 -0
  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 +14 -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,77 +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
- var _middleware = require("./middleware");
27
-
16
+ var _compress = _interopRequireDefault(require("@fastify/compress"));
28
17
  var _api = require("@webiny/api");
29
-
30
18
  var _BeforeHandlerPlugin = require("./plugins/BeforeHandlerPlugin");
31
-
32
19
  var _HandlerResultPlugin = require("./plugins/HandlerResultPlugin");
33
-
34
20
  var _HandlerErrorPlugin = require("./plugins/HandlerErrorPlugin");
35
-
36
- const DEFAULT_HEADERS = (0, _objectSpread2.default)({
37
- "Cache-Control": "no-store",
38
- "Content-Type": "application/json; charset=utf-8",
39
- "Access-Control-Allow-Origin": "*",
40
- "Access-Control-Allow-Headers": "*",
41
- "Access-Control-Allow-Methods": "OPTIONS,POST,GET,DELETE,PUT,PATCH"
42
- }, (0, _utils.getWebinyVersionHeaders)());
43
-
44
- const getDefaultHeaders = routes => {
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
-
51
- if (all) {
52
- return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, DEFAULT_HEADERS), {}, {
53
- "Access-Control-Allow-Methods": "*"
54
- });
55
- }
56
-
57
- return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, DEFAULT_HEADERS), {}, {
58
- "Access-Control-Allow-Methods": keys.filter(key => {
59
- const type = key;
60
-
61
- if (!routes[type] || Array.isArray(routes[type]) === false) {
62
- return false;
63
- }
64
-
65
- return routes[type].length > 0;
66
- }).sort().join(",")
21
+ var _ModifyFastifyPlugin = require("./plugins/ModifyFastifyPlugin");
22
+ var _HandlerOnRequestPlugin = require("./plugins/HandlerOnRequestPlugin");
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);
67
42
  });
43
+ reply.headers(headers.getHeaders());
68
44
  };
69
-
70
- const OPTIONS_HEADERS = {
71
- "Access-Control-Max-Age": "86400",
72
- "Cache-Control": "public, max-age=86400"
73
- };
74
-
75
45
  const createHandler = params => {
76
46
  const definedRoutes = {
77
47
  POST: [],
@@ -89,82 +59,99 @@ const createHandler = params => {
89
59
  PROPPATCH: [],
90
60
  SEARCH: [],
91
61
  TRACE: [],
92
- UNLOCK: []
62
+ UNLOCK: [],
63
+ REPORT: [],
64
+ MKCALENDAR: []
93
65
  };
94
-
95
66
  const throwOnDefinedRoute = (type, path, options) => {
96
67
  if (type === "ALL") {
97
- const all = Object.keys(definedRoutes).some(key => {
68
+ const all = Object.keys(definedRoutes).find(k => {
69
+ const key = k.toUpperCase();
98
70
  const routes = definedRoutes[key];
99
71
  return routes.includes(path);
100
72
  });
101
-
102
73
  if (!all) {
103
74
  return;
104
75
  }
105
-
76
+ console.error(`Error while registering onAll route. One of the routes is already defined.`);
77
+ console.error(JSON.stringify(all));
106
78
  throw new _error.default(`You cannot override a route with onAll() method, please remove unnecessary route from the system.`, "OVERRIDE_ROUTE_ERROR", {
107
79
  type,
108
80
  path
109
81
  });
110
82
  } else if (definedRoutes[type].includes(path) === false) {
111
83
  return;
112
- } else if ((options === null || options === void 0 ? void 0 : options.override) === true) {
84
+ } else if (options?.override === true) {
113
85
  return;
114
86
  }
115
-
87
+ console.error(`Error while trying to override route: [${type}] ${path}`);
116
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", {
117
89
  type,
118
90
  path
119
91
  });
120
92
  };
121
-
122
- const addDefinedRoute = (inputType, path) => {
123
- const type = inputType.toUpperCase();
124
-
93
+ const addDefinedRoute = (input, path) => {
94
+ const type = input.toUpperCase();
125
95
  if (!definedRoutes[type]) {
126
96
  return;
127
97
  } else if (definedRoutes[type].includes(path)) {
128
98
  return;
129
99
  }
130
-
131
100
  definedRoutes[type].push(path);
132
101
  };
102
+
133
103
  /**
134
104
  * We must attach the server to our internal context if we want to have it accessible.
135
105
  */
106
+ const app = (0, _fastify.default)({
107
+ bodyLimit: 536870912,
108
+ // 512MB
109
+ disableRequestLogging: true,
110
+ ...(params.options || {})
111
+ });
136
112
 
137
-
138
- const app = (0, _fastify.default)((0, _objectSpread2.default)({}, params.options || {}));
139
113
  /**
140
- * 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.
141
115
  */
142
-
143
116
  app.addHook("onRoute", route => {
144
117
  const method = route.method;
145
-
146
118
  if (Array.isArray(method)) {
147
119
  for (const m of method) {
148
120
  addDefinedRoute(m, route.path);
149
121
  }
150
-
151
122
  return;
152
123
  }
153
-
154
124
  addDefinedRoute(method, route.path);
155
125
  });
156
126
  /**
127
+ * ############################
128
+ * Register the Fastify plugins.
129
+ */
130
+ /**
131
+ * Package @fastify/cookie
157
132
  *
133
+ * https://github.com/fastify/fastify-cookie
158
134
  */
159
-
160
135
  app.register(_cookie.default, {
161
136
  parseOptions: {} // options for parsing cookies
162
-
137
+ });
138
+ /**
139
+ * Package @fastify/compress
140
+ *
141
+ * https://github.com/fastify/fastify-compress
142
+ */
143
+ app.register(_compress.default, {
144
+ global: true,
145
+ threshold: 1024,
146
+ onUnsupportedEncoding: (encoding, _, reply) => {
147
+ reply.code(406);
148
+ return `We do not support the ${encoding} encoding.`;
149
+ },
150
+ inflateIfDeflated: true
163
151
  });
164
152
  /**
165
153
  * Route helpers - mostly for users.
166
154
  */
167
-
168
155
  const routes = {
169
156
  defined: definedRoutes,
170
157
  onPost: (path, handler, options) => {
@@ -200,120 +187,215 @@ const createHandler = params => {
200
187
  app.head(path, handler);
201
188
  }
202
189
  };
203
- const context = new _Context.Context({
204
- plugins: [
205
- /**
206
- * We must have handlerClient by default.
207
- * And it must be one of the first context plugins applied.
208
- */
209
- (0, _handlerClient.createHandlerClient)(), ...(params.plugins || [])],
210
-
211
- /**
212
- * Inserted via webpack on build time.
213
- */
214
- WEBINY_VERSION: process.env.WEBINY_VERSION,
215
- server: app,
216
- routes
217
- });
190
+ let context;
191
+ const plugins = new _types.PluginsContainer([
218
192
  /**
219
- * We are attaching our custom context to webiny variable on the fastify app so it is accessible everywhere
193
+ * We must have handlerClient by default.
194
+ * And it must be one of the first context plugins applied.
220
195
  */
196
+ (0, _handlerClient.createHandlerClient)()]);
197
+ plugins.merge(params.plugins || []);
198
+ try {
199
+ context = new _Context.Context({
200
+ plugins,
201
+ /**
202
+ * Inserted via webpack at build time.
203
+ */
204
+ WEBINY_VERSION: process.env.WEBINY_VERSION,
205
+ routes
206
+ });
207
+ } catch (ex) {
208
+ console.error(`Error while constructing the Context.`);
209
+ console.error((0, _stringifyError.stringifyError)(ex));
210
+ throw ex;
211
+ }
221
212
 
222
- app.decorate("webiny", context);
223
213
  /**
224
- * We have few types of triggers:
225
- * * Events - EventPlugin
226
- * * Routes - RoutePlugin
227
- *
228
- * Routes are registered in fastify but events must be handled in package which implements cloud specific methods.
214
+ * We are attaching our custom context to webiny variable on the fastify app, so it is accessible everywhere.
229
215
  */
216
+ app.decorate("webiny", context);
230
217
 
231
- const routePlugins = app.webiny.plugins.byType(_RoutePlugin.RoutePlugin.type);
232
218
  /**
233
- * Add routes to the system.
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
234
223
  */
224
+ app.addHook("onRequest", async request => {
225
+ if (request.method === "OPTIONS" && request.body === undefined) {
226
+ request.headers["content-type"] = undefined;
227
+ }
228
+ });
235
229
 
236
- for (const plugin of routePlugins) {
237
- plugin.cb((0, _objectSpread2.default)((0, _objectSpread2.default)({}, app.webiny.routes), {}, {
238
- context: app.webiny
239
- }));
240
- }
241
230
  /**
242
- * On every request we add default headers, which can be changed later.
243
- * Also, if it is an options request, we skip everything after this hook and output options headers.
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`
244
237
  */
245
-
246
-
247
- app.addHook("onRequest", async (request, reply) => {
248
- const defaultHeaders = getDefaultHeaders(definedRoutes);
249
- reply.headers(defaultHeaders);
250
-
251
- if (request.method !== "OPTIONS") {
252
- return;
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);
252
+ });
253
+ app.addHook("preSerialization", async (_, __, payload) => {
254
+ const plugins = app.webiny.plugins.byType(_HandlerResultPlugin.HandlerResultPlugin.type);
255
+ let name;
256
+ try {
257
+ for (const plugin of plugins) {
258
+ name = plugin.name;
259
+ await plugin.handle(app.webiny, payload);
260
+ }
261
+ } catch (ex) {
262
+ console.error(`Error while running the "HandlerResultPlugin" ${name ? `(${name})` : ""} plugin in the preSerialization hook.`);
263
+ console.error((0, _stringifyError.stringifyError)(ex));
264
+ throw ex;
253
265
  }
254
-
255
- const raw = reply.code(204).hijack().raw;
256
- const headers = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, defaultHeaders), OPTIONS_HEADERS);
257
-
258
- for (const key in headers) {
259
- raw.setHeader(key, headers[key]);
266
+ return payload;
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;
260
275
  }
261
-
262
- raw.end("");
276
+ return reply.status(500).headers({
277
+ "Cache-Control": "no-store"
278
+ }).send(
279
+ /**
280
+ * When we are sending the error in the response, we cannot send the whole error object, as it might contain some sensitive data.
281
+ */
282
+ JSON.stringify({
283
+ message: error.message,
284
+ code: error.code,
285
+ data: error.data
286
+ }));
263
287
  });
264
- app.addHook("preParsing", async request => {
265
- app.webiny.request = request;
266
- const plugins = app.webiny.plugins.byType(_api.ContextPlugin.type);
267
-
268
- for (const plugin of plugins) {
269
- await plugin.apply(app.webiny);
288
+ app.addHook("onError", async (_, reply, error) => {
289
+ const plugins = app.webiny.plugins.byType(_HandlerErrorPlugin.HandlerErrorPlugin.type);
290
+ /**
291
+ * Log error to cloud, as these can be extremely annoying to debug!
292
+ */
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
+ }
301
+ /**
302
+ * IMPORTANT! Do not send anything if reply was already sent.
303
+ */
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).");
270
318
  }
319
+ const handler = (0, _utils.middleware)(plugins.map(pl => {
320
+ return (context, error, next) => {
321
+ return pl.handle(context, error, next);
322
+ };
323
+ }));
324
+ await handler(app.webiny, error);
325
+ return reply;
271
326
  });
327
+
272
328
  /**
273
- *
329
+ * Apply response headers modifier plugins.
274
330
  */
275
-
276
- app.addHook("preHandler", async () => {
277
- const plugins = app.webiny.plugins.byType(_BeforeHandlerPlugin.BeforeHandlerPlugin.type);
278
-
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;
279
335
  for (const plugin of plugins) {
280
- await plugin.apply(app.webiny);
336
+ payload = await plugin.exec(request, reply, payload);
281
337
  }
338
+ return payload;
282
339
  });
340
+
283
341
  /**
284
- *
342
+ * We need to output the benchmark results at the end of the request in both response and timeout cases
285
343
  */
286
-
287
- const preSerialization = async (_, __, payload) => {
288
- const plugins = app.webiny.plugins.byType(_HandlerResultPlugin.HandlerResultPlugin.type);
289
-
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);
290
349
  for (const plugin of plugins) {
291
- await plugin.handle(app.webiny, payload);
350
+ await plugin.exec(request, reply);
292
351
  }
352
+ await context.benchmark.output();
353
+ });
293
354
 
294
- return payload;
295
- };
355
+ /**
356
+ * With these plugins we give users possibility to do anything they want on our fastify instance.
357
+ */
358
+ const modifyPlugins = app.webiny.plugins.byType(_ModifyFastifyPlugin.ModifyFastifyPlugin.type);
359
+ let modifyFastifyPluginName;
360
+ try {
361
+ for (const plugin of modifyPlugins) {
362
+ modifyFastifyPluginName = plugin.name;
363
+ plugin.modify(app);
364
+ }
365
+ } catch (ex) {
366
+ console.error(`Error while running the "ModifyFastifyPlugin" ${modifyFastifyPluginName ? `(${modifyFastifyPluginName})` : ""} plugin in the end of the "createHandler" callable.`);
367
+ console.error((0, _stringifyError.stringifyError)(ex));
368
+ throw ex;
369
+ }
296
370
 
297
- app.addHook("preSerialization", preSerialization);
298
- app.addHook("onError", async (_, reply, error) => {
299
- const plugins = app.webiny.plugins.byType(_HandlerErrorPlugin.HandlerErrorPlugin.type); // Log error to cloud, as these can be extremely annoying to debug!
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);
300
379
 
301
- console.log("@webiny/handler");
302
- console.log(JSON.stringify((0, _objectSpread2.default)((0, _objectSpread2.default)({}, error || {}), {}, {
303
- message: error === null || error === void 0 ? void 0 : error.message,
304
- code: error === null || error === void 0 ? void 0 : error.code
305
- })));
306
- const handler = (0, _middleware.middleware)(plugins.map(pl => {
307
- return (context, error, next) => {
308
- return pl.handle(context, error, next);
309
- };
310
- }));
311
- await handler(app.webiny, error);
312
- return reply.headers({
313
- "Cache-Control": "no-store"
314
- }).status(500);
315
- });
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
+ }
316
397
  return app;
317
398
  };
399
+ exports.createHandler = createHandler;
318
400
 
319
- exports.createHandler = createHandler;
401
+ //# sourceMappingURL=fastify.js.map