diff --git a/.changeset/stale-ligers-impress.md b/.changeset/stale-ligers-impress.md new file mode 100644 index 00000000000..4a3def4a2c3 --- /dev/null +++ b/.changeset/stale-ligers-impress.md @@ -0,0 +1,5 @@ +--- +'@apollo/server': patch +--- + +startStandaloneServer: Restore body-parser request limit to 50mb (as it was in the `apollo-server` package in Apollo Server 3) diff --git a/docs/source/api/standalone.mdx b/docs/source/api/standalone.mdx index dfb9d1b84fb..ec81e57e019 100644 --- a/docs/source/api/standalone.mdx +++ b/docs/source/api/standalone.mdx @@ -9,7 +9,7 @@ This API reference documents the `startStandaloneServer` function. ## Overview -This `startStandaloneServer` function helps you get started with Apollo Server quickly. This function is recommended for all projects that don't require serverless support or a particular Node.js framework (such as Fastify). Under the hood, the `startStandaloneServer` function uses Apollo Server 4's Express integration (i.e., [`expressMiddleware`](./express-middleware)). +This `startStandaloneServer` function helps you get started with Apollo Server quickly. This function is recommended for all projects that don't require serverless support or a particular Node.js framework (such as Fastify). Under the hood, the `startStandaloneServer` function uses Apollo Server 4's Express integration (i.e., [`expressMiddleware`](./express-middleware)). Because it sets helpful defaults, this function is less configurable than other Apollo Server integrations. Complex projects might eventually need to [swap to using `expressMiddleware`](#swapping-to-expressmiddleware) (this process is straightforward). @@ -30,7 +30,7 @@ const server = new ApolloServer({ typeDefs, resolvers }); // `startStandaloneServer` returns a `Promise` with the // the URL that the server is listening on. const { url } = await startStandaloneServer(server); //highlight-line -``` +``` @@ -59,7 +59,7 @@ The `startStandaloneServer` function's second optional argument is an object for -An optional asynchronous [`context` initialization function](../data/resolvers#the-context-argument). +An optional asynchronous [`context` initialization function](../data/resolvers#the-context-argument). The `context` function should return an object that all your server's resolvers share during an operation's execution. This enables resolvers to share helpful context values, such as a database connection. @@ -91,7 +91,7 @@ If no `port` is specified, this defaults to using `{port: 4000}`. -### Example +### Example Below is a full example of setting up `startStandaloneServer`: @@ -196,7 +196,8 @@ await server.start(); // and our expressMiddleware function. app.use('/', cors(), - bodyParser.json(), + // 50mb is the limit that `startStandaloneServer` uses, but you may configure this to suit your needs + bodyParser.json({ limit: '50mb' }), // expressMiddleware accepts the same arguments: // an Apollo Server instance and optional configuration options expressMiddleware(server, { @@ -208,4 +209,4 @@ app.use('/', await new Promise(resolve => httpServer.listen({ port: 4000 }, resolve)); console.log(`🚀 Server ready at http://localhost:4000/`); ``` - \ No newline at end of file + diff --git a/packages/server/src/__tests__/standalone/standaloneSpecific.test.ts b/packages/server/src/__tests__/standalone/standaloneSpecific.test.ts index cb4b639ee5e..1f3231c376a 100644 --- a/packages/server/src/__tests__/standalone/standaloneSpecific.test.ts +++ b/packages/server/src/__tests__/standalone/standaloneSpecific.test.ts @@ -1,6 +1,7 @@ +import { describe, expect, it } from '@jest/globals'; +import fetch from 'node-fetch'; import { ApolloServer } from '../..'; import { startStandaloneServer } from '../../standalone'; -import { describe, it } from '@jest/globals'; describe('Typings: TContext inference', () => { it('correctly infers BaseContext when no `context` function is provided', async () => { @@ -103,3 +104,41 @@ describe('Typings: TContext inference', () => { await server.stop(); }); }); + +describe('Configuration', () => { + it('allows > 100KiB bodies to be sent (body-parser default)', async () => { + const server = new ApolloServer({ + typeDefs: `type Query { hello: String }`, + resolvers: { + Query: { + hello: () => 'hello world!', + }, + }, + }); + + const { url } = await startStandaloneServer(server, { + listen: { port: 0 }, + }); + + const excessivelyLargeBody = JSON.stringify({ + query: `{hello}`, + variables: { foo: 'a'.repeat(102400) }, + }); + + // 100kib limit = 102400 bytes + expect(Buffer.byteLength(excessivelyLargeBody)).toBeGreaterThan(102400); + + const result = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: excessivelyLargeBody, + }); + const { data } = await result.json(); + + expect(data.hello).toEqual('hello world!'); + + await server.stop(); + }); +}); diff --git a/packages/server/src/standalone/index.ts b/packages/server/src/standalone/index.ts index 7f50f4f95c0..b2525933340 100644 --- a/packages/server/src/standalone/index.ts +++ b/packages/server/src/standalone/index.ts @@ -56,7 +56,11 @@ export async function startStandaloneServer( await server.start(); const context = options?.context ?? (async () => ({} as TContext)); - app.use(cors(), bodyParser.json(), expressMiddleware(server, { context })); + app.use( + cors(), + bodyParser.json({ limit: '50mb' }), + expressMiddleware(server, { context }), + ); const listenOptions = options?.listen ?? { port: 4000 }; // Wait for server to start listening