@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/parser.ts
CHANGED
|
@@ -1,135 +1,120 @@
|
|
|
1
|
-
// Copyright IBM Corp. 2017. All Rights Reserved.
|
|
1
|
+
// Copyright IBM Corp. 2017,2020. All Rights Reserved.
|
|
2
2
|
// Node module: @loopback/rest
|
|
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 {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
import {
|
|
7
|
+
isReferenceObject,
|
|
8
|
+
OperationObject,
|
|
9
|
+
ParameterObject,
|
|
10
|
+
REQUEST_BODY_INDEX,
|
|
11
|
+
SchemasObject,
|
|
12
|
+
} from '@loopback/openapi-v3';
|
|
13
|
+
import debugFactory from 'debug';
|
|
14
|
+
import {RequestBody, RequestBodyParser} from './body-parsers';
|
|
15
|
+
import {coerceParameter} from './coercion/coerce-parameter';
|
|
16
|
+
import {RestHttpErrors} from './rest-http-error';
|
|
17
|
+
import {ResolvedRoute} from './router';
|
|
10
18
|
import {
|
|
11
19
|
OperationArgs,
|
|
12
|
-
ParsedRequest,
|
|
13
20
|
PathParameterValues,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
req: ServerRequest,
|
|
20
|
-
cb: (err?: Error, body?: {}) => void,
|
|
21
|
-
) => void;
|
|
22
|
-
const jsonBody: jsonBodyFn = require('body/json');
|
|
23
|
-
|
|
24
|
-
// tslint:disable:no-any
|
|
25
|
-
type MaybeBody = any | undefined;
|
|
26
|
-
// tslint:enable:no-any
|
|
27
|
-
|
|
28
|
-
const parseJsonBody: (req: ServerRequest) => Promise<MaybeBody> = promisify(
|
|
29
|
-
jsonBody,
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Get the content-type header value from the request
|
|
34
|
-
* @param req Http request
|
|
35
|
-
*/
|
|
36
|
-
function getContentType(req: ServerRequest): string | undefined {
|
|
37
|
-
const val = req.headers['content-type'];
|
|
38
|
-
if (typeof val === 'string') {
|
|
39
|
-
return val;
|
|
40
|
-
} else if (Array.isArray(val)) {
|
|
41
|
-
// Assume only one value is present
|
|
42
|
-
return val[0];
|
|
43
|
-
}
|
|
44
|
-
return undefined;
|
|
45
|
-
}
|
|
21
|
+
Request,
|
|
22
|
+
RequestBodyValidationOptions,
|
|
23
|
+
} from './types';
|
|
24
|
+
import {validateRequestBody} from './validation/request-body.validator';
|
|
25
|
+
const debug = debugFactory('loopback:rest:parser');
|
|
46
26
|
|
|
47
27
|
/**
|
|
48
28
|
* Parses the request to derive arguments to be passed in for the Application
|
|
49
29
|
* controller method
|
|
50
30
|
*
|
|
51
|
-
* @param request Incoming HTTP request
|
|
52
|
-
* @param
|
|
53
|
-
* @param pathParams Path parameters in incoming HTTP request
|
|
31
|
+
* @param request - Incoming HTTP request
|
|
32
|
+
* @param route - Resolved Route
|
|
54
33
|
*/
|
|
55
34
|
export async function parseOperationArgs(
|
|
56
|
-
request:
|
|
35
|
+
request: Request,
|
|
57
36
|
route: ResolvedRoute,
|
|
37
|
+
requestBodyParser: RequestBodyParser = new RequestBodyParser(),
|
|
38
|
+
options: RequestBodyValidationOptions = {},
|
|
58
39
|
): Promise<OperationArgs> {
|
|
40
|
+
debug('Parsing operation arguments for route %s', route.describe());
|
|
59
41
|
const operationSpec = route.spec;
|
|
60
42
|
const pathParams = route.pathParams;
|
|
61
|
-
const body = await loadRequestBodyIfNeeded(
|
|
62
|
-
|
|
43
|
+
const body = await requestBodyParser.loadRequestBodyIfNeeded(
|
|
44
|
+
operationSpec,
|
|
45
|
+
request,
|
|
46
|
+
);
|
|
47
|
+
return buildOperationArguments(
|
|
48
|
+
operationSpec,
|
|
49
|
+
request,
|
|
50
|
+
pathParams,
|
|
51
|
+
body,
|
|
52
|
+
route.schemas,
|
|
53
|
+
options,
|
|
54
|
+
);
|
|
63
55
|
}
|
|
64
56
|
|
|
65
|
-
function
|
|
57
|
+
async function buildOperationArguments(
|
|
66
58
|
operationSpec: OperationObject,
|
|
67
|
-
request:
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function hasArgumentsFromBody(operationSpec: OperationObject): boolean {
|
|
86
|
-
if (!operationSpec.parameters || !operationSpec.parameters.length)
|
|
87
|
-
return false;
|
|
88
|
-
|
|
89
|
-
for (const paramSpec of operationSpec.parameters) {
|
|
90
|
-
if ('$ref' in paramSpec) continue;
|
|
91
|
-
const source = (paramSpec as ParameterObject).in;
|
|
92
|
-
if (source === 'formData' || source === 'body') return true;
|
|
59
|
+
request: Request,
|
|
60
|
+
pathParams: PathParameterValues,
|
|
61
|
+
body: RequestBody,
|
|
62
|
+
globalSchemas: SchemasObject,
|
|
63
|
+
options: RequestBodyValidationOptions = {},
|
|
64
|
+
): Promise<OperationArgs> {
|
|
65
|
+
let requestBodyIndex = -1;
|
|
66
|
+
if (operationSpec.requestBody) {
|
|
67
|
+
// the type of `operationSpec.requestBody` could be `RequestBodyObject`
|
|
68
|
+
// or `ReferenceObject`, resolving a `$ref` value is not supported yet.
|
|
69
|
+
if (isReferenceObject(operationSpec.requestBody)) {
|
|
70
|
+
throw new Error('$ref requestBody is not supported yet.');
|
|
71
|
+
}
|
|
72
|
+
const i = operationSpec.requestBody[REQUEST_BODY_INDEX];
|
|
73
|
+
requestBodyIndex = i ? i : 0;
|
|
93
74
|
}
|
|
94
|
-
return false;
|
|
95
|
-
}
|
|
96
75
|
|
|
97
|
-
|
|
98
|
-
operationSpec: OperationObject,
|
|
99
|
-
request: ParsedRequest,
|
|
100
|
-
pathParams: PathParameterValues,
|
|
101
|
-
body?: MaybeBody,
|
|
102
|
-
): OperationArgs {
|
|
103
|
-
const args: OperationArgs = [];
|
|
76
|
+
const paramArgs: OperationArgs = [];
|
|
104
77
|
|
|
105
|
-
for (const paramSpec of operationSpec.parameters
|
|
106
|
-
if (
|
|
78
|
+
for (const paramSpec of operationSpec.parameters ?? []) {
|
|
79
|
+
if (isReferenceObject(paramSpec)) {
|
|
107
80
|
// TODO(bajtos) implement $ref parameters
|
|
108
81
|
// See https://github.com/strongloop/loopback-next/issues/435
|
|
109
82
|
throw new Error('$ref parameters are not supported yet.');
|
|
110
83
|
}
|
|
111
84
|
const spec = paramSpec as ParameterObject;
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
85
|
+
const rawValue = getParamFromRequest(spec, request, pathParams);
|
|
86
|
+
const coercedValue = coerceParameter(rawValue, spec);
|
|
87
|
+
paramArgs.push(coercedValue);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
debug('Validating request body - value %j', body);
|
|
91
|
+
await validateRequestBody(
|
|
92
|
+
body,
|
|
93
|
+
operationSpec.requestBody,
|
|
94
|
+
globalSchemas,
|
|
95
|
+
options,
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
if (requestBodyIndex > -1) paramArgs.splice(requestBodyIndex, 0, body.value);
|
|
99
|
+
return paramArgs;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function getParamFromRequest(
|
|
103
|
+
spec: ParameterObject,
|
|
104
|
+
request: Request,
|
|
105
|
+
pathParams: PathParameterValues,
|
|
106
|
+
) {
|
|
107
|
+
switch (spec.in) {
|
|
108
|
+
case 'query':
|
|
109
|
+
return request.query[spec.name];
|
|
110
|
+
case 'path':
|
|
111
|
+
return pathParams[spec.name];
|
|
112
|
+
case 'header':
|
|
113
|
+
// @jannyhou TBD: check edge cases
|
|
114
|
+
return request.headers[spec.name.toLowerCase()];
|
|
115
|
+
// TODO(jannyhou) to support `cookie`,
|
|
116
|
+
// see issue https://github.com/strongloop/loopback-next/issues/997
|
|
117
|
+
default:
|
|
118
|
+
throw RestHttpErrors.invalidParamLocation(spec.in);
|
|
133
119
|
}
|
|
134
|
-
return args;
|
|
135
120
|
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
// Copyright IBM Corp.
|
|
1
|
+
// Copyright IBM Corp. 2018,2020. All Rights Reserved.
|
|
2
2
|
// Node module: @loopback/rest
|
|
3
3
|
// This file is licensed under the MIT License.
|
|
4
4
|
// License text available at https://opensource.org/licenses/MIT
|
|
5
5
|
|
|
6
6
|
import {Context, inject, Provider} from '@loopback/context';
|
|
7
|
-
import {FindRoute} from '../
|
|
7
|
+
import {FindRoute, Request} from '../types';
|
|
8
8
|
import {HttpHandler} from '../http-handler';
|
|
9
9
|
import {RestBindings} from '../keys';
|
|
10
|
+
import {ResolvedRoute} from '../router';
|
|
10
11
|
|
|
11
12
|
export class FindRouteProvider implements Provider<FindRoute> {
|
|
12
13
|
constructor(
|
|
@@ -15,10 +16,12 @@ export class FindRouteProvider implements Provider<FindRoute> {
|
|
|
15
16
|
) {}
|
|
16
17
|
|
|
17
18
|
value(): FindRoute {
|
|
18
|
-
return request =>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
return request => this.action(request);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
action(request: Request): ResolvedRoute {
|
|
23
|
+
const found = this.handler.findRoute(request);
|
|
24
|
+
found.updateBindings(this.context);
|
|
25
|
+
return found;
|
|
23
26
|
}
|
|
24
27
|
}
|
package/src/providers/index.ts
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
// Copyright IBM Corp.
|
|
1
|
+
// Copyright IBM Corp. 2017,2020. All Rights Reserved.
|
|
2
2
|
// Node module: @loopback/rest
|
|
3
3
|
// This file is licensed under the MIT License.
|
|
4
4
|
// License text available at https://opensource.org/licenses/MIT
|
|
5
5
|
|
|
6
|
-
export * from './
|
|
7
|
-
export * from './
|
|
8
|
-
export * from './
|
|
9
|
-
export * from './
|
|
10
|
-
export * from './
|
|
11
|
-
export * from './
|
|
12
|
-
export * from './parse-params';
|
|
13
|
-
export * from './send';
|
|
6
|
+
export * from './find-route.provider';
|
|
7
|
+
export * from './invoke-method.provider';
|
|
8
|
+
export * from './log-error.provider';
|
|
9
|
+
export * from './parse-params.provider';
|
|
10
|
+
export * from './reject.provider';
|
|
11
|
+
export * from './send.provider';
|
|
@@ -1,18 +1,21 @@
|
|
|
1
|
-
// Copyright IBM Corp.
|
|
1
|
+
// Copyright IBM Corp. 2018,2020. All Rights Reserved.
|
|
2
2
|
// Node module: @loopback/rest
|
|
3
3
|
// This file is licensed under the MIT License.
|
|
4
4
|
// License text available at https://opensource.org/licenses/MIT
|
|
5
5
|
|
|
6
6
|
import {Context, inject, Provider} from '@loopback/context';
|
|
7
|
-
import {InvokeMethod} from '../
|
|
7
|
+
import {InvokeMethod, OperationArgs, OperationRetval} from '../types';
|
|
8
8
|
import {RestBindings} from '../keys';
|
|
9
|
+
import {RouteEntry} from '../router';
|
|
9
10
|
|
|
10
11
|
export class InvokeMethodProvider implements Provider<InvokeMethod> {
|
|
11
12
|
constructor(@inject(RestBindings.Http.CONTEXT) protected context: Context) {}
|
|
12
13
|
|
|
13
14
|
value(): InvokeMethod {
|
|
14
|
-
return
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
return (route, args) => this.action(route, args);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
action(route: RouteEntry, args: OperationArgs): Promise<OperationRetval> {
|
|
19
|
+
return route.invokeHandler(this.context, args);
|
|
17
20
|
}
|
|
18
21
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Copyright IBM Corp. 2018,2020. 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 {Provider} from '@loopback/context';
|
|
7
|
+
import {LogError, Request} from '../types';
|
|
8
|
+
|
|
9
|
+
export class LogErrorProvider implements Provider<LogError> {
|
|
10
|
+
value(): LogError {
|
|
11
|
+
return (err, statusCode, req) => this.action(err, statusCode, req);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
action(err: Error, statusCode: number, req: Request) {
|
|
15
|
+
if (statusCode < 500) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
console.error(
|
|
20
|
+
'Unhandled error in %s %s: %s %s',
|
|
21
|
+
req.method,
|
|
22
|
+
req.url,
|
|
23
|
+
statusCode,
|
|
24
|
+
err.stack ?? err,
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Copyright IBM Corp. 2018,2020. 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 {inject, Provider} from '@loopback/context';
|
|
7
|
+
import {RequestBodyParser} from '../body-parsers';
|
|
8
|
+
import {RestBindings} from '../keys';
|
|
9
|
+
import {parseOperationArgs} from '../parser';
|
|
10
|
+
import {ResolvedRoute} from '../router';
|
|
11
|
+
import {
|
|
12
|
+
AjvFactory,
|
|
13
|
+
ParseParams,
|
|
14
|
+
Request,
|
|
15
|
+
RequestBodyValidationOptions,
|
|
16
|
+
} from '../types';
|
|
17
|
+
/**
|
|
18
|
+
* Provides the function for parsing args in requests at runtime.
|
|
19
|
+
*
|
|
20
|
+
* @returns The handler function that will parse request args.
|
|
21
|
+
*/
|
|
22
|
+
export class ParseParamsProvider implements Provider<ParseParams> {
|
|
23
|
+
constructor(
|
|
24
|
+
@inject(RestBindings.REQUEST_BODY_PARSER)
|
|
25
|
+
private requestBodyParser: RequestBodyParser,
|
|
26
|
+
@inject(
|
|
27
|
+
RestBindings.REQUEST_BODY_PARSER_OPTIONS.deepProperty('validation'),
|
|
28
|
+
{optional: true},
|
|
29
|
+
)
|
|
30
|
+
private validationOptions: RequestBodyValidationOptions = {},
|
|
31
|
+
@inject(RestBindings.AJV_FACTORY, {optional: true})
|
|
32
|
+
private ajvFactory?: AjvFactory,
|
|
33
|
+
) {}
|
|
34
|
+
|
|
35
|
+
value(): ParseParams {
|
|
36
|
+
return (request: Request, route: ResolvedRoute) =>
|
|
37
|
+
parseOperationArgs(request, route, this.requestBodyParser, {
|
|
38
|
+
ajvFactory: this.ajvFactory,
|
|
39
|
+
...this.validationOptions,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Copyright IBM Corp. 2018,2020. 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 {LogError, Reject, HandlerContext} from '../types';
|
|
7
|
+
import {inject, Provider} from '@loopback/context';
|
|
8
|
+
import {HttpError} from 'http-errors';
|
|
9
|
+
import {RestBindings} from '../keys';
|
|
10
|
+
import {writeErrorToResponse, ErrorWriterOptions} from 'strong-error-handler';
|
|
11
|
+
|
|
12
|
+
// TODO(bajtos) Make this mapping configurable at RestServer level,
|
|
13
|
+
// allow apps and extensions to contribute additional mappings.
|
|
14
|
+
const codeToStatusCodeMap: {[key: string]: number} = {
|
|
15
|
+
ENTITY_NOT_FOUND: 404,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export class RejectProvider implements Provider<Reject> {
|
|
19
|
+
constructor(
|
|
20
|
+
@inject(RestBindings.SequenceActions.LOG_ERROR)
|
|
21
|
+
protected logError: LogError,
|
|
22
|
+
@inject(RestBindings.ERROR_WRITER_OPTIONS, {optional: true})
|
|
23
|
+
protected errorWriterOptions?: ErrorWriterOptions,
|
|
24
|
+
) {}
|
|
25
|
+
|
|
26
|
+
value(): Reject {
|
|
27
|
+
return (context, error) => this.action(context, error);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
action({request, response}: HandlerContext, error: Error) {
|
|
31
|
+
const err = <HttpError>error;
|
|
32
|
+
|
|
33
|
+
if (!err.status && !err.statusCode && err.code) {
|
|
34
|
+
const customStatus = codeToStatusCodeMap[err.code];
|
|
35
|
+
if (customStatus) {
|
|
36
|
+
err.statusCode = customStatus;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const statusCode = err.statusCode || err.status || 500;
|
|
41
|
+
writeErrorToResponse(err, request, response, this.errorWriterOptions);
|
|
42
|
+
this.logError(error, statusCode, request);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright IBM Corp.
|
|
1
|
+
// Copyright IBM Corp. 2018,2020. All Rights Reserved.
|
|
2
2
|
// Node module: @loopback/rest
|
|
3
3
|
// This file is licensed under the MIT License.
|
|
4
4
|
// License text available at https://opensource.org/licenses/MIT
|
|
@@ -9,10 +9,7 @@ import {writeResultToResponse} from '../writer';
|
|
|
9
9
|
* Provides the function that populates the response object with
|
|
10
10
|
* the results of the operation.
|
|
11
11
|
*
|
|
12
|
-
* @
|
|
13
|
-
* @class SendProvider
|
|
14
|
-
* @implements {Provider<BoundValue>}
|
|
15
|
-
* @returns {BoundValue} The handler function that will populate the
|
|
12
|
+
* @returns The handler function that will populate the
|
|
16
13
|
* response with operation results.
|
|
17
14
|
*/
|
|
18
15
|
export class SendProvider implements Provider<BoundValue> {
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// Copyright IBM Corp. 2018,2020. 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 {Context} from '@loopback/context';
|
|
7
|
+
import {
|
|
8
|
+
HandlerContext,
|
|
9
|
+
MiddlewareContext,
|
|
10
|
+
Request,
|
|
11
|
+
Response,
|
|
12
|
+
} from '@loopback/express';
|
|
13
|
+
import {RestBindings} from './keys';
|
|
14
|
+
import {RestServerResolvedConfig} from './rest.server';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A per-request Context combining an IoC container with handler context
|
|
18
|
+
* (request, response, etc.).
|
|
19
|
+
*/
|
|
20
|
+
export class RequestContext extends MiddlewareContext
|
|
21
|
+
implements HandlerContext {
|
|
22
|
+
/**
|
|
23
|
+
* Get the protocol used by the client to make the request.
|
|
24
|
+
* Please note this protocol may be different from what we are observing
|
|
25
|
+
* at HTTP/TCP level, because reverse proxies like nginx or sidecars like
|
|
26
|
+
* Envoy are switching between protocols.
|
|
27
|
+
*/
|
|
28
|
+
get requestedProtocol(): string {
|
|
29
|
+
return (
|
|
30
|
+
((this.request.get('x-forwarded-proto') ?? '').split(',')[0] ||
|
|
31
|
+
this.request.protocol ||
|
|
32
|
+
this.serverConfig.protocol) ??
|
|
33
|
+
'http'
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Get the effective base path of the incoming request. This base path
|
|
39
|
+
* combines `baseUrl` provided by Express when LB4 handler is mounted on
|
|
40
|
+
* a non-root path, with the `basePath` value configured at LB4 side.
|
|
41
|
+
*/
|
|
42
|
+
get basePath(): string {
|
|
43
|
+
const request = this.request;
|
|
44
|
+
let basePath = this.serverConfig.basePath ?? '';
|
|
45
|
+
if (request.baseUrl && request.baseUrl !== '/') {
|
|
46
|
+
if (!basePath || request.baseUrl.endsWith(basePath)) {
|
|
47
|
+
// Express has already applied basePath to baseUrl
|
|
48
|
+
basePath = request.baseUrl;
|
|
49
|
+
} else {
|
|
50
|
+
basePath = request.baseUrl + basePath;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return basePath;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Get the base URL used by the client to make the request.
|
|
58
|
+
* This URL contains the protocol, hostname, port and base path.
|
|
59
|
+
* The path of the invoked route and query string is not included.
|
|
60
|
+
*
|
|
61
|
+
* Please note these values may be different from what we are observing
|
|
62
|
+
* at HTTP/TCP level, because reverse proxies like nginx are rewriting them.
|
|
63
|
+
*/
|
|
64
|
+
get requestedBaseUrl(): string {
|
|
65
|
+
const request = this.request;
|
|
66
|
+
const config = this.serverConfig;
|
|
67
|
+
|
|
68
|
+
const protocol = this.requestedProtocol;
|
|
69
|
+
// The host can be in one of the forms
|
|
70
|
+
// [::1]:3000
|
|
71
|
+
// [::1]
|
|
72
|
+
// 127.0.0.1:3000
|
|
73
|
+
// 127.0.0.1
|
|
74
|
+
let {host, port} = parseHostAndPort(
|
|
75
|
+
request.get('x-forwarded-host') ?? request.headers.host,
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const forwardedPort = (request.get('x-forwarded-port') ?? '').split(',')[0];
|
|
79
|
+
port = forwardedPort || port;
|
|
80
|
+
|
|
81
|
+
if (!host) {
|
|
82
|
+
// No host detected from http headers
|
|
83
|
+
// Use the configured values or the local network address
|
|
84
|
+
host = config.host ?? request.socket.localAddress;
|
|
85
|
+
port = (config.port || request.socket.localPort).toString();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// clear default ports
|
|
89
|
+
port = protocol === 'https' && port === '443' ? '' : port;
|
|
90
|
+
port = protocol === 'http' && port === '80' ? '' : port;
|
|
91
|
+
|
|
92
|
+
// add port number of present
|
|
93
|
+
host += port !== '' ? ':' + port : '';
|
|
94
|
+
|
|
95
|
+
return protocol + '://' + host + this.basePath;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
constructor(
|
|
99
|
+
public readonly request: Request,
|
|
100
|
+
public readonly response: Response,
|
|
101
|
+
parent: Context,
|
|
102
|
+
public readonly serverConfig: RestServerResolvedConfig,
|
|
103
|
+
name?: string,
|
|
104
|
+
) {
|
|
105
|
+
super(request, response, parent, name);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
protected setupBindings() {
|
|
109
|
+
super.setupBindings();
|
|
110
|
+
this.bind(RestBindings.Http.REQUEST).to(this.request).lock();
|
|
111
|
+
this.bind(RestBindings.Http.RESPONSE).to(this.response).lock();
|
|
112
|
+
this.bind(RestBindings.Http.CONTEXT).to(this).lock();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function parseHostAndPort(host: string | undefined) {
|
|
117
|
+
host = host ?? '';
|
|
118
|
+
host = host.split(',')[0];
|
|
119
|
+
const portPattern = /:([0-9]+)$/;
|
|
120
|
+
const port = (host.match(portPattern) ?? [])[1] || '';
|
|
121
|
+
host = host.replace(portPattern, '');
|
|
122
|
+
return {host, port};
|
|
123
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// Copyright IBM Corp. 2018,2020. 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 HttpErrors from 'http-errors';
|
|
7
|
+
|
|
8
|
+
export namespace RestHttpErrors {
|
|
9
|
+
export function invalidData<T, Props extends object = {}>(
|
|
10
|
+
data: T,
|
|
11
|
+
name: string,
|
|
12
|
+
extraProperties?: Props,
|
|
13
|
+
): HttpErrors.HttpError & Props {
|
|
14
|
+
const msg = `Invalid data ${JSON.stringify(data)} for parameter ${name}!`;
|
|
15
|
+
return Object.assign(
|
|
16
|
+
new HttpErrors.BadRequest(msg),
|
|
17
|
+
{
|
|
18
|
+
code: 'INVALID_PARAMETER_VALUE',
|
|
19
|
+
parameterName: name,
|
|
20
|
+
},
|
|
21
|
+
extraProperties,
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function unsupportedMediaType(
|
|
26
|
+
contentType: string,
|
|
27
|
+
allowedTypes: string[] = [],
|
|
28
|
+
) {
|
|
29
|
+
const msg = allowedTypes?.length
|
|
30
|
+
? `Content-type ${contentType} does not match [${allowedTypes}].`
|
|
31
|
+
: `Content-type ${contentType} is not supported.`;
|
|
32
|
+
return Object.assign(new HttpErrors.UnsupportedMediaType(msg), {
|
|
33
|
+
code: 'UNSUPPORTED_MEDIA_TYPE',
|
|
34
|
+
contentType: contentType,
|
|
35
|
+
allowedMediaTypes: allowedTypes,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function missingRequired(name: string): HttpErrors.HttpError {
|
|
40
|
+
const msg = `Required parameter ${name} is missing!`;
|
|
41
|
+
return Object.assign(new HttpErrors.BadRequest(msg), {
|
|
42
|
+
code: 'MISSING_REQUIRED_PARAMETER',
|
|
43
|
+
parameterName: name,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function invalidParamLocation(location: string): HttpErrors.HttpError {
|
|
48
|
+
const msg = `Parameters with "in: ${location}" are not supported yet.`;
|
|
49
|
+
return new HttpErrors.NotImplemented(msg);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const INVALID_REQUEST_BODY_MESSAGE =
|
|
53
|
+
'The request body is invalid. See error object `details` property for more info.';
|
|
54
|
+
export function invalidRequestBody(): HttpErrors.HttpError {
|
|
55
|
+
return Object.assign(
|
|
56
|
+
new HttpErrors.UnprocessableEntity(INVALID_REQUEST_BODY_MESSAGE),
|
|
57
|
+
{
|
|
58
|
+
code: 'VALIDATION_FAILED',
|
|
59
|
+
},
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* An invalid request body error contains a `details` property as the machine-readable error.
|
|
65
|
+
* Each entry in `error.details` contains 4 attributes: `path`, `code`, `info` and `message`.
|
|
66
|
+
* `ValidationErrorDetails` defines the type of each entry, which is an object.
|
|
67
|
+
* The type of `error.details` is `ValidationErrorDetails[]`.
|
|
68
|
+
*/
|
|
69
|
+
export interface ValidationErrorDetails {
|
|
70
|
+
/**
|
|
71
|
+
* A path to the invalid field.
|
|
72
|
+
*/
|
|
73
|
+
path: string;
|
|
74
|
+
/**
|
|
75
|
+
* A single word code represents the error's type.
|
|
76
|
+
*/
|
|
77
|
+
code: string;
|
|
78
|
+
/**
|
|
79
|
+
* A human readable description of the error.
|
|
80
|
+
*/
|
|
81
|
+
message: string;
|
|
82
|
+
/**
|
|
83
|
+
* Some additional details that the 3 attributes above don't cover.
|
|
84
|
+
*/
|
|
85
|
+
info: object;
|
|
86
|
+
}
|
|
87
|
+
}
|