@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
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright IBM Corp. 2018,2020. All Rights Reserved.
|
|
3
|
+
// Node module: @loopback/rest
|
|
4
|
+
// This file is licensed under the MIT License.
|
|
5
|
+
// License text available at https://opensource.org/licenses/MIT
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.validateRequestBody = void 0;
|
|
8
|
+
const tslib_1 = require("tslib");
|
|
9
|
+
const openapi_v3_1 = require("@loopback/openapi-v3");
|
|
10
|
+
const debug_1 = tslib_1.__importDefault(require("debug"));
|
|
11
|
+
const lodash_1 = tslib_1.__importDefault(require("lodash"));
|
|
12
|
+
const util_1 = tslib_1.__importDefault(require("util"));
|
|
13
|
+
const __1 = require("..");
|
|
14
|
+
const ajv_factory_provider_1 = require("./ajv-factory.provider");
|
|
15
|
+
const toJsonSchema = require('@openapi-contrib/openapi-schema-to-json-schema');
|
|
16
|
+
const debug = debug_1.default('loopback:rest:validation');
|
|
17
|
+
/**
|
|
18
|
+
* Check whether the request body is valid according to the provided OpenAPI schema.
|
|
19
|
+
* The JSON schema is generated from the OpenAPI schema which is typically defined
|
|
20
|
+
* by `@requestBody()`.
|
|
21
|
+
* The validation leverages AJV schema validator.
|
|
22
|
+
* @param body - The request body parsed from an HTTP request.
|
|
23
|
+
* @param requestBodySpec - The OpenAPI requestBody specification defined in `@requestBody()`.
|
|
24
|
+
* @param globalSchemas - The referenced schemas generated from `OpenAPISpec.components.schemas`.
|
|
25
|
+
* @param options - Request body validation options for AJV
|
|
26
|
+
*/
|
|
27
|
+
async function validateRequestBody(body, requestBodySpec, globalSchemas = {}, options = {}) {
|
|
28
|
+
const required = requestBodySpec === null || requestBodySpec === void 0 ? void 0 : requestBodySpec.required;
|
|
29
|
+
if (required && body.value == null) {
|
|
30
|
+
const err = Object.assign(new __1.HttpErrors.BadRequest('Request body is required'), {
|
|
31
|
+
code: 'MISSING_REQUIRED_PARAMETER',
|
|
32
|
+
parameterName: 'request body',
|
|
33
|
+
});
|
|
34
|
+
throw err;
|
|
35
|
+
}
|
|
36
|
+
const schema = body.schema;
|
|
37
|
+
/* istanbul ignore if */
|
|
38
|
+
if (debug.enabled) {
|
|
39
|
+
debug('Request body schema:', util_1.default.inspect(schema, { depth: null }));
|
|
40
|
+
if (schema &&
|
|
41
|
+
openapi_v3_1.isReferenceObject(schema) &&
|
|
42
|
+
schema.$ref.startsWith('#/components/schemas/')) {
|
|
43
|
+
const ref = schema.$ref.slice('#/components/schemas/'.length);
|
|
44
|
+
debug(' referencing:', util_1.default.inspect(globalSchemas[ref], { depth: null }));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (!schema)
|
|
48
|
+
return;
|
|
49
|
+
options = { coerceTypes: !!body.coercionRequired, ...options };
|
|
50
|
+
await validateValueAgainstSchema(body.value, schema, globalSchemas, options);
|
|
51
|
+
}
|
|
52
|
+
exports.validateRequestBody = validateRequestBody;
|
|
53
|
+
/**
|
|
54
|
+
* Convert an OpenAPI schema to the corresponding JSON schema.
|
|
55
|
+
* @param openapiSchema - The OpenAPI schema to convert.
|
|
56
|
+
*/
|
|
57
|
+
function convertToJsonSchema(openapiSchema) {
|
|
58
|
+
const jsonSchema = toJsonSchema(openapiSchema);
|
|
59
|
+
delete jsonSchema['$schema'];
|
|
60
|
+
/* istanbul ignore if */
|
|
61
|
+
if (debug.enabled) {
|
|
62
|
+
debug('Converted OpenAPI schema to JSON schema: %s', util_1.default.inspect(jsonSchema, { depth: null }));
|
|
63
|
+
}
|
|
64
|
+
return jsonSchema;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Built-in cache for complied schemas by AJV
|
|
68
|
+
*/
|
|
69
|
+
const DEFAULT_COMPILED_SCHEMA_CACHE = new WeakMap();
|
|
70
|
+
/**
|
|
71
|
+
* Build a cache key for AJV options
|
|
72
|
+
* @param options - Request body validation options
|
|
73
|
+
*/
|
|
74
|
+
function getKeyForOptions(options) {
|
|
75
|
+
const ajvOptions = {};
|
|
76
|
+
// Sort keys for options
|
|
77
|
+
const keys = Object.keys(options).sort();
|
|
78
|
+
for (const k of keys) {
|
|
79
|
+
if (k === 'compiledSchemaCache')
|
|
80
|
+
continue;
|
|
81
|
+
ajvOptions[k] = options[k];
|
|
82
|
+
}
|
|
83
|
+
return JSON.stringify(ajvOptions);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Validate the request body data against JSON schema.
|
|
87
|
+
* @param body - The request body data.
|
|
88
|
+
* @param schema - The JSON schema used to perform the validation.
|
|
89
|
+
* @param globalSchemas - Schema references.
|
|
90
|
+
* @param options - Request body validation options.
|
|
91
|
+
*/
|
|
92
|
+
async function validateValueAgainstSchema(
|
|
93
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
94
|
+
body, schema, globalSchemas = {}, options = {}) {
|
|
95
|
+
var _a, _b;
|
|
96
|
+
let validate;
|
|
97
|
+
const cache = (_a = options.compiledSchemaCache) !== null && _a !== void 0 ? _a : DEFAULT_COMPILED_SCHEMA_CACHE;
|
|
98
|
+
const key = getKeyForOptions(options);
|
|
99
|
+
let validatorMap;
|
|
100
|
+
if (cache.has(schema)) {
|
|
101
|
+
validatorMap = cache.get(schema);
|
|
102
|
+
validate = validatorMap.get(key);
|
|
103
|
+
}
|
|
104
|
+
if (!validate) {
|
|
105
|
+
const ajvFactory = (_b = options.ajvFactory) !== null && _b !== void 0 ? _b : new ajv_factory_provider_1.AjvFactoryProvider(options).value();
|
|
106
|
+
const ajvInst = ajvFactory(options);
|
|
107
|
+
validate = createValidator(schema, globalSchemas, ajvInst);
|
|
108
|
+
validatorMap = validatorMap !== null && validatorMap !== void 0 ? validatorMap : new Map();
|
|
109
|
+
validatorMap.set(key, validate);
|
|
110
|
+
cache.set(schema, validatorMap);
|
|
111
|
+
}
|
|
112
|
+
let validationErrors = [];
|
|
113
|
+
try {
|
|
114
|
+
const validationResult = await validate(body);
|
|
115
|
+
// When body is optional & values is empty / null, ajv returns null
|
|
116
|
+
if (validationResult || validationResult === null) {
|
|
117
|
+
debug('Request body passed AJV validation.');
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
validationErrors = error.errors;
|
|
123
|
+
}
|
|
124
|
+
/* istanbul ignore if */
|
|
125
|
+
if (debug.enabled) {
|
|
126
|
+
debug('Invalid request body: %s. Errors: %s', util_1.default.inspect(body, { depth: null }), util_1.default.inspect(validationErrors));
|
|
127
|
+
}
|
|
128
|
+
if (typeof options.ajvErrorTransformer === 'function') {
|
|
129
|
+
validationErrors = options.ajvErrorTransformer(validationErrors);
|
|
130
|
+
}
|
|
131
|
+
const error = __1.RestHttpErrors.invalidRequestBody();
|
|
132
|
+
error.details = lodash_1.default.map(validationErrors, e => {
|
|
133
|
+
return {
|
|
134
|
+
path: e.dataPath,
|
|
135
|
+
code: e.keyword,
|
|
136
|
+
message: e.message,
|
|
137
|
+
info: e.params,
|
|
138
|
+
};
|
|
139
|
+
});
|
|
140
|
+
throw error;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Create a validate function for the given schema
|
|
144
|
+
* @param schema - JSON schema for the target
|
|
145
|
+
* @param globalSchemas - Global schemas
|
|
146
|
+
* @param ajvInst - An instance of Ajv
|
|
147
|
+
*/
|
|
148
|
+
function createValidator(schema, globalSchemas = {}, ajvInst) {
|
|
149
|
+
const jsonSchema = convertToJsonSchema(schema);
|
|
150
|
+
// Clone global schemas to set `$async: true` flag
|
|
151
|
+
const schemas = {};
|
|
152
|
+
for (const name in globalSchemas) {
|
|
153
|
+
// See https://github.com/strongloop/loopback-next/issues/4939
|
|
154
|
+
schemas[name] = { ...globalSchemas[name], $async: true };
|
|
155
|
+
}
|
|
156
|
+
const schemaWithRef = { components: { schemas }, ...jsonSchema };
|
|
157
|
+
// See https://ajv.js.org/#asynchronous-validation for async validation
|
|
158
|
+
schemaWithRef.$async = true;
|
|
159
|
+
return ajvInst.compile(schemaWithRef);
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=request-body.validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-body.validator.js","sourceRoot":"","sources":["../../src/validation/request-body.validator.ts"],"names":[],"mappings":"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"}
|
package/dist/writer.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { OperationRetval, Response } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Writes the result from Application controller method
|
|
4
|
+
* into the HTTP response
|
|
5
|
+
*
|
|
6
|
+
* @param response - HTTP Response
|
|
7
|
+
* @param result - Result from the API to write into HTTP Response
|
|
8
|
+
*/
|
|
9
|
+
export declare function writeResultToResponse(response: Response, result: OperationRetval): void;
|
package/dist/writer.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright IBM Corp. 2017,2020. All Rights Reserved.
|
|
3
|
+
// Node module: @loopback/rest
|
|
4
|
+
// This file is licensed under the MIT License.
|
|
5
|
+
// License text available at https://opensource.org/licenses/MIT
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.writeResultToResponse = void 0;
|
|
8
|
+
const stream_1 = require("stream");
|
|
9
|
+
/**
|
|
10
|
+
* Writes the result from Application controller method
|
|
11
|
+
* into the HTTP response
|
|
12
|
+
*
|
|
13
|
+
* @param response - HTTP Response
|
|
14
|
+
* @param result - Result from the API to write into HTTP Response
|
|
15
|
+
*/
|
|
16
|
+
function writeResultToResponse(
|
|
17
|
+
// not needed and responsibility should be in the sequence.send
|
|
18
|
+
response,
|
|
19
|
+
// result returned back from invoking controller method
|
|
20
|
+
result) {
|
|
21
|
+
// Bypass response writing if the controller method returns `response` itself
|
|
22
|
+
// or the response headers have been sent
|
|
23
|
+
if (result === response || response.headersSent) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (result === undefined) {
|
|
27
|
+
response.statusCode = 204;
|
|
28
|
+
response.end();
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const isStream = result instanceof stream_1.Readable || typeof (result === null || result === void 0 ? void 0 : result.pipe) === 'function';
|
|
32
|
+
if (isStream) {
|
|
33
|
+
response.setHeader('Content-Type', 'application/octet-stream');
|
|
34
|
+
// Stream
|
|
35
|
+
result.pipe(response);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
switch (typeof result) {
|
|
39
|
+
case 'object':
|
|
40
|
+
case 'boolean':
|
|
41
|
+
case 'number':
|
|
42
|
+
if (Buffer.isBuffer(result)) {
|
|
43
|
+
// Buffer for binary data
|
|
44
|
+
response.setHeader('Content-Type', 'application/octet-stream');
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
// TODO(ritch) remove this, should be configurable
|
|
48
|
+
// See https://github.com/strongloop/loopback-next/issues/436
|
|
49
|
+
response.setHeader('Content-Type', 'application/json');
|
|
50
|
+
// TODO(bajtos) handle errors - JSON.stringify can throw
|
|
51
|
+
result = JSON.stringify(result);
|
|
52
|
+
}
|
|
53
|
+
break;
|
|
54
|
+
default:
|
|
55
|
+
response.setHeader('Content-Type', 'text/plain');
|
|
56
|
+
result = result.toString();
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
response.end(result);
|
|
60
|
+
}
|
|
61
|
+
exports.writeResultToResponse = writeResultToResponse;
|
|
62
|
+
//# sourceMappingURL=writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writer.js","sourceRoot":"","sources":["../src/writer.ts"],"names":[],"mappings":";AAAA,sDAAsD;AACtD,8BAA8B;AAC9B,+CAA+C;AAC/C,gEAAgE;;;AAGhE,mCAAgC;AAEhC;;;;;;GAMG;AACH,SAAgB,qBAAqB;AACnC,+DAA+D;AAC/D,QAAkB;AAClB,uDAAuD;AACvD,MAAuB;IAEvB,6EAA6E;IAC7E,yCAAyC;IACzC,IAAI,MAAM,KAAK,QAAQ,IAAI,QAAQ,CAAC,WAAW,EAAE;QAC/C,OAAO;KACR;IACD,IAAI,MAAM,KAAK,SAAS,EAAE;QACxB,QAAQ,CAAC,UAAU,GAAG,GAAG,CAAC;QAC1B,QAAQ,CAAC,GAAG,EAAE,CAAC;QACf,OAAO;KACR;IAED,MAAM,QAAQ,GACZ,MAAM,YAAY,iBAAQ,IAAI,QAAO,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,IAAI,CAAA,KAAK,UAAU,CAAC;IAEnE,IAAI,QAAQ,EAAE;QACZ,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,0BAA0B,CAAC,CAAC;QAC/D,SAAS;QACT,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACtB,OAAO;KACR;IACD,QAAQ,OAAO,MAAM,EAAE;QACrB,KAAK,QAAQ,CAAC;QACd,KAAK,SAAS,CAAC;QACf,KAAK,QAAQ;YACX,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;gBAC3B,yBAAyB;gBACzB,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,0BAA0B,CAAC,CAAC;aAChE;iBAAM;gBACL,kDAAkD;gBAClD,6DAA6D;gBAC7D,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;gBACvD,wDAAwD;gBACxD,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;aACjC;YACD,MAAM;QACR;YACE,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;YACjD,MAAM,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;YAC3B,MAAM;KACT;IACD,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACvB,CAAC;AA/CD,sDA+CC"}
|
package/package.json
CHANGED
|
@@ -1,57 +1,85 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loopback/rest",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.1",
|
|
4
4
|
"description": "",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
5
7
|
"engines": {
|
|
6
|
-
"node": ">=
|
|
8
|
+
"node": ">=10"
|
|
7
9
|
},
|
|
8
10
|
"scripts": {
|
|
9
|
-
"acceptance": "lb-
|
|
10
|
-
"build": "
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"prepare": "npm run build && npm run build:apidocs",
|
|
17
|
-
"pretest": "npm run build:current",
|
|
18
|
-
"integration": "lb-dist mocha --opts ../../test/mocha.opts 'DIST/test/integration/**/*.js'",
|
|
19
|
-
"test": "lb-dist mocha --opts ../../test/mocha.opts 'DIST/test/unit/**/*.js' 'DIST/test/integration/**/*.js' 'DIST/test/acceptance/**/*.js'",
|
|
20
|
-
"unit": "lb-dist mocha --opts ../../test/mocha.opts 'DIST/test/unit/**/*.js'",
|
|
11
|
+
"acceptance": "lb-mocha \"dist/__tests__/acceptance/**/*.js\"",
|
|
12
|
+
"build": "lb-tsc",
|
|
13
|
+
"clean": "lb-clean loopback-rest*.tgz dist *.tsbuildinfo package",
|
|
14
|
+
"pretest": "npm run build",
|
|
15
|
+
"integration": "lb-mocha \"dist/__tests__/integration/**/*.js\"",
|
|
16
|
+
"test": "lb-mocha \"dist/__tests__/**/*.js\"",
|
|
17
|
+
"unit": "lb-mocha \"dist/__tests__/unit/**/*.js\"",
|
|
21
18
|
"verify": "npm pack && tar xf loopback-rest*.tgz && tree package && npm run clean"
|
|
22
19
|
},
|
|
23
|
-
"author": "IBM",
|
|
20
|
+
"author": "IBM Corp.",
|
|
21
|
+
"copyright.owner": "IBM Corp.",
|
|
24
22
|
"license": "MIT",
|
|
25
23
|
"dependencies": {
|
|
26
|
-
"@loopback/context": "^
|
|
27
|
-
"@loopback/core": "^
|
|
28
|
-
"@loopback/
|
|
29
|
-
"@
|
|
30
|
-
"@
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
24
|
+
"@loopback/context": "^3.8.1",
|
|
25
|
+
"@loopback/core": "^2.7.0",
|
|
26
|
+
"@loopback/express": "^1.2.1",
|
|
27
|
+
"@loopback/http-server": "^2.1.5",
|
|
28
|
+
"@loopback/openapi-v3": "^3.4.1",
|
|
29
|
+
"@openapi-contrib/openapi-schema-to-json-schema": "^3.0.0",
|
|
30
|
+
"@types/body-parser": "^1.19.0",
|
|
31
|
+
"@types/cors": "^2.8.6",
|
|
32
|
+
"@types/express": "^4.17.6",
|
|
33
|
+
"@types/express-serve-static-core": "^4.17.6",
|
|
34
|
+
"@types/http-errors": "^1.6.3",
|
|
35
|
+
"@types/on-finished": "^2.3.1",
|
|
36
|
+
"@types/serve-static": "1.13.4",
|
|
37
|
+
"@types/type-is": "^1.6.3",
|
|
38
|
+
"ajv": "^6.12.2",
|
|
39
|
+
"ajv-errors": "^1.0.1",
|
|
40
|
+
"ajv-keywords": "^3.4.1",
|
|
41
|
+
"body-parser": "^1.19.0",
|
|
42
|
+
"cors": "^2.8.5",
|
|
43
|
+
"debug": "^4.1.1",
|
|
44
|
+
"express": "^4.17.1",
|
|
45
|
+
"http-errors": "^1.7.3",
|
|
46
|
+
"js-yaml": "^3.13.1",
|
|
47
|
+
"json-schema-compare": "^0.2.2",
|
|
48
|
+
"lodash": "^4.17.15",
|
|
49
|
+
"on-finished": "^2.3.0",
|
|
50
|
+
"path-to-regexp": "^6.1.0",
|
|
51
|
+
"qs": "^6.9.4",
|
|
52
|
+
"strong-error-handler": "^3.4.0",
|
|
53
|
+
"tslib": "^2.0.0",
|
|
54
|
+
"type-is": "^1.6.18",
|
|
55
|
+
"validator": "^13.0.0"
|
|
38
56
|
},
|
|
39
57
|
"devDependencies": {
|
|
40
|
-
"@loopback/build": "^4.
|
|
41
|
-
"@loopback/
|
|
42
|
-
"@loopback/
|
|
58
|
+
"@loopback/build": "^5.4.1",
|
|
59
|
+
"@loopback/eslint-config": "^7.0.1",
|
|
60
|
+
"@loopback/openapi-spec-builder": "^2.1.5",
|
|
61
|
+
"@loopback/repository": "^2.5.1",
|
|
62
|
+
"@loopback/testlab": "^3.1.5",
|
|
63
|
+
"@types/debug": "^4.1.5",
|
|
64
|
+
"@types/js-yaml": "^3.12.4",
|
|
65
|
+
"@types/json-schema-compare": "^0.2.0",
|
|
66
|
+
"@types/lodash": "^4.14.152",
|
|
67
|
+
"@types/multer": "^1.4.3",
|
|
68
|
+
"@types/node": "^10.17.24",
|
|
69
|
+
"@types/on-finished": "^2.3.1",
|
|
70
|
+
"@types/qs": "^6.9.3",
|
|
71
|
+
"multer": "^1.4.2"
|
|
43
72
|
},
|
|
44
73
|
"files": [
|
|
45
74
|
"README.md",
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"dist6/src",
|
|
50
|
-
"api-docs",
|
|
51
|
-
"src"
|
|
75
|
+
"dist",
|
|
76
|
+
"src",
|
|
77
|
+
"!*/__tests__"
|
|
52
78
|
],
|
|
53
79
|
"repository": {
|
|
54
80
|
"type": "git",
|
|
55
|
-
"url": "https://github.com/strongloop/loopback-next.git"
|
|
56
|
-
|
|
81
|
+
"url": "https://github.com/strongloop/loopback-next.git",
|
|
82
|
+
"directory": "packages/rest"
|
|
83
|
+
},
|
|
84
|
+
"gitHead": "62aea854bf85c5a5995b59e6908fe5409f7eea96"
|
|
57
85
|
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// Copyright IBM Corp. 2018,2019. 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
|
+
Options,
|
|
8
|
+
OptionsJson,
|
|
9
|
+
OptionsText,
|
|
10
|
+
OptionsUrlencoded,
|
|
11
|
+
} from 'body-parser';
|
|
12
|
+
import debugModule from 'debug';
|
|
13
|
+
import {HttpError} from 'http-errors';
|
|
14
|
+
import {Request, RequestBodyParserOptions, Response} from '../types';
|
|
15
|
+
|
|
16
|
+
const debug = debugModule('loopback:rest:body-parser');
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Get the content-type header value from the request
|
|
20
|
+
* @param req - Http request
|
|
21
|
+
*/
|
|
22
|
+
export function getContentType(req: Request): string | undefined {
|
|
23
|
+
return req.get('content-type');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Express body parser function type
|
|
28
|
+
*/
|
|
29
|
+
export type BodyParserMiddleware = (
|
|
30
|
+
request: Request,
|
|
31
|
+
response: Response,
|
|
32
|
+
next: (err: HttpError) => void,
|
|
33
|
+
) => void;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Normalize parsing errors as `4xx`
|
|
37
|
+
* @param err
|
|
38
|
+
*/
|
|
39
|
+
export function normalizeParsingError(err: HttpError) {
|
|
40
|
+
debug('Cannot parse request body %j', err);
|
|
41
|
+
if (!err.statusCode || err.statusCode >= 500) {
|
|
42
|
+
err.statusCode = 400;
|
|
43
|
+
}
|
|
44
|
+
return err;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Parse the request body asynchronously
|
|
51
|
+
* @param handle - The express middleware handler
|
|
52
|
+
* @param request - Http request
|
|
53
|
+
*/
|
|
54
|
+
export function invokeBodyParserMiddleware(
|
|
55
|
+
handle: BodyParserMiddleware,
|
|
56
|
+
request: Request,
|
|
57
|
+
): Promise<any> {
|
|
58
|
+
// A hack to fool TypeScript as we don't need `response`
|
|
59
|
+
const response = ({} as any) as Response;
|
|
60
|
+
return new Promise<void>((resolve, reject) => {
|
|
61
|
+
handle(request, response, err => {
|
|
62
|
+
if (err) {
|
|
63
|
+
reject(err);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
resolve(request.body);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Default limit of the body length
|
|
72
|
+
export const DEFAULT_LIMIT = '1mb';
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Extract parser options based on the parser type
|
|
76
|
+
* @param type - json|urlencoded|text
|
|
77
|
+
* @param options
|
|
78
|
+
*/
|
|
79
|
+
export function getParserOptions(
|
|
80
|
+
type: 'json',
|
|
81
|
+
options: RequestBodyParserOptions,
|
|
82
|
+
): OptionsJson;
|
|
83
|
+
export function getParserOptions(
|
|
84
|
+
type: 'urlencoded',
|
|
85
|
+
options: RequestBodyParserOptions,
|
|
86
|
+
): OptionsUrlencoded;
|
|
87
|
+
export function getParserOptions(
|
|
88
|
+
type: 'text',
|
|
89
|
+
options: RequestBodyParserOptions,
|
|
90
|
+
): OptionsText;
|
|
91
|
+
export function getParserOptions(
|
|
92
|
+
type: 'raw',
|
|
93
|
+
options: RequestBodyParserOptions,
|
|
94
|
+
): Options;
|
|
95
|
+
|
|
96
|
+
export function getParserOptions(
|
|
97
|
+
type: 'json' | 'urlencoded' | 'text' | 'raw',
|
|
98
|
+
options: RequestBodyParserOptions,
|
|
99
|
+
) {
|
|
100
|
+
const opts: {[name: string]: any} = {limit: DEFAULT_LIMIT};
|
|
101
|
+
switch (type) {
|
|
102
|
+
case 'json':
|
|
103
|
+
// Allow */json and */*+json
|
|
104
|
+
opts.type = ['*/json', '*/*+json'];
|
|
105
|
+
opts.strict = false;
|
|
106
|
+
break;
|
|
107
|
+
case 'urlencoded':
|
|
108
|
+
opts.type = type;
|
|
109
|
+
opts.extended = true;
|
|
110
|
+
break;
|
|
111
|
+
case 'text':
|
|
112
|
+
// Set media type to `text/*` to match `text/plain` or `text/html`
|
|
113
|
+
opts.type = 'text/*';
|
|
114
|
+
break;
|
|
115
|
+
case 'raw':
|
|
116
|
+
opts.type = ['application/octet-stream', '*/*'];
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
Object.assign(opts, options[type], options);
|
|
120
|
+
for (const k of ['json', 'urlencoded', 'text', 'raw']) {
|
|
121
|
+
delete opts[k];
|
|
122
|
+
}
|
|
123
|
+
return opts;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export namespace builtinParsers {
|
|
127
|
+
export const json = Symbol('json');
|
|
128
|
+
export const urlencoded = Symbol('urlencoded');
|
|
129
|
+
export const text = Symbol('text');
|
|
130
|
+
export const raw = Symbol('raw');
|
|
131
|
+
export const stream = Symbol('stream');
|
|
132
|
+
|
|
133
|
+
export const names: (string | symbol)[] = [
|
|
134
|
+
json,
|
|
135
|
+
urlencoded,
|
|
136
|
+
text,
|
|
137
|
+
raw,
|
|
138
|
+
stream,
|
|
139
|
+
];
|
|
140
|
+
|
|
141
|
+
export const mapping: {[name: string]: symbol} = {
|
|
142
|
+
json,
|
|
143
|
+
urlencoded,
|
|
144
|
+
text,
|
|
145
|
+
raw,
|
|
146
|
+
stream,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// Copyright IBM Corp. 2018,2019. 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} from '@loopback/context';
|
|
7
|
+
import {json} from 'body-parser';
|
|
8
|
+
import {is} from 'type-is';
|
|
9
|
+
import {RestBindings} from '../keys';
|
|
10
|
+
import {Request, RequestBodyParserOptions} from '../types';
|
|
11
|
+
import {
|
|
12
|
+
BodyParserMiddleware,
|
|
13
|
+
getParserOptions,
|
|
14
|
+
invokeBodyParserMiddleware,
|
|
15
|
+
builtinParsers,
|
|
16
|
+
} from './body-parser.helpers';
|
|
17
|
+
import {BodyParser, RequestBody} from './types';
|
|
18
|
+
import {sanitizeJsonParse} from '../parse-json';
|
|
19
|
+
|
|
20
|
+
export class JsonBodyParser implements BodyParser {
|
|
21
|
+
name = builtinParsers.json;
|
|
22
|
+
private jsonParser: BodyParserMiddleware;
|
|
23
|
+
|
|
24
|
+
constructor(
|
|
25
|
+
@inject(RestBindings.REQUEST_BODY_PARSER_OPTIONS, {optional: true})
|
|
26
|
+
options: RequestBodyParserOptions = {},
|
|
27
|
+
) {
|
|
28
|
+
const jsonOptions = getParserOptions('json', options);
|
|
29
|
+
jsonOptions.reviver = sanitizeJsonParse(jsonOptions.reviver);
|
|
30
|
+
this.jsonParser = json(jsonOptions);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
supports(mediaType: string) {
|
|
34
|
+
return !!is(mediaType, '*/json', '*/*+json');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async parse(request: Request): Promise<RequestBody> {
|
|
38
|
+
let body = await invokeBodyParserMiddleware(this.jsonParser, request);
|
|
39
|
+
// https://github.com/expressjs/body-parser/blob/master/lib/types/json.js#L71-L76
|
|
40
|
+
const contentLength = request.get('content-length');
|
|
41
|
+
if (contentLength != null && +contentLength === 0) {
|
|
42
|
+
body = undefined;
|
|
43
|
+
}
|
|
44
|
+
return {value: body};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Copyright IBM Corp. 2018. 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} from '@loopback/context';
|
|
7
|
+
import {raw} from 'body-parser';
|
|
8
|
+
import {is} from 'type-is';
|
|
9
|
+
import {RestBindings} from '../keys';
|
|
10
|
+
import {Request, RequestBodyParserOptions} from '../types';
|
|
11
|
+
import {
|
|
12
|
+
BodyParserMiddleware,
|
|
13
|
+
getParserOptions,
|
|
14
|
+
invokeBodyParserMiddleware,
|
|
15
|
+
builtinParsers,
|
|
16
|
+
} from './body-parser.helpers';
|
|
17
|
+
import {BodyParser, RequestBody} from './types';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Parsing the request body into Buffer
|
|
21
|
+
*/
|
|
22
|
+
export class RawBodyParser implements BodyParser {
|
|
23
|
+
name = builtinParsers.raw;
|
|
24
|
+
private rawParser: BodyParserMiddleware;
|
|
25
|
+
|
|
26
|
+
constructor(
|
|
27
|
+
@inject(RestBindings.REQUEST_BODY_PARSER_OPTIONS, {optional: true})
|
|
28
|
+
options: RequestBodyParserOptions = {},
|
|
29
|
+
) {
|
|
30
|
+
const rawOptions = getParserOptions('raw', options);
|
|
31
|
+
this.rawParser = raw(rawOptions);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
supports(mediaType: string) {
|
|
35
|
+
return !!is(mediaType, 'application/octet-stream');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async parse(request: Request): Promise<RequestBody> {
|
|
39
|
+
const body = await invokeBodyParserMiddleware(this.rawParser, request);
|
|
40
|
+
return {value: body};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Copyright IBM Corp. 2018. 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 {Request} from '../types';
|
|
7
|
+
import {BodyParser, RequestBody} from './types';
|
|
8
|
+
import {builtinParsers} from './body-parser.helpers';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A special body parser to retain request stream as is.
|
|
12
|
+
* It will be used by explicitly setting `x-parser` to `'stream'` in the request
|
|
13
|
+
* body spec.
|
|
14
|
+
*/
|
|
15
|
+
export class StreamBodyParser implements BodyParser {
|
|
16
|
+
name = builtinParsers.stream;
|
|
17
|
+
|
|
18
|
+
supports(mediaType: string) {
|
|
19
|
+
// Return `false` so that this parser can only be trigged by the
|
|
20
|
+
// `{x-parser: 'stream'}` extension in the request body spec
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async parse(request: Request): Promise<RequestBody> {
|
|
25
|
+
return {value: request};
|
|
26
|
+
}
|
|
27
|
+
}
|