@loopback/rest 5.2.0 → 6.2.0

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 (78) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/README.md +4 -0
  3. package/dist/body-parsers/body-parser.js +3 -0
  4. package/dist/body-parsers/body-parser.js.map +1 -1
  5. package/dist/coercion/coerce-parameter.js +3 -2
  6. package/dist/coercion/coerce-parameter.js.map +1 -1
  7. package/dist/coercion/utils.d.ts +1 -1
  8. package/dist/index.js +1 -1
  9. package/dist/keys.d.ts +18 -3
  10. package/dist/keys.js +18 -1
  11. package/dist/keys.js.map +1 -1
  12. package/dist/parser.d.ts +2 -2
  13. package/dist/parser.js +3 -2
  14. package/dist/parser.js.map +1 -1
  15. package/dist/providers/find-route.provider.d.ts +7 -1
  16. package/dist/providers/find-route.provider.js +29 -1
  17. package/dist/providers/find-route.provider.js.map +1 -1
  18. package/dist/providers/invoke-method.provider.d.ts +7 -1
  19. package/dist/providers/invoke-method.provider.js +43 -1
  20. package/dist/providers/invoke-method.provider.js.map +1 -1
  21. package/dist/providers/parse-params.provider.d.ts +8 -2
  22. package/dist/providers/parse-params.provider.js +32 -2
  23. package/dist/providers/parse-params.provider.js.map +1 -1
  24. package/dist/providers/send.provider.d.ts +10 -2
  25. package/dist/providers/send.provider.js +46 -1
  26. package/dist/providers/send.provider.js.map +1 -1
  27. package/dist/request-context.js.map +1 -1
  28. package/dist/rest-http-error.d.ts +3 -1
  29. package/dist/rest-http-error.js +3 -2
  30. package/dist/rest-http-error.js.map +1 -1
  31. package/dist/rest.application.js +1 -1
  32. package/dist/rest.application.js.map +1 -1
  33. package/dist/rest.component.d.ts +1 -2
  34. package/dist/rest.component.js +23 -7
  35. package/dist/rest.component.js.map +1 -1
  36. package/dist/rest.server.d.ts +8 -4
  37. package/dist/rest.server.js +25 -12
  38. package/dist/rest.server.js.map +1 -1
  39. package/dist/router/base-route.js +3 -3
  40. package/dist/router/base-route.js.map +1 -1
  41. package/dist/router/controller-route.js +1 -1
  42. package/dist/router/controller-route.js.map +1 -1
  43. package/dist/router/handler-route.js +1 -1
  44. package/dist/router/handler-route.js.map +1 -1
  45. package/dist/router/redirect-route.js +1 -1
  46. package/dist/router/redirect-route.js.map +1 -1
  47. package/dist/sequence.d.ts +84 -2
  48. package/dist/sequence.js +135 -2
  49. package/dist/sequence.js.map +1 -1
  50. package/dist/types.d.ts +9 -4
  51. package/dist/validation/ajv-factory.provider.d.ts +3 -2
  52. package/dist/validation/ajv-factory.provider.js +7 -2
  53. package/dist/validation/ajv-factory.provider.js.map +1 -1
  54. package/dist/validation/request-body.validator.d.ts +2 -2
  55. package/dist/validation/request-body.validator.js +11 -13
  56. package/dist/validation/request-body.validator.js.map +1 -1
  57. package/package.json +25 -25
  58. package/src/body-parsers/body-parser.ts +3 -0
  59. package/src/coercion/coerce-parameter.ts +4 -3
  60. package/src/keys.ts +34 -3
  61. package/src/parser.ts +4 -3
  62. package/src/providers/find-route.provider.ts +36 -3
  63. package/src/providers/invoke-method.provider.ts +47 -3
  64. package/src/providers/parse-params.provider.ts +36 -9
  65. package/src/providers/send.provider.ts +45 -2
  66. package/src/request-context.ts +2 -1
  67. package/src/rest-http-error.ts +6 -2
  68. package/src/rest.application.ts +1 -1
  69. package/src/rest.component.ts +40 -10
  70. package/src/rest.server.ts +50 -16
  71. package/src/router/base-route.ts +3 -3
  72. package/src/router/controller-route.ts +1 -1
  73. package/src/router/handler-route.ts +3 -1
  74. package/src/router/redirect-route.ts +1 -1
  75. package/src/sequence.ts +174 -4
  76. package/src/types.ts +13 -4
  77. package/src/validation/ajv-factory.provider.ts +10 -8
  78. package/src/validation/request-body.validator.ts +28 -24
@@ -11,12 +11,13 @@ import {
11
11
  } from '@loopback/openapi-v3';
12
12
  import debugModule from 'debug';
13
13
  import {
14
- RequestBodyValidationOptions,
15
14
  RestHttpErrors,
16
15
  validateValueAgainstSchema,
16
+ ValidationOptions,
17
17
  ValueValidationOptions,
18
18
  } from '../';
19
19
  import {parseJson} from '../parse-json';
20
+ import {DEFAULT_AJV_VALIDATION_OPTIONS} from '../validation/ajv-factory.provider';
20
21
  import {
21
22
  DateCoercionOptions,
22
23
  getOAIPrimitiveType,
@@ -167,7 +168,7 @@ function coerceBoolean(data: string | object, spec: ParameterObject) {
167
168
  async function coerceObject(
168
169
  input: string | object,
169
170
  spec: ParameterObject,
170
- options?: RequestBodyValidationOptions,
171
+ options: ValidationOptions = DEFAULT_AJV_VALIDATION_OPTIONS,
171
172
  ) {
172
173
  const data = parseJsonIfNeeded(input, spec);
173
174
 
@@ -186,7 +187,7 @@ async function coerceObject(
186
187
  data,
187
188
  schema,
188
189
  {},
189
- {...options, coerceTypes: true, source: 'parameter'},
190
+ {...options, coerceTypes: true, source: 'parameter', name: spec.name},
190
191
  );
191
192
  }
192
193
 
package/src/keys.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  // License text available at https://opensource.org/licenses/MIT
5
5
 
6
6
  import {BindingKey, Context, CoreBindings} from '@loopback/core';
7
- import {InvokeMiddleware} from '@loopback/express';
7
+ import {DEFAULT_MIDDLEWARE_CHAIN, InvokeMiddleware} from '@loopback/express';
8
8
  import {HttpProtocol} from '@loopback/http-server';
9
9
  import {OpenApiSpec, OperationObject} from '@loopback/openapi-v3';
10
10
  import https from 'https';
@@ -12,13 +12,15 @@ import {ErrorWriterOptions} from 'strong-error-handler';
12
12
  import {BodyParser, RequestBodyParser} from './body-parsers';
13
13
  import {HttpHandler} from './http-handler';
14
14
  import {RestServer, RestServerConfig} from './rest.server';
15
- import {RestRouter, RestRouterOptions} from './router';
15
+ import {ResolvedRoute, RestRouter, RestRouterOptions} from './router';
16
16
  import {SequenceHandler} from './sequence';
17
17
  import {
18
18
  AjvFactory,
19
19
  FindRoute,
20
20
  InvokeMethod,
21
21
  LogError,
22
+ OperationArgs,
23
+ OperationRetval,
22
24
  ParseParams,
23
25
  Reject,
24
26
  Request,
@@ -179,12 +181,20 @@ export namespace RestBindings {
179
181
  */
180
182
  export const SEQUENCE = BindingKey.create<SequenceHandler>('rest.sequence');
181
183
 
184
+ /**
185
+ * Binding key for setting and injecting a `invokeMiddleware` function for
186
+ * middleware based sequence
187
+ */
188
+ export const INVOKE_MIDDLEWARE_SERVICE = BindingKey.create<InvokeMiddleware>(
189
+ 'rest.invokeMiddleware',
190
+ );
191
+
182
192
  /**
183
193
  * Bindings for potential actions that could be used in a sequence
184
194
  */
185
195
  export namespace SequenceActions {
186
196
  /**
187
- * Binding key for setting and injecting a route finding function
197
+ * Binding key for setting and injecting `invokeMiddleware` function
188
198
  */
189
199
  export const INVOKE_MIDDLEWARE = BindingKey.create<InvokeMiddleware>(
190
200
  'rest.sequence.actions.invokeMiddleware',
@@ -225,6 +235,20 @@ export namespace RestBindings {
225
235
  );
226
236
  }
227
237
 
238
+ export namespace Operation {
239
+ export const ROUTE = BindingKey.create<ResolvedRoute>(
240
+ 'rest.operation.route',
241
+ );
242
+
243
+ export const PARAMS = BindingKey.create<OperationArgs>(
244
+ 'rest.operation.params',
245
+ );
246
+
247
+ export const RETURN_VALUE = BindingKey.create<OperationRetval>(
248
+ 'rest.operation.returnValue',
249
+ );
250
+ }
251
+
228
252
  /**
229
253
  * Request-specific bindings
230
254
  */
@@ -285,4 +309,11 @@ export namespace RestTags {
285
309
 
286
310
  export const AJV_KEYWORD = 'ajvKeyword';
287
311
  export const AJV_FORMAT = 'ajvFormat';
312
+
313
+ export const REST_MIDDLEWARE_CHAIN = DEFAULT_MIDDLEWARE_CHAIN;
314
+
315
+ /**
316
+ * Legacy middleware chain for action-based REST sequence
317
+ */
318
+ export const ACTION_MIDDLEWARE_CHAIN = 'middlewareChain.rest.actions';
288
319
  }
package/src/parser.ts CHANGED
@@ -19,8 +19,9 @@ import {
19
19
  OperationArgs,
20
20
  PathParameterValues,
21
21
  Request,
22
- RequestBodyValidationOptions,
22
+ ValidationOptions,
23
23
  } from './types';
24
+ import {DEFAULT_AJV_VALIDATION_OPTIONS} from './validation/ajv-factory.provider';
24
25
  import {validateRequestBody} from './validation/request-body.validator';
25
26
  const debug = debugFactory('loopback:rest:parser');
26
27
 
@@ -35,7 +36,7 @@ export async function parseOperationArgs(
35
36
  request: Request,
36
37
  route: ResolvedRoute,
37
38
  requestBodyParser: RequestBodyParser = new RequestBodyParser(),
38
- options: RequestBodyValidationOptions = {},
39
+ options: ValidationOptions = DEFAULT_AJV_VALIDATION_OPTIONS,
39
40
  ): Promise<OperationArgs> {
40
41
  debug('Parsing operation arguments for route %s', route.describe());
41
42
  const operationSpec = route.spec;
@@ -60,7 +61,7 @@ async function buildOperationArguments(
60
61
  pathParams: PathParameterValues,
61
62
  body: RequestBody,
62
63
  globalSchemas: SchemasObject,
63
- options: RequestBodyValidationOptions = {},
64
+ options: ValidationOptions = DEFAULT_AJV_VALIDATION_OPTIONS,
64
65
  ): Promise<OperationArgs> {
65
66
  let requestBodyIndex = -1;
66
67
  if (operationSpec.requestBody) {
@@ -3,11 +3,16 @@
3
3
  // This file is licensed under the MIT License.
4
4
  // License text available at https://opensource.org/licenses/MIT
5
5
 
6
- import {Context, inject, Provider} from '@loopback/core';
7
- import {FindRoute, Request} from '../types';
6
+ import {bind, Context, inject, Provider} from '@loopback/core';
7
+ import {asMiddleware, Middleware} from '@loopback/express';
8
+ import debugFactory from 'debug';
8
9
  import {HttpHandler} from '../http-handler';
9
- import {RestBindings} from '../keys';
10
+ import {RestBindings, RestTags} from '../keys';
10
11
  import {ResolvedRoute} from '../router';
12
+ import {RestMiddlewareGroups} from '../sequence';
13
+ import {FindRoute, Request} from '../types';
14
+
15
+ const debug = debugFactory('loopback:rest:find-route');
11
16
 
12
17
  export class FindRouteProvider implements Provider<FindRoute> {
13
18
  constructor(
@@ -21,7 +26,35 @@ export class FindRouteProvider implements Provider<FindRoute> {
21
26
 
22
27
  action(request: Request): ResolvedRoute {
23
28
  const found = this.handler.findRoute(request);
29
+ debug('Route found for %s %s', request.method, request.originalUrl, found);
24
30
  found.updateBindings(this.context);
25
31
  return found;
26
32
  }
27
33
  }
34
+
35
+ @bind(
36
+ asMiddleware({
37
+ group: RestMiddlewareGroups.FIND_ROUTE,
38
+ chain: RestTags.REST_MIDDLEWARE_CHAIN,
39
+ }),
40
+ )
41
+ export class FindRouteMiddlewareProvider implements Provider<Middleware> {
42
+ constructor(
43
+ @inject(RestBindings.SequenceActions.FIND_ROUTE)
44
+ protected findRoute: FindRoute,
45
+ ) {}
46
+
47
+ value(): Middleware {
48
+ return async (ctx, next) => {
49
+ debug(
50
+ 'Finding route for %s %s',
51
+ ctx.request.method,
52
+ ctx.request.originalUrl,
53
+ );
54
+ const route = this.findRoute(ctx.request);
55
+ debug('Route found', route);
56
+ ctx.bind(RestBindings.Operation.ROUTE).to(route);
57
+ return next();
58
+ };
59
+ }
60
+ }
@@ -3,10 +3,15 @@
3
3
  // This file is licensed under the MIT License.
4
4
  // License text available at https://opensource.org/licenses/MIT
5
5
 
6
- import {Context, inject, Provider} from '@loopback/core';
7
- import {InvokeMethod, OperationArgs, OperationRetval} from '../types';
8
- import {RestBindings} from '../keys';
6
+ import {bind, Context, inject, Provider} from '@loopback/core';
7
+ import {asMiddleware, Middleware} from '@loopback/express';
8
+ import debugFactory from 'debug';
9
+ import {RestBindings, RestTags} from '../keys';
9
10
  import {RouteEntry} from '../router';
11
+ import {RestMiddlewareGroups} from '../sequence';
12
+ import {InvokeMethod, OperationArgs, OperationRetval} from '../types';
13
+
14
+ const debug = debugFactory('loopback:rest:invoke-method');
10
15
 
11
16
  export class InvokeMethodProvider implements Provider<InvokeMethod> {
12
17
  constructor(@inject(RestBindings.Http.CONTEXT) protected context: Context) {}
@@ -19,3 +24,42 @@ export class InvokeMethodProvider implements Provider<InvokeMethod> {
19
24
  return route.invokeHandler(this.context, args);
20
25
  }
21
26
  }
27
+
28
+ @bind(
29
+ asMiddleware({
30
+ group: RestMiddlewareGroups.INVOKE_METHOD,
31
+ upstreamGroups: RestMiddlewareGroups.PARSE_PARAMS,
32
+ chain: RestTags.REST_MIDDLEWARE_CHAIN,
33
+ }),
34
+ )
35
+ export class InvokeMethodMiddlewareProvider implements Provider<Middleware> {
36
+ constructor(
37
+ @inject(RestBindings.SequenceActions.INVOKE_METHOD)
38
+ protected invokeMethod: InvokeMethod,
39
+ ) {}
40
+
41
+ value(): Middleware {
42
+ return async (ctx, next) => {
43
+ const route: RouteEntry = await ctx.get(RestBindings.Operation.ROUTE);
44
+ const params: OperationArgs = await ctx.get(
45
+ RestBindings.Operation.PARAMS,
46
+ );
47
+ if (debug.enabled) {
48
+ debug('Invoking method %s with', route.describe(), params);
49
+ }
50
+ try {
51
+ const retVal = await this.invokeMethod(route, params);
52
+ ctx.bind(RestBindings.Operation.RETURN_VALUE).to(retVal);
53
+ if (debug.enabled) {
54
+ debug('Return value from %s', route.describe(), retVal);
55
+ }
56
+ return retVal;
57
+ } catch (err) {
58
+ if (debug.enabled) {
59
+ debug('Error thrown from %s', route.describe(), err);
60
+ }
61
+ throw err;
62
+ }
63
+ };
64
+ }
65
+ }
@@ -3,17 +3,19 @@
3
3
  // This file is licensed under the MIT License.
4
4
  // License text available at https://opensource.org/licenses/MIT
5
5
 
6
- import {inject, Provider} from '@loopback/core';
6
+ import {bind, inject, Provider} from '@loopback/core';
7
+ import {asMiddleware, Middleware} from '@loopback/express';
8
+ import debugFactory from 'debug';
7
9
  import {RequestBodyParser} from '../body-parsers';
8
- import {RestBindings} from '../keys';
10
+ import {RestBindings, RestTags} from '../keys';
9
11
  import {parseOperationArgs} from '../parser';
10
12
  import {ResolvedRoute} from '../router';
11
- import {
12
- AjvFactory,
13
- ParseParams,
14
- Request,
15
- RequestBodyValidationOptions,
16
- } from '../types';
13
+ import {RestMiddlewareGroups} from '../sequence';
14
+ import {AjvFactory, ParseParams, Request, ValidationOptions} from '../types';
15
+ import {DEFAULT_AJV_VALIDATION_OPTIONS} from '../validation/ajv-factory.provider';
16
+
17
+ const debug = debugFactory('loopback:rest:parse-param');
18
+
17
19
  /**
18
20
  * Provides the function for parsing args in requests at runtime.
19
21
  *
@@ -27,7 +29,7 @@ export class ParseParamsProvider implements Provider<ParseParams> {
27
29
  RestBindings.REQUEST_BODY_PARSER_OPTIONS.deepProperty('validation'),
28
30
  {optional: true},
29
31
  )
30
- private validationOptions: RequestBodyValidationOptions = {},
32
+ private validationOptions: ValidationOptions = DEFAULT_AJV_VALIDATION_OPTIONS,
31
33
  @inject(RestBindings.AJV_FACTORY, {optional: true})
32
34
  private ajvFactory?: AjvFactory,
33
35
  ) {}
@@ -40,3 +42,28 @@ export class ParseParamsProvider implements Provider<ParseParams> {
40
42
  });
41
43
  }
42
44
  }
45
+
46
+ @bind(
47
+ asMiddleware({
48
+ group: RestMiddlewareGroups.PARSE_PARAMS,
49
+ upstreamGroups: RestMiddlewareGroups.FIND_ROUTE,
50
+ chain: RestTags.REST_MIDDLEWARE_CHAIN,
51
+ }),
52
+ )
53
+ export class ParseParamsMiddlewareProvider implements Provider<Middleware> {
54
+ constructor(
55
+ @inject(RestBindings.SequenceActions.PARSE_PARAMS)
56
+ protected parseParams: ParseParams,
57
+ ) {}
58
+
59
+ value(): Middleware {
60
+ return async (ctx, next) => {
61
+ const route: ResolvedRoute = await ctx.get(RestBindings.Operation.ROUTE);
62
+ debug('Parsing parameters for %s %s', route.verb, route.path);
63
+ const params = await this.parseParams(ctx.request, route);
64
+ ctx.bind(RestBindings.Operation.PARAMS).to(params);
65
+ debug('Parameters', params);
66
+ return next();
67
+ };
68
+ }
69
+ }
@@ -3,7 +3,11 @@
3
3
  // This file is licensed under the MIT License.
4
4
  // License text available at https://opensource.org/licenses/MIT
5
5
 
6
- import {Provider, BoundValue} from '@loopback/core';
6
+ import {bind, inject, Provider} from '@loopback/core';
7
+ import {asMiddleware, Middleware} from '@loopback/express';
8
+ import {RestBindings, RestTags} from '../keys';
9
+ import {RestMiddlewareGroups} from '../sequence';
10
+ import {Reject, Send} from '../types';
7
11
  import {writeResultToResponse} from '../writer';
8
12
  /**
9
13
  * Provides the function that populates the response object with
@@ -12,8 +16,47 @@ import {writeResultToResponse} from '../writer';
12
16
  * @returns The handler function that will populate the
13
17
  * response with operation results.
14
18
  */
15
- export class SendProvider implements Provider<BoundValue> {
19
+ export class SendProvider implements Provider<Send> {
16
20
  value() {
17
21
  return writeResultToResponse;
18
22
  }
19
23
  }
24
+
25
+ @bind(
26
+ asMiddleware({
27
+ group: RestMiddlewareGroups.SEND_RESPONSE,
28
+ downstreamGroups: [
29
+ RestMiddlewareGroups.CORS,
30
+ RestMiddlewareGroups.INVOKE_METHOD,
31
+ ],
32
+ chain: RestTags.REST_MIDDLEWARE_CHAIN,
33
+ }),
34
+ )
35
+ export class SendResponseMiddlewareProvider implements Provider<Middleware> {
36
+ constructor(
37
+ @inject(RestBindings.SequenceActions.SEND)
38
+ protected send: Send,
39
+ @inject(RestBindings.SequenceActions.REJECT)
40
+ protected reject: Reject,
41
+ ) {}
42
+
43
+ value(): Middleware {
44
+ return async (ctx, next) => {
45
+ try {
46
+ /**
47
+ * Invoke downstream middleware to produce the result
48
+ */
49
+ const result = await next();
50
+ /**
51
+ * Write the result to HTTP response
52
+ */
53
+ this.send(ctx.response, result);
54
+ } catch (err) {
55
+ /**
56
+ * Write the error to HTTP response
57
+ */
58
+ this.reject(ctx, err);
59
+ }
60
+ };
61
+ }
62
+ }
@@ -17,7 +17,8 @@ import {RestServerResolvedConfig} from './rest.server';
17
17
  * A per-request Context combining an IoC container with handler context
18
18
  * (request, response, etc.).
19
19
  */
20
- export class RequestContext extends MiddlewareContext
20
+ export class RequestContext
21
+ extends MiddlewareContext
21
22
  implements HandlerContext {
22
23
  /**
23
24
  * Get the protocol used by the client to make the request.
@@ -11,7 +11,7 @@ export namespace RestHttpErrors {
11
11
  name: string,
12
12
  extraProperties?: Props,
13
13
  ): HttpErrors.HttpError & Props {
14
- const msg = `Invalid data ${JSON.stringify(data)} for parameter ${name}!`;
14
+ const msg = `Invalid data ${JSON.stringify(data)} for parameter "${name}".`;
15
15
  return Object.assign(
16
16
  new HttpErrors.BadRequest(msg),
17
17
  {
@@ -51,11 +51,15 @@ export namespace RestHttpErrors {
51
51
 
52
52
  export const INVALID_REQUEST_BODY_MESSAGE =
53
53
  'The request body is invalid. See error object `details` property for more info.';
54
- export function invalidRequestBody(): HttpErrors.HttpError {
54
+
55
+ export function invalidRequestBody(
56
+ details: ValidationErrorDetails[],
57
+ ): HttpErrors.HttpError & {details: ValidationErrorDetails[]} {
55
58
  return Object.assign(
56
59
  new HttpErrors.UnprocessableEntity(INVALID_REQUEST_BODY_MESSAGE),
57
60
  {
58
61
  code: 'VALIDATION_FAILED',
62
+ details,
59
63
  },
60
64
  );
61
65
  }
@@ -102,7 +102,7 @@ export class RestApplication extends Application implements HttpServerLike {
102
102
  }
103
103
 
104
104
  sequence(sequence: Constructor<SequenceHandler>): Binding {
105
- return this.bind(RestBindings.SEQUENCE).toClass(sequence);
105
+ return this.restServer.sequence(sequence);
106
106
  }
107
107
 
108
108
  handler(handlerFn: SequenceFunction) {
@@ -4,15 +4,14 @@
4
4
  // License text available at https://opensource.org/licenses/MIT
5
5
 
6
6
  import {
7
+ Application,
7
8
  Binding,
9
+ Component,
8
10
  Constructor,
11
+ CoreBindings,
12
+ CoreTags,
9
13
  createBindingFromClass,
10
14
  inject,
11
- } from '@loopback/core';
12
- import {
13
- Application,
14
- Component,
15
- CoreBindings,
16
15
  ProviderMap,
17
16
  Server,
18
17
  } from '@loopback/core';
@@ -26,21 +25,24 @@ import {
26
25
  UrlEncodedBodyParser,
27
26
  } from './body-parsers';
28
27
  import {RawBodyParser} from './body-parsers/body-parser.raw';
29
- import {RestBindings} from './keys';
28
+ import {RestBindings, RestTags} from './keys';
30
29
  import {
30
+ FindRouteMiddlewareProvider,
31
31
  FindRouteProvider,
32
+ InvokeMethodMiddlewareProvider,
32
33
  InvokeMethodProvider,
33
34
  LogErrorProvider,
35
+ ParseParamsMiddlewareProvider,
34
36
  ParseParamsProvider,
35
37
  RejectProvider,
36
38
  SendProvider,
39
+ SendResponseMiddlewareProvider,
37
40
  } from './providers';
38
41
  import {
39
42
  createBodyParserBinding,
40
43
  RestServer,
41
44
  RestServerConfig,
42
45
  } from './rest.server';
43
- import {DefaultSequence} from './sequence';
44
46
  import {ConsolidationEnhancer} from './spec-enhancers/consolidate.spec-enhancer';
45
47
  import {InfoSpecEnhancer} from './spec-enhancers/info.spec-enhancer';
46
48
  import {AjvFactoryProvider} from './validation/ajv-factory.provider';
@@ -48,8 +50,6 @@ import {AjvFactoryProvider} from './validation/ajv-factory.provider';
48
50
  export class RestComponent implements Component {
49
51
  providers: ProviderMap = {
50
52
  [RestBindings.SequenceActions.LOG_ERROR.key]: LogErrorProvider,
51
- [RestBindings.SequenceActions.INVOKE_MIDDLEWARE
52
- .key]: InvokeMiddlewareProvider,
53
53
  [RestBindings.SequenceActions.FIND_ROUTE.key]: FindRouteProvider,
54
54
  [RestBindings.SequenceActions.INVOKE_METHOD.key]: InvokeMethodProvider,
55
55
  [RestBindings.SequenceActions.REJECT.key]: RejectProvider,
@@ -86,6 +86,8 @@ export class RestComponent implements Component {
86
86
  ),
87
87
  createBindingFromClass(InfoSpecEnhancer),
88
88
  createBindingFromClass(ConsolidationEnhancer),
89
+
90
+ ...getRestMiddlewareBindings(),
89
91
  ];
90
92
  servers: {
91
93
  [name: string]: Constructor<Server>;
@@ -97,7 +99,26 @@ export class RestComponent implements Component {
97
99
  @inject(CoreBindings.APPLICATION_INSTANCE) app: Application,
98
100
  @inject(RestBindings.CONFIG) config?: RestComponentConfig,
99
101
  ) {
100
- app.bind(RestBindings.SEQUENCE).toClass(DefaultSequence);
102
+ // Register the `InvokeMiddleware` with default to `ACTION_MIDDLEWARE_CHAIN`
103
+ // to keep backward compatibility with action based sequence
104
+ const invokeMiddlewareActionBinding = createBindingFromClass(
105
+ InvokeMiddlewareProvider,
106
+ {
107
+ key: RestBindings.SequenceActions.INVOKE_MIDDLEWARE,
108
+ },
109
+ ).tag({[CoreTags.EXTENSION_POINT]: RestTags.ACTION_MIDDLEWARE_CHAIN});
110
+ app.add(invokeMiddlewareActionBinding);
111
+
112
+ // Register the `InvokeMiddleware` with default to `DEFAULT_MIDDLEWARE_CHAIN`
113
+ // for the middleware based sequence
114
+ const invokeMiddlewareServiceBinding = createBindingFromClass(
115
+ InvokeMiddlewareProvider,
116
+ {
117
+ key: RestBindings.INVOKE_MIDDLEWARE_SERVICE,
118
+ },
119
+ ).tag({[CoreTags.EXTENSION_POINT]: RestTags.REST_MIDDLEWARE_CHAIN});
120
+ app.add(invokeMiddlewareServiceBinding);
121
+
101
122
  const apiSpec = createEmptyApiSpec();
102
123
  // Merge the OpenAPI `servers` spec from the config into the empty one
103
124
  if (config?.openApiSpec?.servers) {
@@ -107,5 +128,14 @@ export class RestComponent implements Component {
107
128
  }
108
129
  }
109
130
 
131
+ function getRestMiddlewareBindings() {
132
+ return [
133
+ SendResponseMiddlewareProvider,
134
+ FindRouteMiddlewareProvider,
135
+ ParseParamsMiddlewareProvider,
136
+ InvokeMethodMiddlewareProvider,
137
+ ].map(cls => createBindingFromClass(cls));
138
+ }
139
+
110
140
  // TODO(kevin): Extend this interface def to include multiple servers?
111
141
  export type RestComponentConfig = RestServerConfig;