AWS Lambda 上的 Apollo Gateway 无法读取未定义的 属性 'content-type'

Apollo Gateway on AWS Lambda Cannot read property 'content-type' of undefined

我在 AWS Lambda 上有一个 Node Apollo Gateway 服务 运行,它委托给两个不同的 GraphQL 服务,它在我的 Mac.

本地运行良好

然而,当 运行 在 AWS Lambda 上时,当我到达终点时网关给我这个错误(期望看到操场)

{
"errorType": "TypeError",
"errorMessage": "Cannot read property 'content-type' of undefined",
"trace": [
"TypeError: Cannot read property 'content-type' of undefined",
"    at fileUploadHandler (/var/task/node_modules/apollo-server-lambda/dist/ApolloServer.js:143:50)",
"    at Runtime.handler (/var/task/node_modules/apollo-server-lambda/dist/ApolloServer.js:166:13)",
"    at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)"
]
}

我没有对上传做任何事情,但是查看 ApolloServer.js,我可以看到一个处理程序已经制作完成。

我的 index.js 看起来像这样:

const isLambda = !!process.env.LAMBDA_TASK_ROOT;

const { ApolloServer, gql } = isLambda ? require('apollo-server-lambda') : require('apollo-server');

const { ApolloGateway, RemoteGraphQLDataSource } = require("@apollo/gateway");

const gateway = new ApolloGateway({
  serviceList: [
    { name: 'service1', url: !isLambda ? 'http://127.0.0.1:5090' : 'https://api.blah.com/search' },
    { name: 'service2', url: !isLambda ? 'http://127.0.0.1:5110' : 'https://api.elsewhere.com/other' },
 ],
});

const server = new ApolloServer({
  gateway,
  subscriptions: false,
  uploads: false,
  context: ({ event, context }) => ({
    headers: event.headers,
    functionName: context.functionName,
    event,
    context,
  }),
  playground: true,
  introspection: true,
});

if (!isLambda) {
    server.listen().then(({ url }) => {
      console.log(` Server ready at ${url}`);
    });
} else {
    exports.graphql = server.createHandler({
      cors: {
        origin: '*',
        credentials: true,
      },
    });
}

我使用的 NPM 模块是:

npm install  @apollo/gateway apollo-server-lambda graphql

关于此处可能出现的问题的任何指示?

2020 年 5 月 25 日更新 这似乎与我在 AWS Gateway 中选择 HTTP 还是 REST 有关,HTTP 让我克服了这个错误,但我不知道我需要做什么才能让它在 REST 中工作

谢谢

克里斯

你不会让它在 REST 中工作,因为 apollo 的代码没有考虑从 AWS API 网关接收输入。

它希望处理整个请求。因此,要么您使用 API 网关作为代理,要么您必须伪造它期望存在的所有其他属性。

这就是我在无需添加特定于 AWS 的更改的情况下解决问题的方法。请注意,这是在 Typescript 中,我希望没关系:

我将我的调用包装在一个 main 函数中并将其放入


function runApollo(event: APIGatewayProxyEvent, context: Context, apollo: any) {
  return new Promise((resolve, reject) => {
    const callback = (error: any, body: any) =>
      error ? reject(error) : resolve(body);
    apollo(event, context, callback);
  });
}

export async function main(
  event: APIGatewayProxyEvent,
  context: Context,
  cb: Callback
) {
  const apollo = server.createHandler({
    cors: {
      origin: "*",
      credentials: true,
    },
  });

  // HERE IS WHERE YOU BACKFILL THE HEADERS
  event.httpMethod = event.httpMethod || "POST";
  event.headers = {
    "content-type": "application/json",
    ...(event.headers || {}),
  };
 // END BACKFILL

  try {
    const response = await runApollo(event, context, apollo);
    return response;
  } catch (err) {
    cb(err, null);
  }
}

我有其他原因需要包装器,添加监控、日志记录等。但这解决了我的问题。我没有 运行 这段代码(因为我只是提取了我的方法所特有的内容),但是您真正需要的部分在注释之间。