Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import type {
Response,
} from 'express-serve-static-core';
import type { ParsedQs } from 'qs';
import depthLimit from 'graphql-depth-limit';
import cors from 'cors';
import safeDepthLimit from './utils/safeDepthLimit';
import resolvers from './resolvers';
import typeDefs from './schema';
import appSettings from './common/appSettings';
Expand Down Expand Up @@ -55,7 +55,7 @@ const httpServer = http.createServer(app);
const server = new ApolloServer<Context>({
formatError,
introspection: true,
validationRules: [depthLimit(appSettings.maxQueryDepth)],
validationRules: [safeDepthLimit(appSettings.maxQueryDepth)],
typeDefs,
resolvers,
plugins: [
Expand Down
35 changes: 35 additions & 0 deletions src/utils/safeDepthLimit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import depthLimit from 'graphql-depth-limit';
import type { ValidationContext } from 'graphql';

/**
* A wrapper around graphql-depth-limit that catches specific crashes caused by
* undefined fragments (which should be handled by standard validation but cause
* graphql-depth-limit to throw).
*/
const safeDepthLimit =
(maxDepth: number, options: any = {}, callback: any = () => undefined) =>
(validationContext: ValidationContext) => {
try {
const validator = depthLimit(maxDepth, options, callback);
return validator(validationContext);
} catch (err: any) {
// graphql-depth-limit version 1.1.0 crashes on unknown fragments with
// TypeError: Cannot read properties of undefined (reading 'kind')
// We catch this specific error to allow standard GraphQL validation to handle the
// unknown fragment error, preventing a 500 Internal Server Error.
if (
err instanceof TypeError &&
err.message.includes(
"Cannot read properties of undefined (reading 'kind')",
)
) {
// If we catch this error, it means depth limit check failed due to invalid AST
// We return the context as is, skipping the depth check for this invalid query.
// Standard validation will subsequently fail with a proper 400 error.
return validationContext;
}
throw err;
}
};

export default safeDepthLimit;