Skip to content

Commit

Permalink
fix: upgrade dependencies and resolve breaking http spec changes (#2105)
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel A. White authored Aug 16, 2022
1 parent 38eccce commit ebbc6c1
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 76 deletions.
4 changes: 2 additions & 2 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
},
"bugs": "https://github.com/stoplightio/prism/issues",
"dependencies": {
"@stoplight/http-spec": "^5.1.1",
"@stoplight/http-spec": "^5.5.2",
"@stoplight/json": "^3.18.1",
"@stoplight/json-schema-ref-parser": "9.2.1",
"@stoplight/prism-core": "^4.10.2",
"@stoplight/prism-http": "^4.10.2",
"@stoplight/prism-http-server": "^4.10.2",
"@stoplight/types": "^13.0.0",
"@stoplight/types": "^13.6.0",
"chalk": "^4.1.2",
"chokidar": "^3.5.2",
"fp-ts": "^2.11.5",
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/extensions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { dereference } from 'json-schema-ref-parser';
import { dereference } from '@stoplight/json-schema-ref-parser';
import { decycle } from '@stoplight/json';
import { get, camelCase, forOwn } from 'lodash';
import * as jsf from 'json-schema-faker';
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/operations.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { transformOas3Operations } from '@stoplight/http-spec/oas3/operation';
import { transformOas2Operations } from '@stoplight/http-spec/oas2/operation';
import { transformPostmanCollectionOperations } from '@stoplight/http-spec/postman/operation';
import { dereference } from 'json-schema-ref-parser';
import { dereference } from '@stoplight/json-schema-ref-parser';
import { bundleTarget, decycle } from '@stoplight/json';
import { IHttpOperation } from '@stoplight/types';
import { get } from 'lodash';
Expand Down
68 changes: 33 additions & 35 deletions packages/http/src/validator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@ import { wildcardMediaTypeMatch } from './utils/wildcardMediaTypeMatch';

export { validateSecurity } from './validators/security';

const checkBodyIsProvided = (requestBody: IHttpOperationRequestBody, body: unknown) =>
const checkRequiredBodyIsProvided = (requestBody: O.Option<IHttpOperationRequestBody>, body: unknown) =>
pipe(
requestBody,
E.fromPredicate<IHttpOperationRequestBody, NonEmptyArray<IPrismDiagnostic>>(
requestBody => !(!!requestBody.required && !body),
E.fromPredicate<O.Option<IHttpOperationRequestBody>, NonEmptyArray<IPrismDiagnostic>>(
requestBody => O.isNone(requestBody) || !(!!requestBody.value.required && !body),
() => [{ code: 'required', message: 'Body parameter is required', severity: DiagnosticSeverity.Error }]
)
),
E.map(requestBody => [requestBody, O.fromNullable(body)] as const)
);

const isMediaTypeSupportedInContents = (mediaType?: string, contents?: IMediaTypeContent[]): boolean =>
Expand All @@ -51,63 +52,60 @@ const isMediaTypeSupportedInContents = (mediaType?: string, contents?: IMediaTyp
);

const validateInputIfBodySpecIsProvided = (
body: unknown,
body: O.Option<unknown>,
mediaType: string,
contents?: IMediaTypeContent[],
requestBody: O.Option<IHttpOperationRequestBody>,
bundle?: unknown
) =>
pipe(
sequenceOption(O.fromNullable(body), O.fromNullable(contents)),
sequenceOption(body, requestBody),
O.fold(
() => E.right(body),
([body, contents]) => validateBody(body, contents, ValidationContext.Input, mediaType, bundle)
([body, contents]) => validateBody(body, contents.contents ?? [], ValidationContext.Input, mediaType, bundle)
)
);

const tryValidateInputBody = (
requestBody: IHttpOperationRequestBody,
const validateInputBody = (
requestBody: O.Option<IHttpOperationRequestBody>,
bundle: unknown,
body: unknown,
headers: IHttpNameValue
) =>
pipe(
checkBodyIsProvided(requestBody, body),
E.chain(() => {
const headersNormalized = caseless(headers || {});

const contentLength = parseInt(headersNormalized.get('content-length')) || 0;
checkRequiredBodyIsProvided(requestBody, body),
E.map(b => [...b, caseless(headers || {})] as const),
E.chain(([requestBody, body, headers]) => {
const contentLength = parseInt(headers.get('content-length')) || 0;
if (contentLength === 0) {
// generously allow this content type if there isn't a body actually provided
return E.right(body);
return E.right([requestBody, body, headers] as const);
}

const mediaType = headersNormalized.get('content-type');
if (isMediaTypeSupportedInContents(mediaType, requestBody.contents)) {
return E.right(body);
}

const specRequestBodyContents = requestBody.contents || [];
let message: string;

if (specRequestBodyContents.length === 0) {
message = 'No supported content types, but request included a non-empty body';
} else {
const supportedContentTypes = specRequestBodyContents.map(x => x.mediaType);
message = `Supported content types: ${supportedContentTypes.join(',')}`;
let errorMessage = 'No supported content types, but request included a non-empty body';
if (O.isSome(requestBody)) {
const mediaType = headers.get('content-type');
if (isMediaTypeSupportedInContents(mediaType, requestBody.value.contents)) {
return E.right([requestBody, body, headers] as const);
}

const specRequestBodyContents = requestBody.value.contents || [];
if (specRequestBodyContents.length > 0) {
const supportedContentTypes = specRequestBodyContents.map(x => x.mediaType);
errorMessage = `Supported content types: ${supportedContentTypes.join(',')}`;
}
}

return E.left<NonEmptyArray<IPrismDiagnostic>>([
{
message,
message: errorMessage,
code: 415,
severity: DiagnosticSeverity.Error,
},
]);
}),
E.chain(() => {
const mediaType = caseless(headers || {}).get('content-type');

return validateInputIfBodySpecIsProvided(body, mediaType, requestBody.contents, bundle);
E.chain(([requestBody, body, headers]) => {
const mediaType = headers.get('content-type');
return validateInputIfBodySpecIsProvided(body, mediaType, requestBody, bundle);
})
);

Expand All @@ -122,7 +120,7 @@ export const validateInput: ValidatorFn<IHttpOperation, IHttpRequest> = ({ resou
e => E.right<NonEmptyArray<IPrismDiagnostic>, unknown>(e),
request =>
sequenceValidation(
request.body ? tryValidateInputBody(request.body, bundle, body, element.headers || {}) : E.right(undefined),
validateInputBody(O.fromNullable(request.body), bundle, body, element.headers || {}),
request.headers ? validateHeaders(element.headers || {}, request.headers, bundle) : E.right(undefined),
request.query ? validateQuery(element.url.query || {}, request.query, bundle) : E.right(undefined),
request.path
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
====test====
If I have an OAS3 document referencing a model that
recursively references itself in a request body through other objects
it should return 200 on a regular request and not crash
====spec====
openapi: 3.0.0
paths:
/:
put:
requestBody:
content:
application/json:
schema:
"$ref": "#/components/schemas/RequestModel"
required: true
responses:
'200':
content:
text/plain:
schema:
type: string
example:
valid request
components:
schemas:
RequestModel:
title: RequestModel
type: object
properties:
data:
anyOf:
- type: array
items:
"$ref": "#/components/schemas/Document"
Document:
title: Document
type: object
properties:
chunks:
type: array
items:
"$ref": "#/components/schemas/Document"
====server====
mock -p 4010 ${document}
====command====
curl -i -X PUT http://localhost:4010/ -H 'content-type: application/json' -d '{}'
====expect====
HTTP/1.1 200 OK

valid request
87 changes: 50 additions & 37 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,12 @@
minimatch "^3.0.4"
strip-json-comments "^3.1.1"

"@faker-js/[email protected]", "@faker-js/faker@^6.0.0":
"@faker-js/[email protected]":
version "5.5.3"
resolved "https://registry.yarnpkg.com/@faker-js/faker/-/faker-5.5.3.tgz#18e3af6b8eae7984072bbeb0c0858474d7c4cefe"
integrity sha512-R11tGE6yIFwqpaIqcfkcg7AICXzFg14+5h5v0TfF/9+RMDL6jhzCy/pxHVOfbALGdtVYdt6JdR21tuxEgl34dw==

"@faker-js/faker@^6.0.0":
version "6.0.0"
resolved "https://registry.yarnpkg.com/@faker-js/faker/-/faker-6.0.0.tgz#b613ebf5f5ebb2ab987afb567d8b7fe860199c13"
integrity sha512-10zLCKhp3YEmBuko71ivcMoIZcCLXgQVck6aNswX+AWwaek/L8S3yz9i8m3tHigRkcF6F2vI+qtdtyySHK+bGA==
Expand Down Expand Up @@ -1983,23 +1988,23 @@
dependencies:
"@sinonjs/commons" "^1.7.0"

"@stoplight/http-spec@^5.1.1":
version "5.1.1"
resolved "https://registry.yarnpkg.com/@stoplight/http-spec/-/http-spec-5.1.1.tgz#80e031cf428798d8011983573ee818cd6e1fb3af"
integrity sha512-KKkImg/jNzMAFOPHllfHTlMld7Ipf+wy9u81H2W7x40tpYQEj6cggvX+xpBFThg8N6vevq/bQ5VeH3pr0jlTUw==
"@stoplight/http-spec@^5.5.2":
version "5.5.2"
resolved "https://registry.yarnpkg.com/@stoplight/http-spec/-/http-spec-5.5.2.tgz#de9d4e282743c9fb09a1ed1f7e293a4b7583f6dd"
integrity sha512-WW2CeTxIuvbT59lm+n47iyxLHO/Uj73Mnta2uW39WdE3uUkJIEqovFJPflsIrJCXUcNIIwLuB+I6ZMTuTGK2Uw==
dependencies:
"@stoplight/json" "^3.18.0"
"@stoplight/json" "^3.18.1"
"@stoplight/json-schema-generator" "1.0.1"
"@stoplight/types" "^13.0.0"
"@types/json-schema" "7.0.5"
"@types/swagger-schema-official" "~2.0.21"
"@stoplight/types" "^13.6.0"
"@types/json-schema" "7.0.11"
"@types/swagger-schema-official" "~2.0.22"
"@types/type-is" "^1.6.3"
fnv-plus "^1.3.1"
lodash.isequalwith "^4.4.0"
lodash.pick "^4.4.0"
lodash.pickby "^4.6.0"
openapi3-ts "^2.0.1"
postman-collection "^4.1.0"
openapi3-ts "^2.0.2"
postman-collection "^4.1.2"
tslib "^2.3.1"
type-is "^1.6.18"

Expand Down Expand Up @@ -2044,7 +2049,7 @@
"@types/json-schema" "^7.0.7"
json-pointer "^0.6.1"

"@stoplight/json@^3.18.0", "@stoplight/json@^3.18.1":
"@stoplight/json@^3.18.1":
version "3.18.1"
resolved "https://registry.yarnpkg.com/@stoplight/json/-/json-3.18.1.tgz#725b34b24e8b0c0f73113362be54c7a4f294cdba"
integrity sha512-QmELAqBS8DC+8YuG7+OvDVP6RaUVi8bzN0KKW2UEcZg+0a1sqeeZgfW079AmJIZg8HEN7udAt4iozIB8Dm0t1Q==
Expand Down Expand Up @@ -2073,6 +2078,14 @@
"@types/json-schema" "^7.0.4"
utility-types "^3.10.0"

"@stoplight/types@^13.6.0":
version "13.6.0"
resolved "https://registry.yarnpkg.com/@stoplight/types/-/types-13.6.0.tgz#96c6aaae05858b36f589821cd52c95aa9b205ce7"
integrity sha512-dzyuzvUjv3m1wmhPfq82lCVYGcXG0xUYgqnWfCq3PCVR4BKFhjdkHrnJ+jIDoMKvXb05AZP/ObQF6+NpDo29IQ==
dependencies:
"@types/json-schema" "^7.0.4"
utility-types "^3.10.0"

"@stoplight/[email protected]":
version "0.0.48"
resolved "https://registry.yarnpkg.com/@stoplight/yaml-ast-parser/-/yaml-ast-parser-0.0.48.tgz#442b21f419427acaa8a3106ebc5d73351c407002"
Expand Down Expand Up @@ -2196,10 +2209,10 @@
jest-diff "^27.0.0"
pretty-format "^27.0.0"

"@types/[email protected].5":
version "7.0.5"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.5.tgz#dcce4430e64b443ba8945f0290fb564ad5bac6dd"
integrity sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==
"@types/[email protected].11":
version "7.0.11"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==

"@types/json-schema@^7.0.3", "@types/json-schema@^7.0.7":
version "7.0.7"
Expand Down Expand Up @@ -2326,7 +2339,7 @@
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff"
integrity sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==

"@types/swagger-schema-official@~2.0.21":
"@types/swagger-schema-official@~2.0.22":
version "2.0.22"
resolved "https://registry.yarnpkg.com/@types/swagger-schema-official/-/swagger-schema-official-2.0.22.tgz#f7e06168e6994574dfd86928ac04b196870ab043"
integrity sha512-7yQiX6MWSFSvc/1wW5smJMZTZ4fHOd+hqLr3qr/HONDxHEa2bnYAsOcGBOEqFIjd4yetwMOdEDdeW+udRAQnHA==
Expand Down Expand Up @@ -7181,12 +7194,12 @@ ono@^4.0.11:
dependencies:
format-util "^1.0.3"

openapi3-ts@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/openapi3-ts/-/openapi3-ts-2.0.1.tgz#b270aecea09e924f1886bc02a72608fca5a98d85"
integrity sha512-v6X3iwddhi276siej96jHGIqTx3wzVfMTmpGJEQDt7GPI7pI6sywItURLzpEci21SBRpPN/aOWSF5mVfFVNmcg==
openapi3-ts@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/openapi3-ts/-/openapi3-ts-2.0.2.tgz#a200dd838bf24c9086c8eedcfeb380b7eb31e82a"
integrity sha512-TxhYBMoqx9frXyOgnRHufjQfPXomTIHYKhSKJ6jHfj13kS8OEIhvmE8CTuQyKtjjWttAjX5DPxM1vmalEpo8Qw==
dependencies:
yaml "^1.10.0"
yaml "^1.10.2"

opencollective-postinstall@^2.0.2:
version "2.0.2"
Expand Down Expand Up @@ -7573,12 +7586,12 @@ postcss@^8.0.2:
picocolors "^1.0.0"
source-map-js "^1.0.2"

postman-collection@^4.1.0:
version "4.1.2"
resolved "https://registry.yarnpkg.com/postman-collection/-/postman-collection-4.1.2.tgz#977f702a68d680743628938259d72e31f3ff476f"
integrity sha512-nRYgzeo2VwQZZXF8YUMUvG8wKXPmjQ+BZPMXix+tNRWBHWAdqa191AwBL80LQxvHzECYp8Lp1JXMpg4OMXHLnw==
postman-collection@^4.1.2:
version "4.1.5"
resolved "https://registry.yarnpkg.com/postman-collection/-/postman-collection-4.1.5.tgz#7aad6aa9e1694d0bce058cee4ac40427fe541ca8"
integrity sha512-BY3NfP7EYExZG5ER9P82r0ZRc17z88WZAzn121EpWC8FM3HYtFwWJpXOsZk+2MKFn3agCq4JPRhnWw3G6XBXgw==
dependencies:
"@faker-js/faker" "6.0.0"
"@faker-js/faker" "5.5.3"
file-type "3.9.0"
http-reasons "0.1.0"
iconv-lite "0.6.3"
Expand All @@ -7587,7 +7600,7 @@ postman-collection@^4.1.0:
mime-format "2.0.1"
mime-types "2.1.35"
postman-url-encoder "3.0.5"
semver "7.3.5"
semver "7.3.7"
uuid "8.3.2"

[email protected]:
Expand Down Expand Up @@ -8098,10 +8111,10 @@ semver-regex@^3.1.2:
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==

[email protected].5, semver@^7.1.1, semver@^7.1.3, semver@^7.3.4, semver@^7.3.5:
version "7.3.5"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
[email protected].7, semver@^7.0.0, semver@^7.3.7:
version "7.3.7"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f"
integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==
dependencies:
lru-cache "^6.0.0"

Expand All @@ -8117,10 +8130,10 @@ semver@^6.0.0, semver@^6.3.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==

semver@^7.0.0, semver@^7.3.7:
version "7.3.7"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f"
integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==
semver@^7.1.1, semver@^7.1.3, semver@^7.3.4, semver@^7.3.5:
version "7.3.5"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
dependencies:
lru-cache "^6.0.0"

Expand Down Expand Up @@ -9337,7 +9350,7 @@ yallist@^4.0.0:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==

yaml@^1.10.0:
yaml@^1.10.0, yaml@^1.10.2:
version "1.10.2"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
Expand Down

0 comments on commit ebbc6c1

Please sign in to comment.