【问题标题】:You are using the legacy Content Type Parser function signature您正在使用旧的 Content Type Parser 函数签名
【发布时间】: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


    【解决方案1】:

    警告不是原因,因为它仍然是supported in v3

    查看@autotelic/apollo-server-fastify package.json,它设计用于fastify v2:

    "fastify": "^2.14.1",
    

    所以你需要降级你的 fastify 服务器或要求升级到模块。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-28
      • 2013-04-18
      • 2011-09-10
      • 1970-01-01
      • 2014-03-20
      相关资源
      最近更新 更多