From ce6d24655eb3c59d9a506baf09dbe185da9a8b2b Mon Sep 17 00:00:00 2001 From: Nicolas Escalante Date: Sun, 18 Jun 2023 20:22:01 -0300 Subject: [PATCH] do not overwrite existing status on validation, if any (#2872) * do not overwrite existing status on validation, if any * add changeset * add unit test * fix one more case and add test to validate * lint fixes --- .changeset/purple-ravens-train.md | 5 ++ .../use-http-validation-error.spec.ts | 61 +++++++++++++++++++ .../use-http-validation-error.ts | 5 +- 3 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 .changeset/purple-ravens-train.md create mode 100644 packages/graphql-yoga/src/plugins/request-validation/use-http-validation-error.spec.ts diff --git a/.changeset/purple-ravens-train.md b/.changeset/purple-ravens-train.md new file mode 100644 index 0000000000..fa278cefa0 --- /dev/null +++ b/.changeset/purple-ravens-train.md @@ -0,0 +1,5 @@ +--- +'graphql-yoga': patch +--- + +Avoid overriding http status on extensions when using a plugin that modifies error prop diff --git a/packages/graphql-yoga/src/plugins/request-validation/use-http-validation-error.spec.ts b/packages/graphql-yoga/src/plugins/request-validation/use-http-validation-error.spec.ts new file mode 100644 index 0000000000..c819dd8fac --- /dev/null +++ b/packages/graphql-yoga/src/plugins/request-validation/use-http-validation-error.spec.ts @@ -0,0 +1,61 @@ +import { AfterValidateEventPayload } from '@envelop/core' +import { createSchema } from '../../schema.js' +import { createYoga } from '../../server.js' + +describe('useHTTPValidationError', () => { + describe('when doing a request with an invalid query', () => { + it('does not overrite status code set on custom plugin', async () => { + const schemaFactory = async () => { + return createSchema({ + typeDefs: /* GraphQL */ ` + type Query { + foo: String + } + `, + resolvers: { + Query: { + foo: () => 'bar', + }, + }, + }) + } + const yoga = createYoga({ + schema: schemaFactory, + plugins: [ + { + onValidate() { + return ({ + valid, + result, + }: // eslint-disable-next-line @typescript-eslint/no-explicit-any + AfterValidateEventPayload>) => { + if (!valid) { + for (const error of result) { + error.extensions.http = { + status: 400, + spec: false, + headers: { + 'custom-header': 'custom-value', + }, + } + } + } + } + }, + }, + ], + }) + const result = await yoga.fetch('http://yoga/graphql', { + method: 'POST', + body: JSON.stringify({ + query: 'query{bar}', + }), + headers: { + 'Content-Type': 'application/json', + }, + }) + expect(result.status).toEqual(400) + expect(result.headers.get('custom-header')).toEqual('custom-value') + }) + }) +}) diff --git a/packages/graphql-yoga/src/plugins/request-validation/use-http-validation-error.ts b/packages/graphql-yoga/src/plugins/request-validation/use-http-validation-error.ts index 4366b3ddf3..eb196d88df 100644 --- a/packages/graphql-yoga/src/plugins/request-validation/use-http-validation-error.ts +++ b/packages/graphql-yoga/src/plugins/request-validation/use-http-validation-error.ts @@ -10,8 +10,9 @@ export function useHTTPValidationError< if (!valid) { for (const error of result) { error.extensions.http = { - spec: true, - status: 400, + ...error.extensions.http, + spec: error.extensions.http?.spec ?? true, + status: error.extensions.http?.status ?? 400, } } }