Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Audit AS4 exported API #6676

Merged
merged 3 commits into from
Jul 13, 2022
Merged
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
6 changes: 6 additions & 0 deletions packages/server/src/ApolloServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1213,6 +1213,12 @@ export async function internalExecuteOperation<TContext extends BaseContext>({
return requestContext.response;
}

// Unlike InternalPlugins (where we can decide whether to install the default
// plugin based on looking at which plugins are installed),
// ImplicitlyInstallablePlugins (ie the default landing page plugin) can't
// determine if they're needed until later in startup. Specifically, we can't
// know if we've defined our own landing page until after serverWillStart
// plugins have run.
export type ImplicitlyInstallablePlugin<TContext extends BaseContext> =
ApolloServerPlugin<TContext> & {
__internal_installed_implicitly__: boolean;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { computeCoreSchemaHash } from '../../../plugin/schemaReporting';
import { printSchema, buildSchema } from 'graphql';
import { computeCoreSchemaHash } from '../../utils/computeCoreSchemaHash.js';

describe('Executable Schema Id', () => {
const unsortedGQLSchemaDocument = `
Expand Down
10 changes: 10 additions & 0 deletions packages/server/src/internalPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ export interface InternalApolloServerPlugin<TContext extends BaseContext>
__internal_plugin_id__(): InternalPluginId;
}

// Helper function for writing internal plugins which lets you write an object
// that is type-checked as InternalApolloServerPlugin but is still only of type
// ApolloServerPlugin (as appropriate for externally-exported plugin-returning
// functions).
export function internalPlugin<TContext extends BaseContext>(
p: InternalApolloServerPlugin<TContext>,
): ApolloServerPlugin<TContext> {
return p;
}

export type InternalPluginId =
| 'CacheControl'
| 'LandingPageDisabled'
Expand Down
9 changes: 5 additions & 4 deletions packages/server/src/plugin/cacheControl/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type {
ApolloServerPlugin,
BaseContext,
CacheAnnotation,
CacheHint,
Expand All @@ -15,7 +16,7 @@ import {
responsePathAsArray,
} from 'graphql';
import { newCachePolicy } from '../../cachePolicy.js';
import type { InternalApolloServerPlugin } from '../../internalPlugin';
import { internalPlugin } from '../../internalPlugin.js';
import LRUCache from 'lru-cache';

export interface ApolloServerPluginCacheControlOptions {
Expand All @@ -39,15 +40,15 @@ export interface ApolloServerPluginCacheControlOptions {

export function ApolloServerPluginCacheControl<TContext extends BaseContext>(
options: ApolloServerPluginCacheControlOptions = Object.create(null),
): InternalApolloServerPlugin<TContext> {
): ApolloServerPlugin<TContext> {
let typeAnnotationCache: LRUCache<GraphQLCompositeType, CacheAnnotation>;

let fieldAnnotationCache: LRUCache<
GraphQLField<unknown, unknown>,
CacheAnnotation
>;

return {
return internalPlugin({
__internal_plugin_id__() {
return 'CacheControl';
},
Expand Down Expand Up @@ -267,7 +268,7 @@ export function ApolloServerPluginCacheControl<TContext extends BaseContext>(
},
};
},
};
});
}

function cacheAnnotationFromDirectives(
Expand Down
10 changes: 5 additions & 5 deletions packages/server/src/plugin/inlineTrace/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Trace } from '@apollo/usage-reporting-protobuf';
import { TraceTreeBuilder } from '../traceTreeBuilder.js';
import type { ApolloServerPluginUsageReportingOptions } from '../usageReporting/options';
import type { InternalApolloServerPlugin } from '../../internalPlugin';
import { internalPlugin } from '../../internalPlugin.js';
import { schemaIsFederated } from '../schemaIsFederated.js';
import type { BaseContext } from '../../externalTypes';
import type { ApolloServerPlugin, BaseContext } from '../../externalTypes';

export interface ApolloServerPluginInlineTraceOptions {
/**
Expand Down Expand Up @@ -33,9 +33,9 @@ export interface ApolloServerPluginInlineTraceOptions {
// usage reporting ingress.
export function ApolloServerPluginInlineTrace<TContext extends BaseContext>(
options: ApolloServerPluginInlineTraceOptions = Object.create(null),
): InternalApolloServerPlugin<TContext> {
): ApolloServerPlugin<TContext> {
let enabled: boolean | null = options.__onlyIfSchemaIsFederated ? null : true;
return {
return internalPlugin({
__internal_plugin_id__() {
return 'InlineTrace';
},
Expand Down Expand Up @@ -128,5 +128,5 @@ export function ApolloServerPluginInlineTrace<TContext extends BaseContext>(
},
};
},
};
});
}
11 changes: 8 additions & 3 deletions packages/server/src/plugin/landingPage/default/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { BaseContext } from '../../../externalTypes';
import type { ApolloServerPlugin, BaseContext } from '../../../externalTypes';
import type { ImplicitlyInstallablePlugin } from '../../../ApolloServer';
import type {
ApolloServerPluginLandingPageLocalDefaultOptions,
Expand All @@ -10,11 +10,16 @@ import {
getEmbeddedSandboxHTML,
} from './getEmbeddedHTML.js';

export type {
ApolloServerPluginLandingPageLocalDefaultOptions,
ApolloServerPluginLandingPageProductionDefaultOptions,
};

export function ApolloServerPluginLandingPageLocalDefault<
TContext extends BaseContext,
>(
options: ApolloServerPluginLandingPageLocalDefaultOptions = {},
): ImplicitlyInstallablePlugin<TContext> {
): ApolloServerPlugin<TContext> {
const { version, __internal_apolloStudioEnv__, ...rest } = {
// we default to Sandbox unless embed is specified as false
embed: true as const,
Expand All @@ -31,7 +36,7 @@ export function ApolloServerPluginLandingPageProductionDefault<
TContext extends BaseContext,
>(
options: ApolloServerPluginLandingPageProductionDefaultOptions = {},
): ImplicitlyInstallablePlugin<TContext> {
): ApolloServerPlugin<TContext> {
const { version, __internal_apolloStudioEnv__, ...rest } = options;
return ApolloServerPluginLandingPageDefault(version, {
isProd: true,
Expand Down
16 changes: 6 additions & 10 deletions packages/server/src/plugin/schemaReporting/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { createHash } from '@apollo/utils.createhash';
import os from 'os';
import type { InternalApolloServerPlugin } from '../../internalPlugin';
import { internalPlugin } from '../../internalPlugin.js';
import { v4 as uuidv4 } from 'uuid';
import { printSchema, validateSchema, buildSchema } from 'graphql';
import { SchemaReporter } from './schemaReporter.js';
import { schemaIsFederated } from '../schemaIsFederated.js';
import type { SchemaReport } from './generated/operations';
import type { BaseContext } from '../../externalTypes';
import type { ApolloServerPlugin, BaseContext } from '../../externalTypes';
import type { Fetcher } from '@apollo/utils.fetcher';
import { packageVersion } from '../../generated/packageVersion.js';
import { computeCoreSchemaHash } from '../../utils/computeCoreSchemaHash.js';

export interface ApolloServerPluginSchemaReportingOptions {
/**
Expand Down Expand Up @@ -65,10 +65,10 @@ export function ApolloServerPluginSchemaReporting<TContext extends BaseContext>(
endpointUrl,
fetcher,
}: ApolloServerPluginSchemaReportingOptions = Object.create(null),
): InternalApolloServerPlugin<TContext> {
): ApolloServerPlugin<TContext> {
const bootId = uuidv4();

return {
return internalPlugin({
__internal_plugin_id__() {
return 'SchemaReporting';
},
Expand Down Expand Up @@ -196,9 +196,5 @@ export function ApolloServerPluginSchemaReporting<TContext extends BaseContext>(
},
};
},
};
}

export function computeCoreSchemaHash(schema: string): string {
return createHash('sha256').update(schema).digest('hex');
});
}
11 changes: 6 additions & 5 deletions packages/server/src/plugin/usageReporting/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ import fetch from 'node-fetch';
import os from 'os';
import { gzip } from 'zlib';
import type {
ApolloServerPlugin,
BaseContext,
GraphQLRequestContext,
GraphQLRequestContextDidResolveOperation,
GraphQLRequestContextWillSendResponse,
GraphQLRequestListener,
GraphQLServerListener,
} from '../../externalTypes';
import type { InternalApolloServerPlugin } from '../../internalPlugin';
import { internalPlugin } from '../../internalPlugin.js';
import type { HeaderMap } from '../../runHttpQuery';
import { computeCoreSchemaHash } from '../schemaReporting/index.js';
import { dateToProtoTimestamp, TraceTreeBuilder } from '../traceTreeBuilder.js';
import { defaultSendOperationsAsTrace } from './defaultSendOperationsAsTrace.js';
import {
Expand All @@ -36,6 +36,7 @@ import type {
import { OurReport } from './stats.js';
import { makeTraceDetails } from './traceDetails.js';
import { packageVersion } from '../../generated/packageVersion.js';
import { computeCoreSchemaHash } from '../../utils/computeCoreSchemaHash.js';

const reportHeaderDefaults = {
hostname: os.hostname(),
Expand Down Expand Up @@ -65,7 +66,7 @@ export function ApolloServerPluginUsageReporting<TContext extends BaseContext>(
options: ApolloServerPluginUsageReportingOptions<TContext> = Object.create(
null,
),
): InternalApolloServerPlugin<TContext> {
): ApolloServerPlugin<TContext> {
// Note: We'd like to change the default to false in Apollo Server 4, so that
// the default usage reporting experience doesn't include *anything* that
// could potentially be PII (like error messages) --- just operations and
Expand All @@ -84,7 +85,7 @@ export function ApolloServerPluginUsageReporting<TContext extends BaseContext>(
let requestDidStartHandler: (
requestContext: GraphQLRequestContext<TContext>,
) => GraphQLRequestListener<TContext>;
return {
return internalPlugin({
__internal_plugin_id__() {
return 'UsageReporting';
},
Expand Down Expand Up @@ -777,7 +778,7 @@ export function ApolloServerPluginUsageReporting<TContext extends BaseContext>(
},
};
},
};
});
}

export function makeHTTPRequestHeaders(
Expand Down
10 changes: 6 additions & 4 deletions packages/server/src/standalone/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export interface StandaloneServerContextFunctionArgument {
res: ServerResponse;
}

interface HTTPServerOptions<TContext extends BaseContext> {
export interface StartStandaloneServerOptions<TContext extends BaseContext> {
context?: ContextFunction<
[StandaloneServerContextFunctionArgument],
TContext
Expand All @@ -32,17 +32,19 @@ interface HTTPServerOptions<TContext extends BaseContext> {

export async function startStandaloneServer(
server: ApolloServer<BaseContext>,
options?: HTTPServerOptions<BaseContext> & { listen?: ListenOptions },
options?: StartStandaloneServerOptions<BaseContext> & {
listen?: ListenOptions;
},
): Promise<{ url: string }>;
export async function startStandaloneServer<TContext extends BaseContext>(
server: ApolloServer<TContext>,
options: WithRequired<HTTPServerOptions<TContext>, 'context'> & {
options: WithRequired<StartStandaloneServerOptions<TContext>, 'context'> & {
listen?: ListenOptions;
},
): Promise<{ url: string }>;
export async function startStandaloneServer<TContext extends BaseContext>(
server: ApolloServer<TContext>,
options?: HTTPServerOptions<TContext> & { listen?: ListenOptions },
options?: StartStandaloneServerOptions<TContext> & { listen?: ListenOptions },
): Promise<{ url: string }> {
const app: express.Express = express();
const httpServer: http.Server = http.createServer(app);
Expand Down
9 changes: 9 additions & 0 deletions packages/server/src/utils/computeCoreSchemaHash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { createHash } from '@apollo/utils.createhash';

// This hash function is used in both the schema reporting and usage reporting
// plugins. Making sure we use the same hash function hypothetically allows the
// two reporting features to work well together, though in practice nothing on
// the Studio side currently correlates this ID across both features.
export function computeCoreSchemaHash(schema: string): string {
return createHash('sha256').update(schema).digest('hex');
}