@loopback/rest 4.0.0-alpha.8 → 5.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1822 -0
- package/LICENSE +1 -1
- package/README.md +30 -58
- package/dist/body-parsers/body-parser.d.ts +25 -0
- package/dist/body-parsers/body-parser.helpers.d.ts +44 -0
- package/dist/body-parsers/body-parser.helpers.js +102 -0
- package/dist/body-parsers/body-parser.helpers.js.map +1 -0
- package/dist/body-parsers/body-parser.js +159 -0
- package/dist/body-parsers/body-parser.js.map +1 -0
- package/dist/body-parsers/body-parser.json.d.ts +9 -0
- package/dist/body-parsers/body-parser.json.js +43 -0
- package/dist/body-parsers/body-parser.json.js.map +1 -0
- package/dist/body-parsers/body-parser.raw.d.ts +12 -0
- package/dist/body-parsers/body-parser.raw.js +39 -0
- package/dist/body-parsers/body-parser.raw.js.map +1 -0
- package/dist/body-parsers/body-parser.stream.d.ts +12 -0
- package/dist/body-parsers/body-parser.stream.js +28 -0
- package/dist/body-parsers/body-parser.stream.js.map +1 -0
- package/dist/body-parsers/body-parser.text.d.ts +9 -0
- package/dist/body-parsers/body-parser.text.js +38 -0
- package/dist/body-parsers/body-parser.text.js.map +1 -0
- package/dist/body-parsers/body-parser.urlencoded.d.ts +9 -0
- package/dist/body-parsers/body-parser.urlencoded.js +36 -0
- package/dist/body-parsers/body-parser.urlencoded.js.map +1 -0
- package/dist/body-parsers/index.d.ts +8 -0
- package/dist/body-parsers/index.js +16 -0
- package/dist/body-parsers/index.js.map +1 -0
- package/dist/body-parsers/types.d.ts +51 -0
- package/dist/body-parsers/types.js +12 -0
- package/dist/body-parsers/types.js.map +1 -0
- package/dist/coercion/coerce-parameter.d.ts +9 -0
- package/dist/coercion/coerce-parameter.js +166 -0
- package/dist/coercion/coerce-parameter.js.map +1 -0
- package/dist/coercion/utils.d.ts +43 -0
- package/dist/coercion/utils.js +96 -0
- package/dist/coercion/utils.js.map +1 -0
- package/dist/coercion/validator.d.ts +49 -0
- package/dist/coercion/validator.js +85 -0
- package/dist/coercion/validator.js.map +1 -0
- package/dist/http-handler.d.ts +38 -0
- package/dist/http-handler.js +68 -0
- package/dist/http-handler.js.map +1 -0
- package/dist/index.d.ts +36 -1
- package/dist/index.js +40 -6
- package/dist/index.js.map +1 -0
- package/dist/keys.d.ts +198 -0
- package/dist/keys.js +202 -0
- package/dist/keys.js.map +1 -0
- package/dist/parse-json.d.ts +11 -0
- package/dist/parse-json.js +42 -0
- package/dist/parse-json.js.map +1 -0
- package/dist/parser.d.ts +11 -0
- package/dist/parser.js +76 -0
- package/dist/parser.js.map +1 -0
- package/{dist6/src/providers/find-route.d.ts → dist/providers/find-route.provider.d.ts} +3 -1
- package/dist/providers/find-route.provider.js +36 -0
- package/dist/providers/find-route.provider.js.map +1 -0
- package/dist/providers/index.d.ts +6 -0
- package/dist/providers/index.js +14 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/{src/providers/invoke-method.d.ts → providers/invoke-method.provider.d.ts} +3 -1
- package/dist/providers/invoke-method.provider.js +30 -0
- package/dist/providers/invoke-method.provider.js.map +1 -0
- package/dist/providers/log-error.provider.d.ts +6 -0
- package/dist/providers/log-error.provider.js +21 -0
- package/dist/providers/log-error.provider.js.map +1 -0
- package/dist/providers/parse-params.provider.d.ts +15 -0
- package/dist/providers/parse-params.provider.js +41 -0
- package/dist/providers/parse-params.provider.js.map +1 -0
- package/dist/providers/reject.provider.d.ts +10 -0
- package/dist/providers/reject.provider.js +47 -0
- package/dist/providers/reject.provider.js.map +1 -0
- package/dist/{src/providers/send.d.ts → providers/send.provider.d.ts} +1 -4
- package/dist/{src/providers/send.js → providers/send.provider.js} +4 -6
- package/dist/providers/send.provider.js.map +1 -0
- package/dist/request-context.d.ts +36 -0
- package/dist/request-context.js +104 -0
- package/dist/request-context.js.map +1 -0
- package/dist/rest-http-error.d.ts +37 -0
- package/dist/rest-http-error.js +51 -0
- package/dist/rest-http-error.js.map +1 -0
- package/dist/rest.application.d.ts +232 -0
- package/dist/rest.application.js +174 -0
- package/dist/rest.application.js.map +1 -0
- package/dist/rest.component.d.ts +15 -0
- package/dist/rest.component.js +72 -0
- package/dist/rest.component.js.map +1 -0
- package/dist/rest.server.d.ts +443 -0
- package/dist/rest.server.js +748 -0
- package/dist/rest.server.js.map +1 -0
- package/dist/router/base-route.d.ts +29 -0
- package/dist/router/base-route.js +41 -0
- package/dist/router/base-route.js.map +1 -0
- package/dist/router/controller-route.d.ts +61 -0
- package/dist/router/controller-route.js +160 -0
- package/dist/router/controller-route.js.map +1 -0
- package/dist/router/external-express-routes.d.ts +24 -0
- package/dist/router/external-express-routes.js +90 -0
- package/dist/router/external-express-routes.js.map +1 -0
- package/dist/router/handler-route.d.ts +12 -0
- package/dist/router/handler-route.js +30 -0
- package/dist/router/handler-route.js.map +1 -0
- package/dist/router/index.d.ts +14 -0
- package/dist/router/index.js +25 -0
- package/dist/router/index.js.map +1 -0
- package/dist/router/openapi-path.d.ts +14 -0
- package/dist/router/openapi-path.js +64 -0
- package/dist/router/openapi-path.js.map +1 -0
- package/dist/router/redirect-route.d.ts +23 -0
- package/dist/router/redirect-route.js +50 -0
- package/dist/router/redirect-route.js.map +1 -0
- package/dist/router/regexp-router.d.ts +25 -0
- package/dist/router/regexp-router.js +84 -0
- package/dist/router/regexp-router.js.map +1 -0
- package/dist/router/rest-router.d.ts +35 -0
- package/dist/{src/internal-types.js → router/rest-router.js} +2 -2
- package/dist/router/rest-router.js.map +1 -0
- package/dist/router/route-entry.d.ts +46 -0
- package/dist/router/route-entry.js +20 -0
- package/dist/router/route-entry.js.map +1 -0
- package/dist/router/route-sort.d.ts +7 -0
- package/dist/router/route-sort.js +75 -0
- package/dist/router/route-sort.js.map +1 -0
- package/dist/router/router-base.d.ts +42 -0
- package/dist/router/router-base.js +101 -0
- package/dist/router/router-base.js.map +1 -0
- package/dist/router/router-spec.d.ts +3 -0
- package/dist/router/router-spec.js +40 -0
- package/dist/router/router-spec.js.map +1 -0
- package/dist/router/routing-table.d.ts +32 -0
- package/dist/router/routing-table.js +86 -0
- package/dist/router/routing-table.js.map +1 -0
- package/dist/router/trie-router.d.ts +13 -0
- package/dist/router/trie-router.js +55 -0
- package/dist/router/trie-router.js.map +1 -0
- package/dist/router/trie.d.ts +59 -0
- package/dist/router/trie.js +180 -0
- package/dist/router/trie.js.map +1 -0
- package/{dist6/src → dist}/sequence.d.ts +28 -23
- package/dist/sequence.js +112 -0
- package/dist/sequence.js.map +1 -0
- package/dist/spec-enhancers/consolidate.spec-enhancer.d.ts +68 -0
- package/dist/spec-enhancers/consolidate.spec-enhancer.js +145 -0
- package/dist/spec-enhancers/consolidate.spec-enhancer.js.map +1 -0
- package/dist/spec-enhancers/info.spec-enhancer.d.ts +19 -0
- package/dist/spec-enhancers/info.spec-enhancer.js +89 -0
- package/dist/spec-enhancers/info.spec-enhancer.js.map +1 -0
- package/dist/types.d.ts +178 -0
- package/dist/types.js +12 -0
- package/dist/types.js.map +1 -0
- package/dist/validation/ajv-factory.provider.d.ts +12 -0
- package/dist/validation/ajv-factory.provider.js +87 -0
- package/dist/validation/ajv-factory.provider.js.map +1 -0
- package/dist/validation/request-body.validator.d.ts +14 -0
- package/dist/validation/request-body.validator.js +161 -0
- package/dist/validation/request-body.validator.js.map +1 -0
- package/dist/writer.d.ts +9 -0
- package/dist/writer.js +62 -0
- package/dist/writer.js.map +1 -0
- package/package.json +66 -38
- package/src/body-parsers/body-parser.helpers.ts +148 -0
- package/src/body-parsers/body-parser.json.ts +46 -0
- package/src/body-parsers/body-parser.raw.ts +42 -0
- package/src/body-parsers/body-parser.stream.ts +27 -0
- package/src/body-parsers/body-parser.text.ts +44 -0
- package/src/body-parsers/body-parser.ts +208 -0
- package/src/body-parsers/body-parser.urlencoded.ts +42 -0
- package/src/body-parsers/index.ts +13 -0
- package/src/body-parsers/types.ts +60 -0
- package/src/coercion/coerce-parameter.ts +207 -0
- package/src/coercion/utils.ts +103 -0
- package/src/coercion/validator.ts +98 -0
- package/src/http-handler.ts +84 -41
- package/src/index.ts +37 -30
- package/src/keys.ts +273 -20
- package/src/parse-json.ts +42 -0
- package/src/parser.ts +89 -104
- package/src/providers/{find-route.ts → find-route.provider.ts} +10 -7
- package/src/providers/index.ts +7 -9
- package/src/providers/{invoke-method.ts → invoke-method.provider.ts} +8 -5
- package/src/providers/log-error.provider.ts +27 -0
- package/src/providers/parse-params.provider.ts +42 -0
- package/src/providers/reject.provider.ts +44 -0
- package/src/providers/{send.ts → send.provider.ts} +2 -5
- package/src/request-context.ts +123 -0
- package/src/rest-http-error.ts +87 -0
- package/src/rest.application.ts +390 -0
- package/src/rest.component.ts +111 -0
- package/src/rest.server.ts +1192 -0
- package/src/router/base-route.ts +53 -0
- package/src/router/controller-route.ts +241 -0
- package/src/router/external-express-routes.ts +139 -0
- package/src/router/handler-route.ts +44 -0
- package/src/router/index.ts +24 -0
- package/src/router/openapi-path.ts +67 -0
- package/src/router/redirect-route.ts +64 -0
- package/src/router/regexp-router.ts +104 -0
- package/src/router/rest-router.ts +48 -0
- package/src/router/route-entry.ts +74 -0
- package/src/router/route-sort.ts +74 -0
- package/src/router/router-base.ts +124 -0
- package/src/router/router-spec.ts +36 -0
- package/src/router/routing-table.ts +83 -279
- package/src/router/trie-router.ts +57 -0
- package/src/router/trie.ts +233 -0
- package/src/sequence.ts +44 -37
- package/src/spec-enhancers/consolidate.spec-enhancer.ts +182 -0
- package/src/spec-enhancers/info.spec-enhancer.ts +92 -0
- package/src/types.ts +216 -0
- package/src/validation/ajv-factory.provider.ts +94 -0
- package/src/validation/request-body.validator.ts +208 -0
- package/src/writer.ts +41 -68
- package/api-docs/.DS_Store +0 -0
- package/api-docs/apple-touch-icon-114x114-precomposed.png +0 -0
- package/api-docs/apple-touch-icon-144x144-precomposed.png +0 -0
- package/api-docs/apple-touch-icon-57x57-precomposed.png +0 -0
- package/api-docs/apple-touch-icon-72x72-precomposed.png +0 -0
- package/api-docs/apple-touch-icon-precomposed.png +0 -0
- package/api-docs/apple-touch-icon.png +0 -0
- package/api-docs/css/bootstrap.min.css +0 -9
- package/api-docs/css/code-themes/arta.css +0 -158
- package/api-docs/css/code-themes/ascetic.css +0 -50
- package/api-docs/css/code-themes/brown_paper.css +0 -104
- package/api-docs/css/code-themes/brown_papersq.png +0 -0
- package/api-docs/css/code-themes/dark.css +0 -103
- package/api-docs/css/code-themes/default.css +0 -135
- package/api-docs/css/code-themes/far.css +0 -111
- package/api-docs/css/code-themes/github.css +0 -127
- package/api-docs/css/code-themes/googlecode.css +0 -144
- package/api-docs/css/code-themes/idea.css +0 -121
- package/api-docs/css/code-themes/ir_black.css +0 -104
- package/api-docs/css/code-themes/magula.css +0 -121
- package/api-docs/css/code-themes/monokai.css +0 -114
- package/api-docs/css/code-themes/pojoaque.css +0 -104
- package/api-docs/css/code-themes/pojoaque.jpg +0 -0
- package/api-docs/css/code-themes/rainbow.css +0 -114
- package/api-docs/css/code-themes/school_book.css +0 -111
- package/api-docs/css/code-themes/school_book.png +0 -0
- package/api-docs/css/code-themes/sl-theme.css +0 -45
- package/api-docs/css/code-themes/solarized_dark.css +0 -88
- package/api-docs/css/code-themes/solarized_light.css +0 -88
- package/api-docs/css/code-themes/sunburst.css +0 -158
- package/api-docs/css/code-themes/tomorrow-night-blue.css +0 -52
- package/api-docs/css/code-themes/tomorrow-night-bright.css +0 -51
- package/api-docs/css/code-themes/tomorrow-night-eighties.css +0 -51
- package/api-docs/css/code-themes/tomorrow-night.css +0 -52
- package/api-docs/css/code-themes/tomorrow.css +0 -49
- package/api-docs/css/code-themes/vs.css +0 -86
- package/api-docs/css/code-themes/xcode.css +0 -154
- package/api-docs/css/code-themes/zenburn.css +0 -115
- package/api-docs/css/main.css +0 -139
- package/api-docs/favicon.ico +0 -0
- package/api-docs/fonts/0ihfXUL2emPh0ROJezvraLO3LdcAZYWl9Si6vvxL-qU.woff +0 -0
- package/api-docs/fonts/OsJ2DjdpjqFRVUSto6IffLO3LdcAZYWl9Si6vvxL-qU.woff +0 -0
- package/api-docs/fonts/_aijTyevf54tkVDLy-dlnLO3LdcAZYWl9Si6vvxL-qU.woff +0 -0
- package/api-docs/index.html +0 -7082
- package/api-docs/js/main.js +0 -19
- package/api-docs/js/vendor/bootstrap.min.js +0 -6
- package/api-docs/js/vendor/jquery-1.10.1.min.js +0 -6
- package/api-docs/js/vendor/jquery.scrollTo-1.4.3.1.js +0 -218
- package/api-docs/js/vendor/modernizr-2.6.2-respond-1.1.0.min.js +0 -11
- package/dist/src/http-handler.d.ts +0 -19
- package/dist/src/http-handler.js +0 -43
- package/dist/src/http-handler.js.map +0 -1
- package/dist/src/index.d.ts +0 -14
- package/dist/src/index.js +0 -33
- package/dist/src/index.js.map +0 -1
- package/dist/src/internal-types.d.ts +0 -67
- package/dist/src/internal-types.js.map +0 -1
- package/dist/src/keys.d.ts +0 -22
- package/dist/src/keys.js +0 -35
- package/dist/src/keys.js.map +0 -1
- package/dist/src/parser.d.ts +0 -11
- package/dist/src/parser.js +0 -98
- package/dist/src/parser.js.map +0 -1
- package/dist/src/providers/bind-element.d.ts +0 -7
- package/dist/src/providers/bind-element.js +0 -34
- package/dist/src/providers/bind-element.js.map +0 -1
- package/dist/src/providers/find-route.d.ts +0 -9
- package/dist/src/providers/find-route.js +0 -42
- package/dist/src/providers/find-route.js.map +0 -1
- package/dist/src/providers/get-from-context.d.ts +0 -7
- package/dist/src/providers/get-from-context.js +0 -34
- package/dist/src/providers/get-from-context.js.map +0 -1
- package/dist/src/providers/index.d.ts +0 -8
- package/dist/src/providers/index.js +0 -18
- package/dist/src/providers/index.js.map +0 -1
- package/dist/src/providers/invoke-method.js +0 -36
- package/dist/src/providers/invoke-method.js.map +0 -1
- package/dist/src/providers/log-error-provider.d.ts +0 -6
- package/dist/src/providers/log-error-provider.js +0 -17
- package/dist/src/providers/log-error-provider.js.map +0 -1
- package/dist/src/providers/parse-params.d.ts +0 -13
- package/dist/src/providers/parse-params.js +0 -22
- package/dist/src/providers/parse-params.js.map +0 -1
- package/dist/src/providers/reject.d.ts +0 -6
- package/dist/src/providers/reject.js +0 -40
- package/dist/src/providers/reject.js.map +0 -1
- package/dist/src/providers/send.js.map +0 -1
- package/dist/src/rest-component.d.ts +0 -12
- package/dist/src/rest-component.js +0 -50
- package/dist/src/rest-component.js.map +0 -1
- package/dist/src/rest-server.d.ts +0 -211
- package/dist/src/rest-server.js +0 -426
- package/dist/src/rest-server.js.map +0 -1
- package/dist/src/router/metadata.d.ts +0 -150
- package/dist/src/router/metadata.js +0 -410
- package/dist/src/router/metadata.js.map +0 -1
- package/dist/src/router/routing-table.d.ts +0 -68
- package/dist/src/router/routing-table.js +0 -204
- package/dist/src/router/routing-table.js.map +0 -1
- package/dist/src/sequence.d.ts +0 -81
- package/dist/src/sequence.js +0 -104
- package/dist/src/sequence.js.map +0 -1
- package/dist/src/writer.d.ts +0 -17
- package/dist/src/writer.js +0 -87
- package/dist/src/writer.js.map +0 -1
- package/dist6/index.d.ts +0 -1
- package/dist6/index.js +0 -12
- package/dist6/src/http-handler.d.ts +0 -19
- package/dist6/src/http-handler.js +0 -53
- package/dist6/src/http-handler.js.map +0 -1
- package/dist6/src/index.d.ts +0 -14
- package/dist6/src/index.js +0 -33
- package/dist6/src/index.js.map +0 -1
- package/dist6/src/internal-types.d.ts +0 -67
- package/dist6/src/internal-types.js +0 -7
- package/dist6/src/internal-types.js.map +0 -1
- package/dist6/src/keys.d.ts +0 -22
- package/dist6/src/keys.js +0 -35
- package/dist6/src/keys.js.map +0 -1
- package/dist6/src/parser.d.ts +0 -11
- package/dist6/src/parser.js +0 -108
- package/dist6/src/parser.js.map +0 -1
- package/dist6/src/providers/bind-element.d.ts +0 -7
- package/dist6/src/providers/bind-element.js +0 -34
- package/dist6/src/providers/bind-element.js.map +0 -1
- package/dist6/src/providers/find-route.js +0 -42
- package/dist6/src/providers/find-route.js.map +0 -1
- package/dist6/src/providers/get-from-context.d.ts +0 -7
- package/dist6/src/providers/get-from-context.js +0 -34
- package/dist6/src/providers/get-from-context.js.map +0 -1
- package/dist6/src/providers/index.d.ts +0 -8
- package/dist6/src/providers/index.js +0 -18
- package/dist6/src/providers/index.js.map +0 -1
- package/dist6/src/providers/invoke-method.d.ts +0 -7
- package/dist6/src/providers/invoke-method.js +0 -44
- package/dist6/src/providers/invoke-method.js.map +0 -1
- package/dist6/src/providers/log-error-provider.d.ts +0 -6
- package/dist6/src/providers/log-error-provider.js +0 -17
- package/dist6/src/providers/log-error-provider.js.map +0 -1
- package/dist6/src/providers/parse-params.d.ts +0 -13
- package/dist6/src/providers/parse-params.js +0 -22
- package/dist6/src/providers/parse-params.js.map +0 -1
- package/dist6/src/providers/reject.d.ts +0 -6
- package/dist6/src/providers/reject.js +0 -40
- package/dist6/src/providers/reject.js.map +0 -1
- package/dist6/src/providers/send.d.ts +0 -15
- package/dist6/src/providers/send.js +0 -24
- package/dist6/src/providers/send.js.map +0 -1
- package/dist6/src/rest-component.d.ts +0 -12
- package/dist6/src/rest-component.js +0 -50
- package/dist6/src/rest-component.js.map +0 -1
- package/dist6/src/rest-server.d.ts +0 -211
- package/dist6/src/rest-server.js +0 -444
- package/dist6/src/rest-server.js.map +0 -1
- package/dist6/src/router/metadata.d.ts +0 -150
- package/dist6/src/router/metadata.js +0 -410
- package/dist6/src/router/metadata.js.map +0 -1
- package/dist6/src/router/routing-table.d.ts +0 -68
- package/dist6/src/router/routing-table.js +0 -218
- package/dist6/src/router/routing-table.js.map +0 -1
- package/dist6/src/sequence.js +0 -114
- package/dist6/src/sequence.js.map +0 -1
- package/dist6/src/writer.d.ts +0 -17
- package/dist6/src/writer.js +0 -87
- package/dist6/src/writer.js.map +0 -1
- package/index.d.ts +0 -6
- package/index.js +0 -9
- package/src/internal-types.ts +0 -96
- package/src/providers/bind-element.ts +0 -15
- package/src/providers/get-from-context.ts +0 -16
- package/src/providers/log-error-provider.ts +0 -23
- package/src/providers/parse-params.ts +0 -20
- package/src/providers/reject.ts +0 -27
- package/src/rest-component.ts +0 -54
- package/src/rest-server.ts +0 -584
- package/src/router/metadata.ts +0 -517
package/src/providers/reject.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
// Copyright IBM Corp. 2017. All Rights Reserved.
|
|
2
|
-
// Node module: loopback
|
|
3
|
-
// This file is licensed under the MIT License.
|
|
4
|
-
// License text available at https://opensource.org/licenses/MIT
|
|
5
|
-
|
|
6
|
-
import {LogError, Reject} from '../internal-types';
|
|
7
|
-
import {inject} from '@loopback/context';
|
|
8
|
-
import {ServerResponse, ServerRequest} from 'http';
|
|
9
|
-
import {HttpError} from 'http-errors';
|
|
10
|
-
import {writeErrorToResponse} from '../writer';
|
|
11
|
-
import {RestBindings} from '../keys';
|
|
12
|
-
|
|
13
|
-
export class RejectProvider {
|
|
14
|
-
constructor(
|
|
15
|
-
@inject(RestBindings.SequenceActions.LOG_ERROR)
|
|
16
|
-
protected logError: LogError,
|
|
17
|
-
) {}
|
|
18
|
-
|
|
19
|
-
value(): Reject {
|
|
20
|
-
return (response: ServerResponse, request: ServerRequest, error: Error) => {
|
|
21
|
-
const err = <HttpError>error;
|
|
22
|
-
const statusCode = err.statusCode || err.status || 500;
|
|
23
|
-
writeErrorToResponse(response, err);
|
|
24
|
-
this.logError(error, statusCode, request);
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
}
|
package/src/rest-component.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
// Copyright IBM Corp. 2017. All Rights Reserved.
|
|
2
|
-
// Node module: @loopback/rest
|
|
3
|
-
// This file is licensed under the MIT License.
|
|
4
|
-
// License text available at https://opensource.org/licenses/MIT
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
Component,
|
|
8
|
-
CoreBindings,
|
|
9
|
-
ProviderMap,
|
|
10
|
-
Server,
|
|
11
|
-
Application,
|
|
12
|
-
} from '@loopback/core';
|
|
13
|
-
import {inject, Constructor} from '@loopback/context';
|
|
14
|
-
import {RestBindings} from './keys';
|
|
15
|
-
import {LogErrorProvider} from './providers';
|
|
16
|
-
import {
|
|
17
|
-
BindElementProvider,
|
|
18
|
-
FindRouteProvider,
|
|
19
|
-
GetFromContextProvider,
|
|
20
|
-
InvokeMethodProvider,
|
|
21
|
-
RejectProvider,
|
|
22
|
-
ParseParamsProvider,
|
|
23
|
-
SendProvider,
|
|
24
|
-
} from './providers';
|
|
25
|
-
import {RestServer, RestServerConfig} from './rest-server';
|
|
26
|
-
|
|
27
|
-
export class RestComponent implements Component {
|
|
28
|
-
providers: ProviderMap = {
|
|
29
|
-
[RestBindings.SequenceActions.LOG_ERROR]: LogErrorProvider,
|
|
30
|
-
[RestBindings.SequenceActions.FIND_ROUTE]: FindRouteProvider,
|
|
31
|
-
[RestBindings.SequenceActions.INVOKE_METHOD]: InvokeMethodProvider,
|
|
32
|
-
[RestBindings.SequenceActions.REJECT]: RejectProvider,
|
|
33
|
-
[RestBindings.BIND_ELEMENT]: BindElementProvider,
|
|
34
|
-
[RestBindings.GET_FROM_CONTEXT]: GetFromContextProvider,
|
|
35
|
-
[RestBindings.SequenceActions.PARSE_PARAMS]: ParseParamsProvider,
|
|
36
|
-
[RestBindings.SequenceActions.SEND]: SendProvider,
|
|
37
|
-
};
|
|
38
|
-
servers: {
|
|
39
|
-
[name: string]: Constructor<Server>;
|
|
40
|
-
} = {
|
|
41
|
-
RestServer,
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
constructor(
|
|
45
|
-
@inject(CoreBindings.APPLICATION_INSTANCE) app: Application,
|
|
46
|
-
@inject(RestBindings.CONFIG) config?: RestComponentConfig,
|
|
47
|
-
) {
|
|
48
|
-
if (!config) config = {};
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export interface RestComponentConfig extends RestServerConfig {
|
|
53
|
-
// TODO(kevin): Extend this interface def to include multiple servers?
|
|
54
|
-
}
|
package/src/rest-server.ts
DELETED
|
@@ -1,584 +0,0 @@
|
|
|
1
|
-
// Copyright IBM Corp. 2017. All Rights Reserved.
|
|
2
|
-
// Node module: @loopback/rest
|
|
3
|
-
// This file is licensed under the MIT License.
|
|
4
|
-
// License text available at https://opensource.org/licenses/MIT
|
|
5
|
-
|
|
6
|
-
import {AssertionError} from 'assert';
|
|
7
|
-
const swagger2openapi = require('swagger2openapi');
|
|
8
|
-
import {safeDump} from 'js-yaml';
|
|
9
|
-
import {Binding, Context, Constructor, inject} from '@loopback/context';
|
|
10
|
-
import {Route, ControllerRoute, RouteEntry, ParsedRequest} from '.';
|
|
11
|
-
import {
|
|
12
|
-
OpenApiSpec,
|
|
13
|
-
createEmptyApiSpec,
|
|
14
|
-
OperationObject,
|
|
15
|
-
} from '@loopback/openapi-spec';
|
|
16
|
-
import {ServerRequest, ServerResponse, createServer} from 'http';
|
|
17
|
-
import * as Http from 'http';
|
|
18
|
-
import {Application, CoreBindings, Server} from '@loopback/core';
|
|
19
|
-
import {getControllerSpec} from './router/metadata';
|
|
20
|
-
import {HttpHandler} from './http-handler';
|
|
21
|
-
import {DefaultSequence, SequenceHandler, SequenceFunction} from './sequence';
|
|
22
|
-
import {
|
|
23
|
-
FindRoute,
|
|
24
|
-
InvokeMethod,
|
|
25
|
-
Send,
|
|
26
|
-
Reject,
|
|
27
|
-
ParseParams,
|
|
28
|
-
} from './internal-types';
|
|
29
|
-
import {ControllerClass} from './router/routing-table';
|
|
30
|
-
import {RestBindings} from './keys';
|
|
31
|
-
|
|
32
|
-
const SequenceActions = RestBindings.SequenceActions;
|
|
33
|
-
|
|
34
|
-
// NOTE(bajtos) we cannot use `import * as cloneDeep from 'lodash/cloneDeep'
|
|
35
|
-
// because it produces the following TypeScript error:
|
|
36
|
-
// Module '"(...)/node_modules/@types/lodash/cloneDeep/index"' resolves to
|
|
37
|
-
// a non-module entity and cannot be imported using this construct.
|
|
38
|
-
const cloneDeep: <T>(value: T) => T = require('lodash/cloneDeep');
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* The object format used for building the template bases of our OpenAPI spec
|
|
42
|
-
* files.
|
|
43
|
-
*
|
|
44
|
-
* @interface OpenApiSpecOptions
|
|
45
|
-
*/
|
|
46
|
-
interface OpenApiSpecOptions {
|
|
47
|
-
version?: string;
|
|
48
|
-
format?: string;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const OPENAPI_SPEC_MAPPING: {[key: string]: OpenApiSpecOptions} = {
|
|
52
|
-
'/openapi.json': {version: '3.0.0', format: 'json'},
|
|
53
|
-
'/openapi.yaml': {version: '3.0.0', format: 'yaml'},
|
|
54
|
-
'/swagger.json': {version: '2.0', format: 'json'},
|
|
55
|
-
'/swagger.yaml': {version: '2.0', format: 'yaml'},
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* A REST API server for use with Loopback.
|
|
60
|
-
* Add this server to your application by importing the RestComponent.
|
|
61
|
-
* ```ts
|
|
62
|
-
* const app = new MyApplication({
|
|
63
|
-
* components: [RestComponent]
|
|
64
|
-
* });
|
|
65
|
-
* // OR
|
|
66
|
-
* app.component(RestComponent);
|
|
67
|
-
* ```
|
|
68
|
-
*
|
|
69
|
-
* To add additional instances of RestServer to your application, use the
|
|
70
|
-
* `.server` function:
|
|
71
|
-
* ```ts
|
|
72
|
-
* app.server(RestServer, 'nameOfYourServer');
|
|
73
|
-
* ```
|
|
74
|
-
*
|
|
75
|
-
* By default, one instance of RestServer will be created when the RestComponent
|
|
76
|
-
* is bootstrapped. This instance can be retrieved with
|
|
77
|
-
* `app.getServer(RestServer)`, or by calling `app.get('servers.RestServer')`
|
|
78
|
-
* Note that retrieving other instances of RestServer must be done using the
|
|
79
|
-
* server's name:
|
|
80
|
-
* ```ts
|
|
81
|
-
* const server = await app.getServer('foo')
|
|
82
|
-
* // OR
|
|
83
|
-
* const server = await app.get('servers.foo');
|
|
84
|
-
* ```
|
|
85
|
-
*
|
|
86
|
-
* @export
|
|
87
|
-
* @class RestServer
|
|
88
|
-
* @extends {Context}
|
|
89
|
-
* @implements {Server}
|
|
90
|
-
*/
|
|
91
|
-
export class RestServer extends Context implements Server {
|
|
92
|
-
/**
|
|
93
|
-
* Handle incoming HTTP(S) request by invoking the corresponding
|
|
94
|
-
* Controller method via the configured Sequence.
|
|
95
|
-
*
|
|
96
|
-
* @example
|
|
97
|
-
*
|
|
98
|
-
* ```ts
|
|
99
|
-
* const app = new Application();
|
|
100
|
-
* // setup controllers, etc.
|
|
101
|
-
*
|
|
102
|
-
* const server = http.createServer(app.handleHttp);
|
|
103
|
-
* server.listen(3000);
|
|
104
|
-
* ```
|
|
105
|
-
*
|
|
106
|
-
* @param req The request.
|
|
107
|
-
* @param res The response.
|
|
108
|
-
*/
|
|
109
|
-
public handleHttp: (req: ServerRequest, res: ServerResponse) => void;
|
|
110
|
-
|
|
111
|
-
protected _httpHandler: HttpHandler;
|
|
112
|
-
protected get httpHandler(): HttpHandler {
|
|
113
|
-
this._setupHandlerIfNeeded();
|
|
114
|
-
return this._httpHandler;
|
|
115
|
-
}
|
|
116
|
-
protected _httpServer: Http.Server;
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* @memberof RestServer
|
|
120
|
-
* Creates an instance of RestServer.
|
|
121
|
-
*
|
|
122
|
-
* @param {Application} app The application instance (injected via
|
|
123
|
-
* CoreBindings.APPLICATION_INSTANCE).
|
|
124
|
-
* @param {RestServerConfig=} options The configuration options (injected via
|
|
125
|
-
* RestBindings.CONFIG).
|
|
126
|
-
*
|
|
127
|
-
*/
|
|
128
|
-
constructor(
|
|
129
|
-
@inject(CoreBindings.APPLICATION_INSTANCE) app: Application,
|
|
130
|
-
@inject(RestBindings.CONFIG) options?: RestServerConfig,
|
|
131
|
-
) {
|
|
132
|
-
super(app);
|
|
133
|
-
|
|
134
|
-
if (!options) options = {};
|
|
135
|
-
|
|
136
|
-
// Can't check falsiness, 0 is a valid port.
|
|
137
|
-
if (options.port === null || options.port === undefined) {
|
|
138
|
-
options.port = 3000;
|
|
139
|
-
}
|
|
140
|
-
this.bind(RestBindings.PORT).to(options.port);
|
|
141
|
-
this.api(createEmptyApiSpec());
|
|
142
|
-
|
|
143
|
-
this.sequence(options.sequence ? options.sequence : DefaultSequence);
|
|
144
|
-
|
|
145
|
-
this.handleHttp = (req: ServerRequest, res: ServerResponse) => {
|
|
146
|
-
try {
|
|
147
|
-
this._handleHttpRequest(req, res).catch(err =>
|
|
148
|
-
this._onUnhandledError(req, res, err),
|
|
149
|
-
);
|
|
150
|
-
} catch (err) {
|
|
151
|
-
this._onUnhandledError(req, res, err);
|
|
152
|
-
}
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
this.bind(RestBindings.HANDLER).toDynamicValue(() => this.httpHandler);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
protected _handleHttpRequest(
|
|
159
|
-
request: ServerRequest,
|
|
160
|
-
response: ServerResponse,
|
|
161
|
-
) {
|
|
162
|
-
// allow CORS support for all endpoints so that users
|
|
163
|
-
// can test with online SwaggerUI instance
|
|
164
|
-
response.setHeader('Access-Control-Allow-Origin', '*');
|
|
165
|
-
response.setHeader('Access-Control-Allow-Credentials', 'true');
|
|
166
|
-
response.setHeader('Access-Control-Allow-Max-Age', '86400');
|
|
167
|
-
|
|
168
|
-
if (
|
|
169
|
-
request.method === 'GET' &&
|
|
170
|
-
request.url &&
|
|
171
|
-
request.url in OPENAPI_SPEC_MAPPING
|
|
172
|
-
) {
|
|
173
|
-
// NOTE(bajtos) Regular routes are handled through Sequence.
|
|
174
|
-
// IMO, this built-in endpoint should not run through a Sequence,
|
|
175
|
-
// because it's not part of the application API itself.
|
|
176
|
-
// E.g. if the app implements access/audit logs, I don't want
|
|
177
|
-
// this endpoint to trigger a log entry. If the server implements
|
|
178
|
-
// content-negotiation to support XML clients, I don't want the OpenAPI
|
|
179
|
-
// spec to be converted into an XML response.
|
|
180
|
-
const options = OPENAPI_SPEC_MAPPING[request.url];
|
|
181
|
-
return this._serveOpenApiSpec(request, response, options);
|
|
182
|
-
}
|
|
183
|
-
if (
|
|
184
|
-
request.method === 'GET' &&
|
|
185
|
-
request.url &&
|
|
186
|
-
request.url === '/swagger-ui'
|
|
187
|
-
) {
|
|
188
|
-
return this._redirectToSwaggerUI(request, response);
|
|
189
|
-
}
|
|
190
|
-
return this.httpHandler.handleRequest(request, response);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
protected _setupHandlerIfNeeded() {
|
|
194
|
-
// TODO(bajtos) support hot-reloading of controllers
|
|
195
|
-
// after the app started. The idea is to rebuild the HttpHandler
|
|
196
|
-
// instance whenever a controller was added/deleted.
|
|
197
|
-
// See https://github.com/strongloop/loopback-next/issues/433
|
|
198
|
-
if (this._httpHandler) return;
|
|
199
|
-
|
|
200
|
-
this._httpHandler = new HttpHandler(this);
|
|
201
|
-
for (const b of this.find('controllers.*')) {
|
|
202
|
-
const controllerName = b.key.replace(/^controllers\./, '');
|
|
203
|
-
const ctor = b.valueConstructor;
|
|
204
|
-
if (!ctor) {
|
|
205
|
-
throw new Error(
|
|
206
|
-
`The controller ${controllerName} was not bound via .toClass()`,
|
|
207
|
-
);
|
|
208
|
-
}
|
|
209
|
-
const apiSpec = getControllerSpec(ctor);
|
|
210
|
-
if (!apiSpec) {
|
|
211
|
-
// controller methods are specified through app.api() spec
|
|
212
|
-
continue;
|
|
213
|
-
}
|
|
214
|
-
this._httpHandler.registerController(ctor, apiSpec);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
for (const b of this.find('routes.*')) {
|
|
218
|
-
// TODO(bajtos) should we support routes defined asynchronously?
|
|
219
|
-
const route = this.getSync(b.key);
|
|
220
|
-
this._httpHandler.registerRoute(route);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// TODO(bajtos) should we support API spec defined asynchronously?
|
|
224
|
-
const spec: OpenApiSpec = this.getSync(RestBindings.API_SPEC);
|
|
225
|
-
for (const path in spec.paths) {
|
|
226
|
-
for (const verb in spec.paths[path]) {
|
|
227
|
-
const routeSpec: OperationObject = spec.paths[path][verb];
|
|
228
|
-
this._setupOperation(verb, path, routeSpec);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
private _setupOperation(verb: string, path: string, spec: OperationObject) {
|
|
234
|
-
const handler = spec['x-operation'];
|
|
235
|
-
if (typeof handler === 'function') {
|
|
236
|
-
// Remove a field value that cannot be represented in JSON.
|
|
237
|
-
// Start by creating a shallow-copy of the spec, so that we don't
|
|
238
|
-
// modify the original spec object provided by user.
|
|
239
|
-
spec = Object.assign({}, spec);
|
|
240
|
-
delete spec['x-operation'];
|
|
241
|
-
|
|
242
|
-
const route = new Route(verb, path, spec, handler);
|
|
243
|
-
this._httpHandler.registerRoute(route);
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
const controllerName = spec['x-controller-name'];
|
|
248
|
-
if (typeof controllerName === 'string') {
|
|
249
|
-
const b = this.find(`controllers.${controllerName}`)[0];
|
|
250
|
-
if (!b) {
|
|
251
|
-
throw new Error(
|
|
252
|
-
`Unknown controller ${controllerName} used by "${verb} ${path}"`,
|
|
253
|
-
);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
const ctor = b.valueConstructor;
|
|
257
|
-
if (!ctor) {
|
|
258
|
-
throw new Error(
|
|
259
|
-
`The controller ${controllerName} was not bound via .toClass()`,
|
|
260
|
-
);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
const route = new ControllerRoute(verb, path, spec, ctor);
|
|
264
|
-
this._httpHandler.registerRoute(route);
|
|
265
|
-
return;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
throw new Error(
|
|
269
|
-
`There is no handler configured for operation "${verb} ${path}`,
|
|
270
|
-
);
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
private async _serveOpenApiSpec(
|
|
274
|
-
request: ServerRequest,
|
|
275
|
-
response: ServerResponse,
|
|
276
|
-
options?: OpenApiSpecOptions,
|
|
277
|
-
) {
|
|
278
|
-
options = options || {version: '2.0', format: 'json'};
|
|
279
|
-
let specObj = this.getApiSpec();
|
|
280
|
-
if (options.version === '3.0.0') {
|
|
281
|
-
specObj = await swagger2openapi.convertObj(specObj, {direct: true});
|
|
282
|
-
}
|
|
283
|
-
if (options.format === 'json') {
|
|
284
|
-
const spec = JSON.stringify(specObj, null, 2);
|
|
285
|
-
response.setHeader('content-type', 'application/json; charset=utf-8');
|
|
286
|
-
response.end(spec, 'utf-8');
|
|
287
|
-
} else {
|
|
288
|
-
const yaml = safeDump(specObj, {});
|
|
289
|
-
response.setHeader('content-type', 'text/yaml; charset=utf-8');
|
|
290
|
-
response.end(yaml, 'utf-8');
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
private async _redirectToSwaggerUI(
|
|
295
|
-
request: ServerRequest,
|
|
296
|
-
response: ServerResponse,
|
|
297
|
-
) {
|
|
298
|
-
response.statusCode = 308;
|
|
299
|
-
response.setHeader(
|
|
300
|
-
'Location',
|
|
301
|
-
'http://petstore.swagger.io/?url=' +
|
|
302
|
-
'http://' +
|
|
303
|
-
request.headers.host +
|
|
304
|
-
'/swagger.json',
|
|
305
|
-
);
|
|
306
|
-
response.end();
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
/**
|
|
310
|
-
* Register a controller class with this server.
|
|
311
|
-
*
|
|
312
|
-
* @param {Constructor} controllerCtor The controller class
|
|
313
|
-
* (constructor function).
|
|
314
|
-
* @returns {Binding} The newly created binding, you can use the reference to
|
|
315
|
-
* further modify the binding, e.g. lock the value to prevent further
|
|
316
|
-
* modifications.
|
|
317
|
-
*
|
|
318
|
-
* ```ts
|
|
319
|
-
* class MyController {
|
|
320
|
-
* }
|
|
321
|
-
* app.controller(MyController).lock();
|
|
322
|
-
* ```
|
|
323
|
-
*
|
|
324
|
-
*/
|
|
325
|
-
controller(controllerCtor: ControllerClass): Binding {
|
|
326
|
-
return this.bind('controllers.' + controllerCtor.name).toClass(
|
|
327
|
-
controllerCtor,
|
|
328
|
-
);
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
/**
|
|
332
|
-
* Register a new Controller-based route.
|
|
333
|
-
*
|
|
334
|
-
* ```ts
|
|
335
|
-
* class MyController {
|
|
336
|
-
* greet(name: string) {
|
|
337
|
-
* return `hello ${name}`;
|
|
338
|
-
* }
|
|
339
|
-
* }
|
|
340
|
-
* app.route('get', '/greet', operationSpec, MyController, 'greet');
|
|
341
|
-
* ```
|
|
342
|
-
*
|
|
343
|
-
* @param verb HTTP verb of the endpoint
|
|
344
|
-
* @param path URL path of the endpoint
|
|
345
|
-
* @param spec The OpenAPI spec describing the endpoint (operation)
|
|
346
|
-
* @param controller Controller constructor
|
|
347
|
-
* @param methodName The name of the controller method
|
|
348
|
-
*/
|
|
349
|
-
route(
|
|
350
|
-
verb: string,
|
|
351
|
-
path: string,
|
|
352
|
-
spec: OperationObject,
|
|
353
|
-
controller: ControllerClass,
|
|
354
|
-
methodName: string,
|
|
355
|
-
): Binding;
|
|
356
|
-
|
|
357
|
-
/**
|
|
358
|
-
* Register a new route.
|
|
359
|
-
*
|
|
360
|
-
* ```ts
|
|
361
|
-
* function greet(name: string) {
|
|
362
|
-
* return `hello ${name}`;
|
|
363
|
-
* }
|
|
364
|
-
* const route = new Route('get', '/', operationSpec, greet);
|
|
365
|
-
* app.route(route);
|
|
366
|
-
* ```
|
|
367
|
-
*
|
|
368
|
-
* @param route The route to add.
|
|
369
|
-
*/
|
|
370
|
-
route(route: RouteEntry): Binding;
|
|
371
|
-
|
|
372
|
-
route(
|
|
373
|
-
routeOrVerb: RouteEntry | string,
|
|
374
|
-
path?: string,
|
|
375
|
-
spec?: OperationObject,
|
|
376
|
-
controller?: ControllerClass,
|
|
377
|
-
methodName?: string,
|
|
378
|
-
): Binding {
|
|
379
|
-
if (typeof routeOrVerb === 'object') {
|
|
380
|
-
const r = routeOrVerb;
|
|
381
|
-
return this.bind(`routes.${r.verb} ${r.path}`).to(r);
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
if (!path) {
|
|
385
|
-
throw new AssertionError({
|
|
386
|
-
message: 'path is required for a controller-based route',
|
|
387
|
-
});
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
if (!spec) {
|
|
391
|
-
throw new AssertionError({
|
|
392
|
-
message: 'spec is required for a controller-based route',
|
|
393
|
-
});
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
if (!controller) {
|
|
397
|
-
throw new AssertionError({
|
|
398
|
-
message: 'controller is required for a controller-based route',
|
|
399
|
-
});
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
if (!methodName) {
|
|
403
|
-
throw new AssertionError({
|
|
404
|
-
message: 'methodName is required for a controller-based route',
|
|
405
|
-
});
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
return this.route(
|
|
409
|
-
new ControllerRoute(routeOrVerb, path, spec, controller, methodName),
|
|
410
|
-
);
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
/**
|
|
414
|
-
* Set the OpenAPI specification that defines the REST API schema for this
|
|
415
|
-
* server. All routes, parameter definitions and return types will be defined
|
|
416
|
-
* in this way.
|
|
417
|
-
*
|
|
418
|
-
* Note that this will override any routes defined via decorators at the
|
|
419
|
-
* controller level (this function takes precedent).
|
|
420
|
-
*
|
|
421
|
-
* @param {OpenApiSpec} spec The OpenAPI specification, as an object.
|
|
422
|
-
* @returns {Binding}
|
|
423
|
-
* @memberof RestServer
|
|
424
|
-
*/
|
|
425
|
-
api(spec: OpenApiSpec): Binding {
|
|
426
|
-
return this.bind(RestBindings.API_SPEC).to(spec);
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
/**
|
|
430
|
-
* Get the OpenAPI specification describing the REST API provided by
|
|
431
|
-
* this application.
|
|
432
|
-
*
|
|
433
|
-
* This method merges operations (HTTP endpoints) from the following sources:
|
|
434
|
-
* - `app.api(spec)`
|
|
435
|
-
* - `app.controller(MyController)`
|
|
436
|
-
* - `app.route(route)`
|
|
437
|
-
* - `app.route('get', '/greet', operationSpec, MyController, 'greet')`
|
|
438
|
-
*/
|
|
439
|
-
getApiSpec(): OpenApiSpec {
|
|
440
|
-
const spec = this.getSync(RestBindings.API_SPEC);
|
|
441
|
-
|
|
442
|
-
// Apply deep clone to prevent getApiSpec() callers from
|
|
443
|
-
// accidentally modifying our internal routing data
|
|
444
|
-
spec.paths = cloneDeep(this.httpHandler.describeApiPaths());
|
|
445
|
-
|
|
446
|
-
return spec;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
/**
|
|
450
|
-
* Configure a custom sequence class for handling incoming requests.
|
|
451
|
-
*
|
|
452
|
-
* ```ts
|
|
453
|
-
* class MySequence implements SequenceHandler {
|
|
454
|
-
* constructor(
|
|
455
|
-
* @inject('send) public send: Send)) {
|
|
456
|
-
* }
|
|
457
|
-
*
|
|
458
|
-
* public async handle(request: ParsedRequest, response: ServerResponse) {
|
|
459
|
-
* send(response, 'hello world');
|
|
460
|
-
* }
|
|
461
|
-
* }
|
|
462
|
-
* ```
|
|
463
|
-
*
|
|
464
|
-
* @param value The sequence to invoke for each incoming request.
|
|
465
|
-
*/
|
|
466
|
-
public sequence(value: Constructor<SequenceHandler>) {
|
|
467
|
-
this.bind(RestBindings.SEQUENCE).toClass(value);
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
/**
|
|
471
|
-
* Configure a custom sequence function for handling incoming requests.
|
|
472
|
-
*
|
|
473
|
-
* ```ts
|
|
474
|
-
* app.handler((sequence, request, response) => {
|
|
475
|
-
* sequence.send(response, 'hello world');
|
|
476
|
-
* });
|
|
477
|
-
* ```
|
|
478
|
-
*
|
|
479
|
-
* @param handlerFn The handler to invoke for each incoming request.
|
|
480
|
-
*/
|
|
481
|
-
public handler(handlerFn: SequenceFunction) {
|
|
482
|
-
class SequenceFromFunction extends DefaultSequence {
|
|
483
|
-
// NOTE(bajtos) Unfortunately, we have to duplicate the constructor
|
|
484
|
-
// in order for our DI/IoC framework to inject constructor arguments
|
|
485
|
-
constructor(
|
|
486
|
-
@inject(RestBindings.Http.CONTEXT) public ctx: Context,
|
|
487
|
-
@inject(SequenceActions.FIND_ROUTE) protected findRoute: FindRoute,
|
|
488
|
-
@inject(SequenceActions.PARSE_PARAMS)
|
|
489
|
-
protected parseParams: ParseParams,
|
|
490
|
-
@inject(SequenceActions.INVOKE_METHOD) protected invoke: InvokeMethod,
|
|
491
|
-
@inject(SequenceActions.SEND) public send: Send,
|
|
492
|
-
@inject(SequenceActions.REJECT) public reject: Reject,
|
|
493
|
-
) {
|
|
494
|
-
super(ctx, findRoute, parseParams, invoke, send, reject);
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
async handle(
|
|
498
|
-
request: ParsedRequest,
|
|
499
|
-
response: ServerResponse,
|
|
500
|
-
): Promise<void> {
|
|
501
|
-
await Promise.resolve(handlerFn(this, request, response));
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
this.sequence(SequenceFromFunction);
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
/**
|
|
509
|
-
* Start this REST API's HTTP/HTTPS server.
|
|
510
|
-
*
|
|
511
|
-
* @returns {Promise<void>}
|
|
512
|
-
* @memberof RestServer
|
|
513
|
-
*/
|
|
514
|
-
async start(): Promise<void> {
|
|
515
|
-
// Setup the HTTP handler so that we can verify the configuration
|
|
516
|
-
// of API spec, controllers and routes at startup time.
|
|
517
|
-
this._setupHandlerIfNeeded();
|
|
518
|
-
|
|
519
|
-
const httpPort = await this.get(RestBindings.PORT);
|
|
520
|
-
this._httpServer = createServer(this.handleHttp);
|
|
521
|
-
const httpServer = this._httpServer;
|
|
522
|
-
|
|
523
|
-
// TODO(bajtos) support httpHostname too
|
|
524
|
-
// See https://github.com/strongloop/loopback-next/issues/434
|
|
525
|
-
httpServer.listen(httpPort);
|
|
526
|
-
|
|
527
|
-
return new Promise<void>((resolve, reject) => {
|
|
528
|
-
httpServer.once('listening', () => {
|
|
529
|
-
this.bind(RestBindings.PORT).to(httpServer.address().port);
|
|
530
|
-
resolve();
|
|
531
|
-
});
|
|
532
|
-
httpServer.once('error', reject);
|
|
533
|
-
});
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
/**
|
|
537
|
-
* Stop this REST API's HTTP/HTTPS server.
|
|
538
|
-
*
|
|
539
|
-
* @returns {Promise<void>}
|
|
540
|
-
* @memberof RestServer
|
|
541
|
-
*/
|
|
542
|
-
async stop() {
|
|
543
|
-
// Kill the server instance.
|
|
544
|
-
const server = this._httpServer;
|
|
545
|
-
return new Promise<void>((resolve, reject) => {
|
|
546
|
-
server.close((err: Error) => {
|
|
547
|
-
if (err) {
|
|
548
|
-
reject(err);
|
|
549
|
-
} else {
|
|
550
|
-
resolve();
|
|
551
|
-
}
|
|
552
|
-
});
|
|
553
|
-
});
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
protected _onUnhandledError(
|
|
557
|
-
req: ServerRequest,
|
|
558
|
-
res: ServerResponse,
|
|
559
|
-
err: Error,
|
|
560
|
-
) {
|
|
561
|
-
if (!res.headersSent) {
|
|
562
|
-
res.statusCode = 500;
|
|
563
|
-
res.end();
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
// It's the responsibility of the Sequence to handle any errors.
|
|
567
|
-
// If an unhandled error escaped, then something very wrong happened
|
|
568
|
-
// and it's best to crash the process immediately.
|
|
569
|
-
process.nextTick(() => {
|
|
570
|
-
throw err;
|
|
571
|
-
});
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
/**
|
|
576
|
-
* Valid configuration for the RestServer constructor.
|
|
577
|
-
*
|
|
578
|
-
* @export
|
|
579
|
-
* @interface RestServerConfig
|
|
580
|
-
*/
|
|
581
|
-
export interface RestServerConfig {
|
|
582
|
-
port?: number;
|
|
583
|
-
sequence?: Constructor<SequenceHandler>;
|
|
584
|
-
}
|