From fb224d60c4755b4cca41c934d15859f8e8d69934 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Tue, 15 Feb 2022 13:05:19 -0800 Subject: [PATCH] Remove subscriptions, comment out the sanitize directive --- packages/api/src/apollo.ts | 51 ++---------- packages/api/src/directives.ts | 46 +++++------ packages/api/src/graphql_tracing.ts | 122 ---------------------------- packages/api/src/server.ts | 4 + 4 files changed, 32 insertions(+), 191 deletions(-) delete mode 100644 packages/api/src/graphql_tracing.ts diff --git a/packages/api/src/apollo.ts b/packages/api/src/apollo.ts index b0cf8134c..e52b91400 100644 --- a/packages/api/src/apollo.ts +++ b/packages/api/src/apollo.ts @@ -15,12 +15,12 @@ import { tracer } from './tracing' import { env } from './env' import { promisify } from 'util' import { buildLogger } from './utils/logger' -import { ApolloServer, makeExecutableSchema } from 'apollo-server-express' +import { ApolloServer } from 'apollo-server-express' +import { makeExecutableSchema } from '@graphql-tools/schema' import { applyMiddleware } from 'graphql-middleware' import * as cookie from 'cookie' import typeDefs from './schema' -import { gqlTracingPlugin, traceResolvers } from './graphql_tracing' -import { SanitizeDirective } from './directives' +// import { SanitizeDirective } from './directives' import { functionResolvers } from './resolvers/function_resolvers' import ScalarResolvers from './scalars' import * as Sentry from '@sentry/node' @@ -38,10 +38,6 @@ const resolvers = { ...ScalarResolvers, } -const schemaDirectives = { - sanitize: SanitizeDirective, -} - const contextFunc: ContextFunction = async ({ req, res, @@ -112,53 +108,16 @@ const contextFunc: ContextFunction = async ({ } export function makeApolloServer(app: Express): ApolloServer { - traceResolvers(functionResolvers) - + let schema = makeExecutableSchema({ typeDefs, resolvers }) const apollo = new ApolloServer({ - schema: applyMiddleware( - makeExecutableSchema({ typeDefs, resolvers, schemaDirectives }) - ), + schema: schema, context: contextFunc, - plugins: [ - gqlTracingPlugin, - { - requestDidStart: () => ({ - didEncounterErrors: (ctx) => { - const error = ctx.errors[0] - const trxId = ctx.request.http?.headers.get('X-Transaction-ID') - const userId = ctx.context?.claims?.uid - const consoleMessage = `Transaction ID: ${trxId}. user: ${userId}.\n` - console.error(consoleMessage, error) - }, - }), - }, - ], formatError: (err) => { Sentry.captureException(err) // hide error messages from frontend on prod return new Error('Unexpected server error') }, - subscriptions: { - path: '/api/graphql', - keepAlive: 4000, - onConnect: (connectionParams, webSocket, context) => { - const extraContext: { [key: string]: Record } = {} - if ( - context.request && - context.request.headers && - context.request.headers.cookie - ) { - extraContext.cookies = cookie.parse(context.request.headers.cookie) - } - return { - ...extraContext, - ...context, - } - }, - }, }) - apollo.applyMiddleware({ app, path: '/api/graphql', cors: corsConfig }) - return apollo } diff --git a/packages/api/src/directives.ts b/packages/api/src/directives.ts index 7b660e142..e3da60302 100644 --- a/packages/api/src/directives.ts +++ b/packages/api/src/directives.ts @@ -1,25 +1,25 @@ /* eslint-disable @typescript-eslint/restrict-template-expressions */ -import { SchemaDirectiveVisitor } from 'apollo-server-express' -import { GraphQLInputField, GraphQLScalarType } from 'graphql' -import { SanitizedString } from './scalars' -import { GraphQLNonNull } from 'graphql/type/definition' +// import { SchemaDirectiveVisitor } from 'apollo-server-express' +// import { GraphQLInputField, GraphQLScalarType } from 'graphql' +// import { SanitizedString } from './scalars' +// import { GraphQLNonNull } from 'graphql/type/definition' -export class SanitizeDirective extends SchemaDirectiveVisitor { - visitInputFieldDefinition( - field: GraphQLInputField - ): GraphQLInputField | void | null { - const { allowedTags, maxLength } = this.args - if ( - field.type instanceof GraphQLNonNull && - field.type.ofType instanceof GraphQLScalarType - ) { - field.type = new GraphQLNonNull( - new SanitizedString(field.type.ofType, allowedTags, maxLength) - ) - } else if (field.type instanceof GraphQLScalarType) { - field.type = new SanitizedString(field.type, allowedTags, maxLength) - } else { - throw new Error(`Not a scalar type: ${field.type}`) - } - } -} +// export class SanitizeDirective extends SchemaDirectiveVisitor { +// visitInputFieldDefinition( +// field: GraphQLInputField +// ): GraphQLInputField | void | null { +// const { allowedTags, maxLength } = this.args +// if ( +// field.type instanceof GraphQLNonNull && +// field.type.ofType instanceof GraphQLScalarType +// ) { +// field.type = new GraphQLNonNull( +// new SanitizedString(field.type.ofType, allowedTags, maxLength) +// ) +// } else if (field.type instanceof GraphQLScalarType) { +// field.type = new SanitizedString(field.type, allowedTags, maxLength) +// } else { +// throw new Error(`Not a scalar type: ${field.type}`) +// } +// } +// } diff --git a/packages/api/src/graphql_tracing.ts b/packages/api/src/graphql_tracing.ts deleted file mode 100644 index f31c61d99..000000000 --- a/packages/api/src/graphql_tracing.ts +++ /dev/null @@ -1,122 +0,0 @@ -/* eslint-disable @typescript-eslint/require-await */ -/* eslint-disable @typescript-eslint/no-unused-vars */ -/* eslint-disable prefer-const */ -/* eslint-disable @typescript-eslint/no-unsafe-member-access */ -/* eslint-disable @typescript-eslint/no-unsafe-return */ -/* eslint-disable @typescript-eslint/no-unsafe-assignment */ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { - ApolloServerPlugin, - GraphQLRequestListener, - ValueOrPromise, - WithRequired, -} from 'apollo-server-plugin-base' -import { GraphQLRequestContext } from 'apollo-server-core' -import { GraphQLResolveInfo } from 'graphql' -import { ResolverContext } from './resolvers/types' -import { ResolverFn, SubscriptionResolverObject } from './generated/graphql' -import { traceAs } from './tracing' - -/** - * Replaces resolver functions with tracing-wrapped functions. - */ -export function traceResolvers(resolvers: { - [rootKey: string]: { - [fieldKey: string]: - | ResolverFn - | SubscriptionResolverObject - } -}): void { - for (const typeKey in resolvers) { - const rootType = resolvers[typeKey] - for (const fieldKey in rootType) { - const resolver = rootType[fieldKey] - const resolveFn = - typeof resolver === 'function' ? resolver : resolver.resolve - - // eslint-disable-next-line @typescript-eslint/explicit-function-return-type - const wrappedResolveFn = async ( - ...resolverArgs: [any, any, ResolverContext, GraphQLResolveInfo] - ) => { - let info, ctx, args - if (resolverArgs.length === 4) { - ;[, args, ctx, info] = resolverArgs - } - if (!info?.path) { - return resolveFn(...resolverArgs) - } - - const spanName = `${typeKey}.${info.path.key}` - return traceAs( - { - spanName, - attributes: { - 'resolver.args': JSON.stringify(args), - }, - }, - async () => { - return resolveFn(...resolverArgs) - } - ) - } - - if (typeof resolver === 'function') { - rootType[fieldKey] = wrappedResolveFn - } else { - ;(rootType[fieldKey] as any).resolve = wrappedResolveFn - } - } - } -} - -class GQLTracingPlugin implements GraphQLRequestListener { - [key: string]: import('apollo-server-types').AnyFunction | undefined - willSendResponse({ - context, - }: WithRequired< - GraphQLRequestContext, - 'metrics' | 'response' - >): ValueOrPromise { - context.tracingSpan.end() - } - - didEncounterErrors( - ctx: WithRequired< - GraphQLRequestContext, - 'metrics' | 'source' | 'errors' - > - ): ValueOrPromise { - const error = ctx.errors[0] - const trxId = ctx.request.http?.headers.get('X-Transaction-ID') - const userId = ctx.context?.claims?.uid - ctx.context.tracingSpan.setAttributes({ - 'graphql.error': true, - 'graphql.error.message': error.message, - 'request.transaction_id': trxId || '', - }) - } -} - -export const gqlTracingPlugin: ApolloServerPlugin = { - requestDidStart({ - context: { tracingSpan, claims }, - request, - }: GraphQLRequestContext): GraphQLRequestListener | void { - if (request.query) { - tracingSpan.setAttribute('graphql.query', request.query) - } - if (claims?.uid) { - tracingSpan.setAttribute('user.id', claims.uid) - } - if (request.operationName) { - tracingSpan.setAttribute('graphql.operationName', request.operationName) - } - if (request.variables) { - tracingSpan.setAttribute( - 'graphql.variables', - JSON.stringify(request.variables) - ) - } - return new GQLTracingPlugin() - }, -} diff --git a/packages/api/src/server.ts b/packages/api/src/server.ts index 5fc5aa9ac..a1cfec86e 100755 --- a/packages/api/src/server.ts +++ b/packages/api/src/server.ts @@ -38,6 +38,7 @@ import ReminderModel from './datalayer/reminders' import { remindersServiceRouter } from './routers/svc/reminders' import { ApolloServer } from 'apollo-server-express' import { pdfAttachmentsRouter } from './routers/svc/pdf_attachments' +import { corsConfig } from './utils/corsConfig' const PORT = process.env.PORT || 4000 @@ -125,6 +126,9 @@ const main = async (): Promise => { const { app, apollo, httpServer } = createApp() + await apollo.start() + apollo.applyMiddleware({ app, path: '/api/graphql', cors: corsConfig }) + if (!env.dev.isLocal) { const mwLogger = loggers.get('express', { levels: config.syslog.levels }) const transport = buildLoggerTransport('express')