Skip to content

Commit

Permalink
fix(handler): Stringify errors by exposing only the message
Browse files Browse the repository at this point in the history
  • Loading branch information
enisdenjo committed Apr 13, 2023
1 parent b8bdc71 commit cabf8a9
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 3 deletions.
13 changes: 13 additions & 0 deletions src/__tests__/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,16 @@ it('should replace the validation rules when providing a function', async () =>
}
`);
});

it('should print plain errors in detail', async () => {
const server = startTServer({});
const url = new URL(server.url);
const result = await fetch(url.toString(), {
method: 'POST',
headers: { 'content-type': 'application/json' },
// missing body
});
await expect(result.text()).resolves.toMatchInlineSnapshot(
`"{"errors":[{"message":"Unparsable JSON body"}]}"`,
);
});
7 changes: 4 additions & 3 deletions src/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
isExecutionResult,
isGraphQLError,
isObject,
jsonErrorReplacer,
} from './utils';

/**
Expand Down Expand Up @@ -726,7 +727,7 @@ export function makeResponse(
!isGraphQLError(resultOrErrors)
) {
return [
JSON.stringify({ errors: [resultOrErrors] }),
JSON.stringify({ errors: [resultOrErrors] }, jsonErrorReplacer),
{
status: 400,
statusText: 'Bad Request',
Expand All @@ -743,7 +744,7 @@ export function makeResponse(
: null;
if (errors) {
return [
JSON.stringify({ errors }),
JSON.stringify({ errors }, jsonErrorReplacer),
{
...(acceptedMediaType === 'application/json'
? {
Expand All @@ -765,7 +766,7 @@ export function makeResponse(
}

return [
JSON.stringify(resultOrErrors),
JSON.stringify(resultOrErrors, jsonErrorReplacer),
{
status: 200,
statusText: 'OK',
Expand Down
16 changes: 16 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,19 @@ export function isAsyncIterable<T = unknown>(
): val is AsyncIterable<T> {
return typeof Object(val)[Symbol.asyncIterator] === 'function';
}

/** @private */
export function jsonErrorReplacer(_key: string, val: any) {

Check warning on line 73 in src/utils.ts

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
if (
val instanceof Error &&
// GraphQL errors implement their own stringer
!isGraphQLError(val)
) {
return {
// name: val.name, name is included in message
message: val.message,
// stack: val.stack, can leak sensitive details
};
}
return val;
}

0 comments on commit cabf8a9

Please sign in to comment.