Skip to content

Commit

Permalink
Merge pull request #7690 from obrien-k/express
Browse files Browse the repository at this point in the history
Recommend express.json() instead of body-parser
  • Loading branch information
Meschreiber committed Oct 18, 2023
2 parents 040808b + c142fca commit 8135ad9
Show file tree
Hide file tree
Showing 10 changed files with 29 additions and 40 deletions.
2 changes: 1 addition & 1 deletion docs/source/api/apollo-server.mdx
Expand Up @@ -519,7 +519,7 @@ await server.start();
app.use(
'/graphql',
cors<cors.CorsRequest>(),
json(),
express.json(),
expressMiddleware(server),
);
```
Expand Down
10 changes: 4 additions & 6 deletions docs/source/api/express-middleware.mdx
Expand Up @@ -13,7 +13,7 @@ This API reference documents Apollo Server 4's [Express](https://expressjs.com/)

The `expressMiddleware` function enables you to attach Apollo Server to an Express server.

The `expressMiddleware` function expects you to set up HTTP body parsing and CORS headers for your web framework. Specifically, you should install the [`body-parser`](https://www.npmjs.com/package/body-parser) and [`cors`](https://www.npmjs.com/package/cors) packages and use them to set up your Express app, as shown below.
The `expressMiddleware` function expects you to set up HTTP body parsing and CORS headers for your web framework. Specifically, you can use the native [`express.json()`](https://expressjs.com/en/api.html#express.json) function (available in Express `v4.16.0` onwards) and the [`cors`](https://www.npmjs.com/package/cors) package to set up your Express app, as shown below.

> See [Configuring CORS](../security/cors#specifying-origins) for guidance on configuring the CORS behavior of your project.
Expand All @@ -25,7 +25,6 @@ The `expressMiddleware` function accepts two arguments. The first **required** a
import { ApolloServer } from '@apollo/server';
import { expressMiddleware } from '@apollo/server/express4';
import cors from 'cors';
import { json } from 'body-parser';
import express from 'express';

const app = express();
Expand All @@ -43,7 +42,7 @@ await server.start();
app.use(
'/graphql',
cors<cors.CorsRequest>(),
json(),
express.json(),
expressMiddleware(server),
);
//highlight-end
Expand Down Expand Up @@ -96,14 +95,13 @@ Below is a full example of setting up `expressMiddleware`:
<MultiCodeBlock>

```ts
// npm install @apollo/server express graphql cors body-parser
// npm install @apollo/server express graphql cors
import { ApolloServer } from '@apollo/server';
import { expressMiddleware } from '@apollo/server/express4';
import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer';
import express from 'express';
import http from 'http';
import cors from 'cors';
import bodyParser from 'body-parser';
import { typeDefs, resolvers } from './schema';

interface MyContext {
Expand Down Expand Up @@ -132,7 +130,7 @@ await server.start();
app.use(
'/',
cors<cors.CorsRequest>(),
bodyParser.json(),
express.json(),
// expressMiddleware accepts the same arguments:
// an Apollo Server instance and optional configuration options
expressMiddleware(server, {
Expand Down
3 changes: 1 addition & 2 deletions docs/source/api/plugin/drain-http-server.mdx
Expand Up @@ -36,7 +36,6 @@ import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHt
import express from 'express';
import http from 'http';
import cors from 'cors';
import { json } from 'body-parser';
import { typeDefs, resolvers } from './schema';

interface MyContext {
Expand All @@ -59,7 +58,7 @@ await server.start();
app.use(
'/graphql',
cors<cors.CorsRequest>(),
json(),
express.json(),
expressMiddleware(server, {
context: async ({ req }) => ({ token: req.headers.token }),
}),
Expand Down
7 changes: 3 additions & 4 deletions docs/source/api/standalone.mdx
Expand Up @@ -150,25 +150,24 @@ console.log(`馃殌 Server ready at ${url}`);
```
</MultiCodeBlock>

To swap to using `expressMiddleware`, you'll first need to install the following packages so you'll be able to set up HTTP body parsing and CORS for your server:
To swap to using `expressMiddleware`, you'll first need to install the following packages so you'll be able to set up CORS for your server:

```bash
npm install express cors body-parser
npm install express cors
```

Next, we can modify our code to match the following:

<MultiCodeBlock>

```ts
// npm install @apollo/server express graphql cors body-parser
// npm install @apollo/server express graphql cors
import { ApolloServer } from '@apollo/server';
import { expressMiddleware } from '@apollo/server/express4';
import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer';
import express from 'express';
import http from 'http';
import cors from 'cors';
import bodyParser from 'body-parser';
import { typeDefs, resolvers } from './schema';

interface MyContext {
Expand Down
3 changes: 1 addition & 2 deletions docs/source/data/subscriptions.mdx
Expand Up @@ -146,7 +146,6 @@ import express from 'express';
import { makeExecutableSchema } from '@graphql-tools/schema';
import { WebSocketServer } from 'ws';
import { useServer } from 'graphql-ws/lib/use/ws';
import bodyParser from 'body-parser';
import cors from 'cors';
import resolvers from './resolvers';
import typeDefs from './typeDefs';
Expand Down Expand Up @@ -192,7 +191,7 @@ await server.start();
app.use(
'/graphql',
cors<cors.CorsRequest>(),
bodyParser.json(),
express.json(),
expressMiddleware(server),
);

Expand Down
6 changes: 2 additions & 4 deletions docs/source/deployment/lambda.mdx
Expand Up @@ -473,7 +473,6 @@ const { ApolloServer } = require('@apollo/server');
const { expressMiddleware } = require('@apollo/server/express4');
const serverlessExpress = require('@vendia/serverless-express');
const express = require('express');
const { json } = require('body-parser');
const cors = require('cors');

const server = new ApolloServer({
Expand All @@ -486,7 +485,7 @@ server.startInBackgroundHandlingStartupErrorsByLoggingAndFailingAllRequests();
const app = express();
app.use(
cors(),
json(),
express.json(),
expressMiddleware(server, {
// The Express request and response objects are passed into
// your context initialization function
Expand Down Expand Up @@ -523,7 +522,6 @@ const { ApolloServer } = require('@apollo/server');
const { expressMiddleware } = require('@apollo/server/express4');
const serverlessExpress = require('@vendia/serverless-express');
const express = require('express');
const { json } = require('body-parser');
const cors = require('cors');

const server = new ApolloServer({
Expand All @@ -534,7 +532,7 @@ const server = new ApolloServer({
server.startInBackgroundHandlingStartupErrorsByLoggingAndFailingAllRequests();

const app = express();
app.use(cors(), json(), expressMiddleware(server));
app.use(cors(), express.json(), expressMiddleware(server));

exports.graphqlHandler = serverlessExpress({ app });
```
Expand Down
18 changes: 8 additions & 10 deletions docs/source/migration.mdx
Expand Up @@ -64,7 +64,7 @@ If there is no Apollo Server integration for your favorite framework _yet_, help
Below are a few high-level changes for using framework integrations:

- You can pass your [`context` initialization function](#context-initialization-function) directly to your framework's integration function (e.g., `expressMiddleware` or `startStandaloneServer`) instead of the `ApolloServer` constructor.
- You are responsible for [setting up HTTP body parsing and CORS](#body-parser-and-cors) using your framework integration's standard functionality.
- You are responsible for [setting up HTTP body parsing and CORS](#http-body-parsing-and-cors) using your framework integration's standard functionality.
- If you want your server to listen on a specific URL path, pass that path directly to your framework's router instead of using the [`path` option](#path-parsing). If you did not specify a URL path, the default in Apollo Server 3 was `/graphql`, so to preserve existing behavior, you should specify that path explicitly.

The following sections show how servers using `apollo-server` or `apollo-server-express` can update to Apollo Server 4.
Expand Down Expand Up @@ -189,9 +189,9 @@ If you used the `apollo-server-express` package in Apollo Server 3, use the `exp

To migrate from Apollo Server 3's `apollo-server-express` package to using the `expressMiddleware` function, do the following:

1. Install the `@apollo/server`, `cors`, and `body-parser` packages.
1. Install the `@apollo/server` and `cors` packages.
2. Import symbols from `@apollo/server` (i.e., instead of from `apollo-server-express` and `apollo-server-core`).
3. Add `cors` and `bodyParser.json()` to your server setup.
3. Add `cors` to your server setup.
4. Remove the Apollo Server 3 `apollo-server-express` and `apollo-server-core` packages.
5. If you are using `apollo-server-express`'s default `/graphql` URL path (i.e., not specifying another URL with the [path option](/apollo-server/v3/api/apollo-server/#path)), you can mount `expressMiddleware` at `/graphql` to maintain behavior. To use another URL path, mount your server (with `app.use`) at the specified path.

Expand Down Expand Up @@ -232,15 +232,13 @@ looks like this in Apollo Server 4:
<MultiCodeBlock>

```ts title="apollo-server-4.ts"
// npm install @apollo/server express graphql cors body-parser
// npm install @apollo/server express graphql cors
import { ApolloServer } from '@apollo/server';
import { expressMiddleware } from '@apollo/server/express4';
import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer';
import express from 'express';
import http from 'http';
import cors from 'cors';
import pkg from 'body-parser';
const { json } = pkg;
import { typeDefs, resolvers } from './schema';

interface MyContext {
Expand All @@ -257,7 +255,7 @@ const server = new ApolloServer<MyContext>({
await server.start();
app.use('/graphql',
cors<cors.CorsRequest>(),
json(),
express.json(),
expressMiddleware(server, {
context: async ({ req }) => ({ token: req.headers.token }),
}),
Expand Down Expand Up @@ -910,11 +908,11 @@ In Apollo Server 4, you should use your framework's routing feature to mount you

> Apollo Server 3's batteries-included `apollo-server` package, replaced by `startStandaloneServer` in Apollo Server 4, serves all URLs (i.e., rather than only listening on `/graphql`).
### `body-parser` and `cors`
### HTTP body parsing and CORS

In Apollo Server 3, framework integrations automatically set up HTTP body parsing and CORS response headers. You can customize your integration's CORS or body parsing functionality using the Apollo Server API; these configuration options [vary by integration](/apollo-server/v3/api/apollo-server#cors-1).

In Apollo Server 4, it's your responsibility to set up HTTP body parsing and CORS headers for your web framework. Specifically, when using [`expressMiddleware`](#migrate-from-apollo-server-express), you should install the `body-parser` and `cors` npm packages and use them in your Express app, just like with any other JSON-based API server. If you passed a `cors` option to `applyMiddleware` or `getMiddleware`, pass the same value to the `cors` function. If you passed a `bodyParserConfig` option to `applyMiddleware` or `getMiddleware`, pass the same value to the `body-parser` package's `json` function.
In Apollo Server 4, it's your responsibility to set up HTTP body parsing and CORS headers for your web framework. Specifically, when using [`expressMiddleware`](#migrate-from-apollo-server-express), you can use the native [`express.json()`](https://expressjs.com/en/api.html#express.json) function (available in Express `v4.16.0` onwards) for body parsing and the `cors` npm package for CORS headers. You can install use the `cors` package in your Express app, just like with any other JSON-based API server. If you passed a `cors` option to `applyMiddleware` or `getMiddleware`, pass the same value to the `cors` function. If you passed a `bodyParserConfig` option to `applyMiddleware` or `getMiddleware`, pass the same value to the [`express.json()`](https://expressjs.com/en/api.html#express.json) function.

Note that [`startStandaloneServer`](#migrate-from-apollo-server) sets up body parsing and CORS functionality for you, but you can't configure this behavior. In Apollo Server 3, you could configure the batteries-included `apollo-server`'s CORS behavior via the `cors` constructor option. In Apollo Server 4, if you need to configure CORS behavior, use `expressMiddleware` rather than `startStandaloneServer`.

Expand Down Expand Up @@ -1106,7 +1104,7 @@ Whereas this query would be invalid:
If you'd like to restore the previous behavior, you can `JSON.parse` the `variables` and `extensions` fields after your framework has parsed the request body. In Express that might look like:

```ts
app.use(json());
app.use(express.json());
app.use((req, res, next) => {
if (typeof req.body?.variables === 'string') {
try {
Expand Down
8 changes: 4 additions & 4 deletions docs/source/monitoring/health-checks.mdx
Expand Up @@ -3,7 +3,7 @@ title: Health checks
description: Determining the health status of Apollo Server
---

> **Apollo Server 4 no longer [supports built-in health checks](../migration/#health-checks)**. Instead, we recommend performing [GraphQL-level health checks](#graphql-level-health-checks) to ensure your server successfully serves traffic _and_ performs GraphQL operations.
> **Apollo Server 4 no longer [supports built-in health checks](../migration/#health-checks)**. Instead, we recommend performing [GraphQL-level health checks](#graphql-level-health-checks) to ensure your server successfully serves traffic _and_ performs GraphQL operations.
Load balancers often use health checks to determine if a server is available and ready to serve traffic.

Expand All @@ -21,7 +21,7 @@ Note that this health check will run an actual GraphQL operation. If your server

> Sending an `apollo-require-preflight: true` header alongside your health check ensures that Apollo Server's [CSRF prevention](../security/cors/#preventing-cross-site-request-forgery-csrf) feature won't block it.
If you want to create a health check for your HTTP server that is _unrelated_ to the health of the GraphQL execution engine (i.e., such as [Apollo Server 3's health check feature](/apollo-server/v3/monitoring/health-checks)), you can add a `GET` handler that always succeeds to your web framework.
If you want to create a health check for your HTTP server that is _unrelated_ to the health of the GraphQL execution engine (i.e., such as [Apollo Server 3's health check feature](/apollo-server/v3/monitoring/health-checks)), you can add a `GET` handler that always succeeds to your web framework.

Below is an example of an HTTP server health check with [`expressMiddleware`](../api/express-middleware/):

Expand All @@ -39,7 +39,7 @@ const server = new ApolloServer({
await server.start();
app.use('/graphql',
cors<cors.CorsRequest>(),
json(),
express.json(),
expressMiddleware(server)
);
await new Promise<void>(resolve => app.listen({ port: 4000 }, resolve));
Expand All @@ -56,4 +56,4 @@ app.get('/health', (req, res) => {

</MultiCodeBlock>

> If you are using `startStandaloneServer`, you must first [swap to using the `expressMiddleware` function](../api/standalone/#swapping-to-expressmiddleware) before creating an HTTP server health check.
> If you are using `startStandaloneServer`, you must first [swap to using the `expressMiddleware` function](../api/standalone/#swapping-to-expressmiddleware) before creating an HTTP server health check.
9 changes: 4 additions & 5 deletions docs/source/security/cors.mdx
Expand Up @@ -86,7 +86,7 @@ If you create a public API or an API to embed in websites you don't control your
If your application doesn't fit into any of the above categories, [`startStandaloneServer`](../api/standalone)'s CORS behavior should suit your use case. You can always choose to swap to another Apollo Server integration later to [customize your CORS configuration](#configuring-cors-options-for-apollo-server).

## Configuring CORS options for Apollo Server
> 馃摚 **New in Apollo Server 4**: if you are using an Apollo Server integration (e.g., [`expressMiddleware`](../api/express-middleware)), you are responsible for [setting up CORS for your web framework](../migration#body-parser-and-cors).
> 馃摚 **New in Apollo Server 4**: if you are using an Apollo Server integration (e.g., [`expressMiddleware`](../api/express-middleware)), you are responsible for [setting up CORS for your web framework](../migration#http-body-parsing-and-cors).
Apollo Server's standalone server (i.e., [`startStandaloneServer`](../api/standalone)) serves the `Access-Control-Allow-Origin` HTTP header with the wildcard value (`*`). This allows scripts on any origin to make requests, _without cookies_, to the server and read its responses.

Expand All @@ -104,7 +104,6 @@ import { expressMiddleware } from '@apollo/server/express4';
import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer';
import express from 'express';
import http from 'http';
import { json } from 'body-parser';
import { typeDefs, resolvers } from './schema';
// highlight-start
import cors from 'cors';
Expand All @@ -125,7 +124,7 @@ app.use(
// highlight-start
cors<cors.CorsRequest>({ origin: ['https://www.your-app.example', 'https://studio.apollographql.com'] }),
// highlight-end
json(),
express.json(),
expressMiddleware(server),
);

Expand All @@ -137,7 +136,7 @@ console.log(`馃殌 Server ready at http://localhost:4000/graphql`);

> Invoking the `cors` function with no arguments sets your server's `Access-Control-Allow-Origin` HTTP header to the wildcard value (`*`), allowing scripts on any origin to make requests. So, your server would have the same CORS behavior as `startStandaloneServer`.
Using the `cors` package directly, we can configure the `Access-Control-Allow-Origin` header using the [`origin` option](https://github.com/expressjs/cors#configuration-options). The example above enables CORS requests from `https://www.your-app.example`, along with `https://studio.apollographql.com`.
Using the `cors` package directly, we can configure the `Access-Control-Allow-Origin` header using the [`origin` option](https://github.com/expressjs/cors#configuration-options). The example above enables CORS requests from `https://www.your-app.example`, along with `https://studio.apollographql.com`.

> If you want to use [Apollo Studio Explorer](https://www.apollographql.com/docs/studio/explorer/explorer/) as a GraphQL web IDE, you should include `https://studio.apollographql.com` in your list of valid origins. However, if you plan to embed the [Explorer](https://www.apollographql.com/docs/studio/explorer/embed-explorer/) or use [Apollo Sandbox](https://www.apollographql.com/docs/studio/explorer/sandbox), you *don't* need to specify Studio's URL in your CORS origins because requests will go through the page embedding Studio.
Expand Down Expand Up @@ -170,7 +169,7 @@ app.use(
credentials: true,
}),
// highlight-end
json(),
express.json(),
expressMiddleware(server),
);
```
Expand Down
3 changes: 1 addition & 2 deletions docs/source/security/terminating-ssl.mdx
Expand Up @@ -21,7 +21,6 @@ import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHt
import typeDefs from './graphql/schema';
import resolvers from './graphql/resolvers';
import cors from 'cors';
import bodyParser from 'body-parser';
import express from 'express';
import http from 'http';
import https from 'https';
Expand All @@ -47,7 +46,7 @@ const app = express();
app.use(
'/graphql',
cors<cors.CorsRequest>(),
bodyParser.json(),
express.json(),
expressMiddleware(server),
);

Expand Down

0 comments on commit 8135ad9

Please sign in to comment.