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