Skip to content

Commit 8638fa7

Browse files
innerdvationspwizlaremidej
authored
Add graphQL landingPage configuration and updates Playground → Sandbox (#2343)
* enhancement: add landingPage config * Fix broken anchor * Fix broken anchor * Fix broken anchor * Fix broken anchor * Add format around path * Simplify * Don't use positional words in docs (below → following) * Fix broken anchor * Update docusaurus/docs/dev-docs/plugins/graphql.md Co-authored-by: Rémi de Juvigny <[email protected]> * Update docusaurus/docs/dev-docs/plugins/graphql.md Co-authored-by: Rémi de Juvigny <[email protected]> --------- Co-authored-by: Pierre Wizla <[email protected]> Co-authored-by: Rémi de Juvigny <[email protected]>
1 parent 88e9a19 commit 8638fa7

File tree

1 file changed

+137
-18
lines changed

1 file changed

+137
-18
lines changed

docusaurus/docs/dev-docs/plugins/graphql.md

Lines changed: 137 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -53,35 +53,51 @@ npm install @strapi/plugin-graphql
5353

5454
</Tabs>
5555

56-
Then, start your app and open your browser at [http://localhost:1337/graphql](http://localhost:1337/graphql). You should now be able to access the **GraphQL Playground** that will help you to write your GraphQL queries and mutations.
56+
Then, start your app and open your browser at [http://localhost:1337/graphql](http://localhost:1337/graphql). You should now be able to access the **GraphQL Sandbox** that will help you to write your GraphQL queries and mutations.
5757

5858
:::note
59-
The GraphQL Playground is enabled by default for both the development and staging environments, but disabled in production environments. Set the `playgroundAlways` configuration option to `true` to also enable the GraphQL Playground in production environments (see [plugins configuration documentation](/dev-docs/configurations/plugins#graphql)).
59+
The GraphQL Sandbox is enabled by default in all environments except production. Set the `landingPage` configuration option to `true` to also enable the GraphQL Playground in production environments (see [plugins configuration documentation](/dev-docs/configurations/plugins#graphql)).
6060
:::
6161

6262
## Configuration
6363

6464
Plugins configuration are defined in the `config/plugins.js` file. This configuration file can include a `graphql.config` object to define specific configurations for the GraphQL plugin (see [plugins configuration documentation](/dev-docs/configurations/plugins#graphql)).
6565

66-
[Apollo Server](https://www.apollographql.com/docs/apollo-server/api/apollo-server/#apolloserver) options can be set with the `graphql.config.apolloServer` [configuration object](/dev-docs/configurations/plugins#graphql). Apollo Server options can be used for instance to enable the [tracing feature](https://www.apollographql.com/docs/federation/metrics/), which is supported by the GraphQL playground to track the response time of each part of your query. From `Apollo Server` version 3.9 default cache option is `cache: 'bounded'`. You can change it in the `apolloServer` configuration. For more information visit [Apollo Server Docs](https://www.apollographql.com/docs/apollo-server/performance/cache-backends/).
66+
[Apollo Server](https://www.apollographql.com/docs/apollo-server/api/apollo-server/#apolloserver) options can be passed directly to Apollo with the `graphql.config.apolloServer` [configuration object](/dev-docs/configurations/plugins#graphql). Apollo Server options can be used for instance to enable the [tracing feature](https://www.apollographql.com/docs/federation/metrics/), which is supported by the GraphQL Sandbox to track the response time of each part of your query. The `Apollo Server` default cache option is `cache: 'bounded'`. You can change it in the `apolloServer` configuration. For more information visit [Apollo Server Docs](https://www.apollographql.com/docs/apollo-server/performance/cache-backends/).
6767

6868
:::caution
6969
The maximum number of items returned by the response is limited to 100 by default. This value can be changed using the `amountLimit` configuration option, but should only be changed after careful consideration: a large query can cause a DDoS (Distributed Denial of Service) and may cause abnormal load on your Strapi server, as well as your database server.
7070
:::
7171

72+
## GraphQL Configuration Options
73+
74+
The following configuration options are supported by the GraphQL plugin and can be defined in the `config/plugins` file:
75+
76+
| Option | Type | Description | Default Value | Notes |
77+
| ------------------ | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | --------------------------------------------------- |
78+
| `endpoint` | String | Sets the GraphQL endpoint path. | `'/graphql'` | Example: `/custom-graphql` |
79+
| `shadowCRUD` | Boolean | Enables or disables automatic schema generation for content types. | `true` | |
80+
| `depthLimit` | Number | Limits the depth of GraphQL queries to prevent excessive nesting. | `10` | Use this to mitigate potential DoS attacks. |
81+
| `amountLimit` | Number | Limits the maximum number of items returned in a single response. | `100` | Use cautiously to avoid performance issues. |
82+
| `playgroundAlways` | Boolean | [Deprecated] Enables GraphQL Playground in all environments (deprecated). | `false` | Prefer using `landingPage` instead. |
83+
| `landingPage` | Boolean \| Function | Enables or disables the landing page for GraphQL. Accepts a boolean or a function returning a boolean or an ApolloServerPlugin implementing `renderLandingPage`. | | `false` in production, `true` in other environments |
84+
| `apolloServer` | Object | Passes configuration options directly to Apollo Server. | `{}` | Example: `{ tracing: true }` |
85+
86+
### Example
87+
88+
The following is an example of how to use these options in a Strapi configuration file:
89+
7290
<Tabs groupId="js-ts">
7391

7492
<TabItem value="javascript" label="JavaScript">
7593

76-
```js title="./config/plugins.js"
77-
94+
```javascript title="./config/plugins.js"
7895
module.exports = {
79-
//
8096
graphql: {
8197
config: {
8298
endpoint: '/graphql',
8399
shadowCRUD: true,
84-
playgroundAlways: false,
100+
landingPage: false, // disable Sandbox everywhere
85101
depthLimit: 7,
86102
amountLimit: 100,
87103
apolloServer: {
@@ -97,18 +113,63 @@ module.exports = {
97113
<TabItem value="typescript" label="TypeScript">
98114

99115
```ts title="./config/plugins.ts"
100-
101116
export default {
102-
//
103117
graphql: {
104118
config: {
105119
endpoint: '/graphql',
106120
shadowCRUD: true,
107-
playgroundAlways: false,
121+
landingPage: false, // disable Sandbox everywhere
108122
depthLimit: 7,
109123
amountLimit: 100,
110-
apolloServer: {
111-
tracing: false,
124+
},
125+
},
126+
};
127+
```
128+
129+
</TabItem>
130+
131+
</Tabs>
132+
133+
Here is an example of using a function to dynamically enable it:
134+
135+
<Tabs groupId="js-ts">
136+
137+
<TabItem value="javascript" label="JavaScript">
138+
139+
```javascript title="./config/plugins.js"
140+
module.exports = ({ env }) => {
141+
graphql: {
142+
config: {
143+
endpoint: '/graphql',
144+
shadowCRUD: true,
145+
landingPage: (strapi) => {
146+
if (env("NODE_ENV") !== "production") {
147+
return true;
148+
} else {
149+
return false;
150+
}
151+
},
152+
},
153+
},
154+
};
155+
```
156+
157+
</TabItem>
158+
159+
<TabItem value="typescript" label="TypeScript">
160+
161+
```ts title="./config/plugins.ts"
162+
export default ({ env }) => {
163+
graphql: {
164+
config: {
165+
endpoint: '/graphql',
166+
shadowCRUD: true,
167+
landingPage: (strapi) => {
168+
if (env("NODE_ENV") !== "production") {
169+
return true;
170+
} else {
171+
return false;
172+
}
112173
},
113174
},
114175
},
@@ -119,6 +180,66 @@ export default {
119180

120181
</Tabs>
121182

183+
### CORS exceptions for Landing Page
184+
185+
If the landing page is enabled in production environments (which is not recommended), CORS headers for the Apollo Server landing page must be added manually.
186+
187+
To add them globally, you can merge the following into your middleware configuration:
188+
189+
```
190+
{
191+
name: "strapi::security",
192+
config: {
193+
contentSecurityPolicy: {
194+
useDefaults: true,
195+
directives: {
196+
"connect-src": ["'self'", "https:", "apollo-server-landing-page.cdn.apollographql.com"],
197+
"img-src": ["'self'", "data:", "blob:", "apollo-server-landing-page.cdn.apollographql.com"],
198+
"script-src": ["'self'", "'unsafe-inline'", "apollo-server-landing-page.cdn.apollographql.com"],
199+
"style-src": ["'self'", "'unsafe-inline'", "apollo-server-landing-page.cdn.apollographql.com"],
200+
"frame-src": ["sandbox.embed.apollographql.com"]
201+
}
202+
}
203+
}
204+
}
205+
```
206+
207+
To add these exceptions only for the `/graphql` path (recommended), you can create a new middleware to handle it. For example:
208+
209+
<Tabs groupId="js-ts">
210+
211+
<TabItem value="javascript" label="JavaScript">
212+
213+
```javascript title="./middlewares/graphql-security.js"
214+
module.exports = (config, { strapi }) => {
215+
return async (ctx, next) => {
216+
if (ctx.request.path === '/graphql') {
217+
ctx.set('Content-Security-Policy', "default-src 'self'; script-src 'self' 'unsafe-inline' cdn.jsdelivr.net apollo-server-landing-page.cdn.apollographql.com; connect-src 'self' https:; img-src 'self' data: blob: apollo-server-landing-page.cdn.apollographql.com; media-src 'self' data: blob: apollo-server-landing-page.cdn.apollographql.com; frame-src sandbox.embed.apollographql.com; manifest-src apollo-server-landing-page.cdn.apollographql.com;");
218+
}
219+
await next();
220+
};
221+
};
222+
```
223+
224+
</TabItem>
225+
226+
<TabItem value="typescript" label="TypeScript">
227+
228+
```ts title="./middlewares/graphql-security.ts"
229+
export default (config, { strapi }) => {
230+
return async (ctx, next) => {
231+
if (ctx.request.path === '/graphql') {
232+
ctx.set('Content-Security-Policy', "default-src 'self'; script-src 'self' 'unsafe-inline' cdn.jsdelivr.net apollo-server-landing-page.cdn.apollographql.com; connect-src 'self' https:; img-src 'self' data: blob: apollo-server-landing-page.cdn.apollographql.com; media-src 'self' data: blob: apollo-server-landing-page.cdn.apollographql.com; frame-src sandbox.embed.apollographql.com; manifest-src apollo-server-landing-page.cdn.apollographql.com;");
233+
}
234+
await next();
235+
};
236+
};
237+
```
238+
239+
</TabItem>
240+
241+
</Tabs>
242+
122243
## Shadow CRUD
123244

124245
To simplify and automate the build of the GraphQL schema, we introduced the Shadow CRUD feature. It automatically generates the type definitions, queries, mutations and resolvers based on your models.
@@ -940,15 +1061,14 @@ mutation {
9401061

9411062
</Request>
9421063

943-
Then on each request, send along an `Authorization` header in the form of `{ "Authorization": "Bearer YOUR_JWT_GOES_HERE" }`. This can be set in the HTTP Headers section of your GraphQL Playground.
944-
1064+
Then on each request, send along an `Authorization` header in the form of `{ "Authorization": "Bearer YOUR_JWT_GOES_HERE" }`. This can be set in the HTTP Headers section of your GraphQL Sandbox.
9451065

9461066
## API tokens
9471067

9481068
To use API tokens for authentication, pass the token in the `Authorization` header using the format `Bearer your-api-token`.
9491069

9501070
:::note
951-
Using API tokens in the the GraphQL playground requires adding the authorization header with your token in the `HTTP HEADERS` tab:
1071+
Using API tokens in the the GraphQL Sandbox requires adding the authorization header with your token in the `HTTP HEADERS` tab:
9521072

9531073
```http
9541074
{
@@ -963,10 +1083,9 @@ Replace `<TOKEN>` with your API token generated in the Strapi Admin panel.
9631083

9641084
GraphQL is a query language allowing users to use a broader panel of inputs than traditional REST APIs. GraphQL APIs are inherently prone to security risks, such as credential leakage and denial of service attacks, that can be reduced by taking appropriate precautions.
9651085

1086+
### Disable introspection and Sandbox in production
9661087

967-
### Disable introspection and playground in production
968-
969-
In production environments, disabling the GraphQL Playground and the introspection query is recommended.
1088+
In production environments, disabling the GraphQL Sandbox and the introspection query is strongly recommended.
9701089
If you haven't edited the [configuration file](/dev-docs/configurations/plugins#graphql), it is already disabled in production by default.
9711090

9721091
### Limit max depth and complexity

0 commit comments

Comments
 (0)