【发布时间】:2020-11-05 17:53:34
【问题描述】:
我正在运行 Fastify 3.0.2 和 @autotelic/apollo-server-fastify 3.0.0。
Fastify 抛出此错误:
[1] (node:6827) [FSTDEP003] FastifyDeprecation [FSTDEP003]:您正在使用旧的内容类型解析器函数签名。请改用文档中建议的那个。
bootstrap.ts
/* tslint:disable:object-literal-sort-keys */
import 'reflect-metadata';
import * as TypeORM from 'typeorm';
import * as TypeGraphQL from 'type-graphql';
import fastify from 'fastify';
import {Container} from 'typedi';
import {AddressEntity} from './persistence/domain/AddressEntity';
import {CompanyEntity} from './persistence/domain/CompanyEntity';
import {ProductEntity} from './persistence/domain/ProductEntity';
import {UserInfoEntity} from './persistence/domain/UserInfoEntity';
import {UserRoleEntity} from './persistence/domain/UserRoleEntity';
import {seedDatabase} from './persistence/helpers';
import {Context} from './resolvers/types/context';
import {UserResolver} from './resolvers/UserResolver';
import {customAuthChecker} from './authChecker';
import {ApolloServer} from '@autotelic/apollo-server-fastify';
TypeORM.useContainer(Container);
async function bootstrap() {
try {
// create TypeORM connection
await TypeORM.createConnection({
type: 'postgres',
database: 'agrilink',
username: 'agrilink', // fill this with your username
password: 'password', // and password
port: 5434,
host: 'localhost',
entities: [AddressEntity, CompanyEntity, ProductEntity, UserInfoEntity, UserRoleEntity],
synchronize: true,
logger: 'advanced-console',
logging: 'all',
dropSchema: true,
cache: true,
});
// seed database with some data
const {defaultUser} = await seedDatabase();
// build TypeGraphQL executable schema
const schema = await TypeGraphQL.buildSchema({
resolvers: [UserResolver],
container: Container,
authChecker: customAuthChecker,
});
// create mocked context
const context: Context = {user: defaultUser};
// create GraphQL server
const server = new ApolloServer({schema, context});
const app = fastify();
// start the server
await (async function () {
app.register(server.createHandler());
await app.listen(4000);
})();
} catch (err) {
console.error(err);
}
}
bootstrap();
我可以验证问题源于 apollo-server-fastify 内部的这个实现:
来自@autotelic/apollo-server-fastify 的 ApolloServer.ts
import { renderPlaygroundPage } from '@apollographql/graphql-playground-html';
import { Accepts } from 'accepts';
import {
ApolloServerBase,
FileUploadOptions,
formatApolloErrors,
PlaygroundRenderPageOptions,
processFileUploads,
} from 'apollo-server-core';
import { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify';
import { IncomingMessage, OutgoingMessage, ServerResponse, Server } from 'http';
import { graphqlFastify } from './fastifyApollo';
import { GraphQLOperation } from 'graphql-upload';
const kMultipart = Symbol('multipart');
const fastJson = require('fast-json-stringify');
export interface ServerRegistration {
path?: string;
cors?: object | boolean;
onHealthCheck?: (req: FastifyRequest<IncomingMessage>) => Promise<any>;
disableHealthCheck?: boolean;
}
const stringifyHealthCheck = fastJson({
type: 'object',
properties: {
status: {
type: 'string',
},
},
});
const fileUploadMiddleware = (
uploadsConfig: FileUploadOptions,
server: ApolloServerBase,
) => (
req: FastifyRequest<IncomingMessage>,
reply: FastifyReply<ServerResponse>,
done: (err: Error | null, body?: any) => void,
) => {
if (
(req.req as any)[kMultipart] &&
typeof processFileUploads === 'function'
) {
processFileUploads(req.req, reply.res, uploadsConfig)
.then((body: GraphQLOperation | GraphQLOperation[]) => {
req.body = body;
done(null);
})
.catch((error: any) => {
if (error.status && error.expose) reply.status(error.status);
throw formatApolloErrors([error], {
formatter: server.requestOptions.formatError,
debug: server.requestOptions.debug,
});
});
} else {
done(null);
}
};
export class ApolloServer extends ApolloServerBase {
protected supportsSubscriptions(): boolean {
return true;
}
protected supportsUploads(): boolean {
return true;
}
public createHandler({
path,
cors,
disableHealthCheck,
onHealthCheck,
}: ServerRegistration = {}) {
this.graphqlPath = path ? path : '/graphql';
const promiseWillStart = this.willStart();
return async (
app: FastifyInstance<Server, IncomingMessage, ServerResponse>,
) => {
await promiseWillStart;
if (!disableHealthCheck) {
app.get('/.well-known/apollo/server-health', async (req, res) => {
// Response follows https://tools.ietf.org/html/draft-inadarei-api-health-check-01
res.type('application/health+json');
if (onHealthCheck) {
try {
await onHealthCheck(req);
res.send(stringifyHealthCheck({ status: 'pass' }));
} catch (e) {
res.status(503).send(stringifyHealthCheck({ status: 'fail' }));
}
} else {
res.send(stringifyHealthCheck({ status: 'pass' }));
}
});
}
app.register(
async instance => {
instance.register(require('fastify-accepts'));
if (cors === true) {
instance.register(require('fastify-cors'));
} else if (cors !== false) {
instance.register(require('fastify-cors'), cors);
}
instance.setNotFoundHandler((_request, reply) => {
reply.code(405);
reply.header('allow', 'GET, POST');
reply.send();
});
const preHandlers = [
(
req: FastifyRequest<IncomingMessage>,
reply: FastifyReply<ServerResponse>,
done: () => void,
) => {
// Note: if you enable playground in production and expect to be able to see your
// schema, you'll need to manually specify `introspection: true` in the
// ApolloServer constructor; by default, the introspection query is only
// enabled in dev.
if (this.playgroundOptions && req.req.method === 'GET') {
// perform more expensive content-type check only if necessary
const accept = (req as any).accepts() as Accepts;
const types = accept.types() as string[];
const prefersHTML =
types.find(
(x: string) =>
x === 'text/html' || x === 'application/json',
) === 'text/html';
if (prefersHTML) {
const playgroundRenderPageOptions: PlaygroundRenderPageOptions = {
endpoint: this.graphqlPath,
subscriptionEndpoint: this.subscriptionsPath,
...this.playgroundOptions,
};
reply.type('text/html');
const playground = renderPlaygroundPage(
playgroundRenderPageOptions,
);
reply.send(playground);
return;
}
}
done();
},
];
if (typeof processFileUploads === 'function' && this.uploadsConfig) {
instance.addContentTypeParser(
'multipart',
(
request: IncomingMessage,
done: (err: Error | null, body?: any) => void,
) => {
(request as any)[kMultipart] = true;
done(null);
},
);
preHandlers.push(fileUploadMiddleware(this.uploadsConfig, this));
}
const graphQLServerOptions = this.graphQLServerOptions.bind(this);
const applyContextArgs = async (
request?: FastifyRequest<IncomingMessage>,
reply?: FastifyReply<OutgoingMessage>,
) => graphQLServerOptions({ request, reply });
instance.route({
method: ['GET', 'POST'],
url: '/',
preHandler: preHandlers,
handler: await graphqlFastify(applyContextArgs),
});
},
{
prefix: this.graphqlPath,
},
);
};
}
}
似乎还不够最新,奇怪的是我也遇到了 fastify 3.0.0 的问题。
注意 澄清一下,问题不是警告本身,而是警告后服务器根本不工作。
提前感谢您的帮助。
【问题讨论】:
标签: apollo-server fastify