Skip to content

Commit 5ebe970

Browse files
authored
Merge pull request #9 from mxstbr/patch-1
Update README with more documentation
2 parents 6ef0b2c + 612649e commit 5ebe970

File tree

1 file changed

+83
-23
lines changed

1 file changed

+83
-23
lines changed

README.md

Lines changed: 83 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,93 @@
11
# GraphQL Errors
22

3-
When an error occurs when processing GraphQL queries, [graphql-js](https://github.com/graphql/graphql-js) sends the complete error message to the client with the response. In most cases, sending error messages to the client without supervision is not recommended. The `graphql-errors` module fixes this issue by masking error messages sent to the client. This module intercepts GraphQL error messages and replaces them with `"internal error"`.
3+
When an error occurs when processing GraphQL queries, [graphql-js](https://github.com/graphql/graphql-js) sends the complete error message to the client with the response. In most cases, **sending error messages to the client without supervision is a bad idea** since those might leak sensitive information.
4+
5+
The `graphql-errors` module fixes this issue by **masking error messages sent to the client**. This module intercepts GraphQL error messages and replaces them with `"Internal error"` and a UUID. It also logs the error on the server with the stacktrace and it's UUID, making user bug reports easy to cross-reference.
6+
7+
## Usage
48

59
``` javascript
6-
var express = require('express');
7-
var graphql = require('graphql');
8-
var graphqlHTTP = require('express-graphql');
9-
var maskErrors = require('graphql-errors').maskErrors;
10-
11-
var schema = new graphql.GraphQLSchema({
12-
query: new graphql.GraphQLObjectType({
13-
name: 'RootQueryType',
14-
fields: {
15-
test: {
16-
type: graphql.GraphQLString,
17-
resolve() {
18-
throw new Error('secret error message');
19-
},
20-
},
21-
},
22-
}),
10+
const { maskErrors } = require('graphql-errors');
11+
12+
const schema = new graphql.GraphQLSchema({
13+
// ...your schema here...
2314
});
2415

25-
// mask error messages
16+
// Mask the error messages
2617
maskErrors(schema);
2718

28-
var app = express();
29-
app.use('/', graphqlHTTP({schema: schema}));
30-
app.listen(3000);
19+
// Use your schema like you normally would, for example:
20+
app.use('/', graphqlHTTP({ schema: schema }));
21+
```
22+
23+
### User errors
24+
25+
Some error messages you _do_ want to send to the user though, like permission errors, so `graphql-errors` exports a `UserError` class. Throwing a `UserError` will not mask the error message so your users sees the exact one you threw:
26+
27+
```JS
28+
const { UserError } = require('graphql-errors')
29+
30+
const resolvers = {
31+
Query: {
32+
hiddenField() {
33+
// Your user sees: "Permission denied."
34+
throw new UserError('Permission denied.');
35+
}
36+
}
37+
}
3138
```
3239

33-
To make error debugging easier, it logs the error on the server with the stack. The module can be activated on a schema using its `processSchema` function.
40+
## Example Error
41+
42+
Let's say your database throws an error because you exceeded some limit. Normally your user would see an error message saying "Database limit exceeded.", but not with `graphql-errors`!
43+
44+
**What the user gets in the response**
45+
46+
```JSON
47+
{
48+
"data": {
49+
"post": null
50+
},
51+
"errors": [
52+
{
53+
"message": "Internal Error: e553aaa4-47dc-47db-9bfc-314cc2cf5833",
54+
"locations": [
55+
{
56+
"line": 2,
57+
"column": 3
58+
}
59+
],
60+
"path": [
61+
"post"
62+
]
63+
}
64+
]
65+
}
66+
```
67+
68+
As you can see, no sensitive information is leaked to the user at all. You might think this'll make bug reports less useful, but note how a UUID is attached to the error message!
69+
70+
**What you see in the server console**
71+
72+
```
73+
Error: Database limit exceeded.: e553aaa4-47dc-47db-9bfc-314cc2cf5833
74+
at post (/project/server/queries/post.js:10:35)
75+
at _callee$ (/project/node_modules/graphql-errors/dist/index.js:140:36)
76+
at tryCatch (/project/node_modules/regenerator-runtime/runtime.js:64:40)
77+
at Generator.invoke [as _invoke] (/project/node_modules/regenerator-runtime/runtime.js:355:22)
78+
at Generator.prototype.(anonymous function) [as next] (/project/node_modules/regenerator-runtime/runtime.js:116:21)
79+
at step (/project/node_modules/babel-runtime/helpers/asyncToGenerator.js:17:30)
80+
at /project/node_modules/babel-runtime/helpers/asyncToGenerator.js:35:14
81+
at F (/project/node_modules/babel-runtime/node_modules/core-js/library/modules/_export.js:35:28)
82+
at /project/node_modules/babel-runtime/helpers/asyncToGenerator.js:14:12
83+
at /project/node_modules/graphql-errors/dist/index.js:160:18
84+
at resolveOrError (/project/node_modules/graphql/execution/execute.js:475:12)
85+
at resolveField (/project/node_modules/graphql/execution/execute.js:461:16)
86+
at /project/node_modules/graphql/execution/execute.js:275:18
87+
at Array.reduce (native)
88+
at executeFields (/project/node_modules/graphql/execution/execute.js:272:42)
89+
at executeOperation (/project/node_modules/graphql/execution/execute.js:212:10)
90+
```
91+
92+
Note how the same UUID (`"e553aaa4-47dc-47db-9bfc-314cc2cf5833"`) is sent to the user and logged together with the stack trace, making it easy to cross-reference user bug reports to your server logs.
93+

0 commit comments

Comments
 (0)