Skip to content

Commit

Permalink
fix: 1917 fixed handling of example request for invalid requests
Browse files Browse the repository at this point in the history
  • Loading branch information
Łukasz Kużyński committed Oct 18, 2021
1 parent 1b73f8f commit 444012b
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 8 deletions.
23 changes: 15 additions & 8 deletions packages/http/src/mocker/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import {
findContentByMediaTypeOrFirst,
splitUriParams,
} from '../validator/validators/body';
import { NonEmptyArray } from 'fp-ts/NonEmptyArray';
import * as NEA from 'fp-ts/NonEmptyArray';

const eitherRecordSequence = Record.sequence(E.Applicative);
const eitherSequence = sequenceT(E.Apply);
Expand Down Expand Up @@ -71,8 +71,8 @@ const mock: IPrismComponents<IHttpOperation, IHttpRequest, IHttpResponse, IHttpM
R.chain(result => assembleResponse(result, payloadGenerator)),
R.chain(response =>
/* Note: This is now just logging the errors without propagating them back. This might be moved as a first
level concept in Prism.
*/
level concept in Prism.
*/
logger =>
pipe(
response,
Expand Down Expand Up @@ -147,17 +147,24 @@ function parseBodyIfUrlEncoded(request: IHttpRequest, resource: IHttpOperation)
}

export function createInvalidInputResponse(
failedValidations: NonEmptyArray<IPrismDiagnostic>,
failedValidations: NEA.NonEmptyArray<IPrismDiagnostic>,
responses: IHttpOperationResponse[],
exampleKey?: string
mockConfig: IHttpOperationConfig
): R.Reader<Logger, E.Either<ProblemJsonError, IHttpNegotiationResult>> {
const securityValidation = failedValidations.find(validation => validation.code === 401);

const expectedCodes: NEA.NonEmptyArray<number> = securityValidation ? [401] : [422, 400];
const isExampleKeyFromExpectedCodes = !!mockConfig.code && expectedCodes.includes(mockConfig.code);

return pipe(
withLogger(logger => logger.warn({ name: 'VALIDATOR' }, 'Request did not pass the validation rules')),
R.chain(() =>
pipe(
helpers.negotiateOptionsForInvalidRequest(responses, securityValidation ? [401] : [422, 400], exampleKey),
helpers.negotiateOptionsForInvalidRequest(
responses,
expectedCodes,
isExampleKeyFromExpectedCodes ? mockConfig.exampleKey : undefined
),
RE.mapLeft(error => {
if (error instanceof ProblemJsonError && error.status === 404) {
return error;
Expand All @@ -178,7 +185,7 @@ export const createUnauthorisedResponse = (tags?: string[]): ProblemJsonError =>
tags && tags.length ? { headers: { 'WWW-Authenticate': tags.join(',') } } : undefined
);

export const createUnprocessableEntityResponse = (validations: NonEmptyArray<IPrismDiagnostic>): ProblemJsonError =>
export const createUnprocessableEntityResponse = (validations: NEA.NonEmptyArray<IPrismDiagnostic>): ProblemJsonError =>
ProblemJsonError.fromTemplate(
UNPROCESSABLE_ENTITY,
'Your request is not valid and no HTTP validation response was found in the spec, so Prism is generating this error for you.',
Expand All @@ -203,7 +210,7 @@ function negotiateResponse(
);

if (errors && A.isNonEmpty(input.validations)) {
return createInvalidInputResponse(input.validations, resource.responses, mockConfig.exampleKey);
return createInvalidInputResponse(input.validations, resource.responses, mockConfig);
} else {
return pipe(
withLogger(logger => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
====test====
If Prism detects an invalid input (422 code), but user requests for other code (200) with an example key then example key and requested code are ignored
====spec====
openapi: 3.1.0
info:
title: test
version: '1.0'
servers:
- url: 'http://localhost:3000'
paths:
/test:
post:
summary: ''
operationId: post-test
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
name:
type: string
examples:
200-test:
value:
name: 200-test
'422':
description: Unprocessable Entity (WebDAV)
content:
application/json:
schema:
type: object
properties:
name:
type: string
examples:
422-test:
value:
name: 422-test
422-test2:
value:
name: 422-test2
requestBody:
content:
application/json:
schema:
type: object
properties:
test:
type: string
required:
- test
====server====
mock -p 4010 ${document} --errors
====command====
curl --request POST --url 'http://localhost:4010/test' \
--header 'Content-Type: application/json' \
--header 'Prefer: code=200, example=200-test' \
--data '{}'
====expect====
HTTP/1.1 422 Unauthorized
sl-violations: [{"location":["request","body"],"severity":"Error","code":"required","message":"must have required property 'test'"}]

{"name":"422-test"}

0 comments on commit 444012b

Please sign in to comment.