From 3ae3f737212369a56bee0d49ae0365214585032e Mon Sep 17 00:00:00 2001 From: ayushvyas-dev Date: Tue, 1 Sep 2026 20:49:29 +0530 Subject: [PATCH 1/2] docs(express): document resolver response manipulation --- src/use/express.ts | 31 +++++++++++++++++++++-- tests/use.test.ts | 61 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 2 deletions(-) diff --git a/src/use/express.ts b/src/use/express.ts index 4098b52e..ba293988 100644 --- a/src/use/express.ts +++ b/src/use/express.ts @@ -11,6 +11,10 @@ import { RequestParams } from '../common'; /** * The context in the request for the handler. * + * The `res` property is the Express response object for the current request. + * It can be used to manipulate the HTTP response from the `context` option + * or from GraphQL resolvers, for example to set response headers or cookies. + * * @category Server/express */ export interface RequestContext { @@ -82,16 +86,39 @@ export type HandlerOptions = * Create a GraphQL over HTTP spec compliant request handler for * the express framework. * + * The Express response is available to GraphQL resolvers through + * `req.context.res`. This can be used to manipulate the HTTP response, + * for example to set response headers or cookies. + * * ```js * import express from 'express'; // yarn add express * import { createHandler } from 'graphql-http/lib/use/express'; * import { schema } from './my-graphql-schema'; * * const app = express(); - * app.all('/graphql', createHandler({ schema })); + * + * app.all( + * '/graphql', + * createHandler({ + * schema, + * context(req) { + * return { + * res: req.context.res, + * }; + * }, + * }), + * ); * * app.listen({ port: 4000 }); - * console.log('Listening to port 4000'); + * ``` + * + * A resolver can then manipulate the response: + * + * ```js + * resolve(_, __, { res }) { + * res.setHeader('set-cookie', 'session=; Max-Age=0; Path=/'); + * return true; + * } * ``` * * @category Server/express diff --git a/tests/use.test.ts b/tests/use.test.ts index 114da4d4..1df49873 100644 --- a/tests/use.test.ts +++ b/tests/use.test.ts @@ -1,4 +1,5 @@ import { describe, it, expect, beforeAll, afterAll } from 'vitest'; +import { GraphQLBoolean, GraphQLObjectType, GraphQLSchema } from 'graphql'; import net from 'net'; import { fetch } from '@whatwg-node/fetch'; import { serverAudits } from '../src/audits'; @@ -137,6 +138,66 @@ describe('express', () => { await dispose(); }); + + it('should allow manipulating the response from a resolver', async () => { + const responseSchema = new GraphQLSchema({ + query: new GraphQLObjectType({ + name: 'Query', + fields: { + hello: { + type: GraphQLBoolean, + resolve: () => true, + }, + }, + }), + mutation: new GraphQLObjectType({ + name: 'Mutation', + fields: { + logout: { + type: GraphQLBoolean, + resolve: (_, __, context) => { + context.res.setHeader('x-test', 'test-x'); + return true; + }, + }, + }, + }), + }); + + const app = express(); + + app.all( + '/', + createExpressHandler({ + schema: responseSchema, + context(req) { + return { + res: req.context.res, + }; + }, + }), + ); + + const [url, , dispose] = startDisposableServer(app.listen(0)); + + const res = await fetch(url, { + method: 'POST', + headers: { + 'content-type': 'application/json', + }, + body: JSON.stringify({ + query: 'mutation { logout }', + }), + }); + + await expect(res.text()).resolves.toMatchInlineSnapshot( + `"{\"data\":{\"logout\":true}}"`, + ); + + expect(res.headers.get('x-test')).toBe('test-x'); + + await dispose(); + }); }); describe('fastify', () => { From 7096011e4b68c7324898df2cc09c2f53994ee114 Mon Sep 17 00:00:00 2001 From: ayushvyas-dev Date: Fri, 4 Sep 2026 09:13:16 +0530 Subject: [PATCH 2/2] docs(express): clarify response context usage --- src/use/express.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/use/express.ts b/src/use/express.ts index ba293988..79d8d287 100644 --- a/src/use/express.ts +++ b/src/use/express.ts @@ -11,13 +11,15 @@ import { RequestParams } from '../common'; /** * The context in the request for the handler. * - * The `res` property is the Express response object for the current request. - * It can be used to manipulate the HTTP response from the `context` option - * or from GraphQL resolvers, for example to set response headers or cookies. - * * @category Server/express */ export interface RequestContext { + /** + * The Express response object for the current request. + * + * This can be used to manipulate the HTTP response, for example to set + * response headers or cookies. + */ res: Response; } @@ -86,9 +88,10 @@ export type HandlerOptions = * Create a GraphQL over HTTP spec compliant request handler for * the express framework. * - * The Express response is available to GraphQL resolvers through - * `req.context.res`. This can be used to manipulate the HTTP response, - * for example to set response headers or cookies. + * The Express response is available through `req.context.res`. To expose it + * to GraphQL resolvers, return it from the `context` option. This can be used + * to manipulate the HTTP response, for example to set response headers or + * cookies. * * ```js * import express from 'express'; // yarn add express