无服务器框架 + AWS + Lambda + DynamoDB + GraphQL + Apollo Server = 无法进行 POST 请求工作
Serverless framework + AWS + Lambda + DynamoDB + GraphQL + Apollo Server = Can't make POST Request Work
好的,几天前我就一直在处理这个问题。
我试着学习这个教程:
https://serverless.com/blog/make-serverless-graphql-api-using-lambda-dynamodb/
并使其与 apollo-server-lambda 一起工作。本教程帮助:
https://medium.com/vessels/apollo-server-serverless-graphql-bliss-68e8e15195ac
问题是当您尝试使用与 DynamoDB 建立真实连接的 apollo 服务器 lambda 时(对我而言)没有任何效果。我得到了一个错误列表,我已经记不起来了,这真令人沮丧。
这是我的代码:
# serverless.yml
service: graphql-api
provider:
name: aws
runtime: nodejs6.10
region: eu-west-3
stage: dev
environment:
DYNAMODB_TABLE: ${self:service}-${self:provider.stage}
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:GetItem
- dynamodb:UpdateItem
Resource: "arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:provider.environment.DYNAMODB_TABLE}"
resources:
Resources:
NicknamesTable:
Type: 'AWS::DynamoDB::Table'
Properties:
AttributeDefinitions:
- AttributeName: firstName
AttributeType: S
KeySchema:
- AttributeName: firstName
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
TableName: ${self:provider.environment.DYNAMODB_TABLE}
functions:
graphql:
handler: handler.graphql
events:
- http:
path: graphql
method: post
cors: true
- http:
path: graphql
method: get
cors: true
我的经纪人:
# handler.js
const AWS = require('aws-sdk');
const server = require("apollo-server-lambda");
const makeExecutableSchema = require('graphql-tools').makeExecutableSchema;
const dynamoDb = new AWS.DynamoDB.DocumentClient();
const promisify = foo => new Promise((resolve, reject) => {
foo((error, result) => {
if (error) {
reject(error)
} else {
resolve(result)
}
})
})
const getGreeting = firstName => promisify(callback =>
dynamoDb.get({
TableName: process.env.DYNAMODB_TABLE,
Key: { firstName },
}, callback))
.then(result => {
if (!result.Item) {
return firstName
}
return result.Item.nickname
})
.then(name => `Hello, ${name}.`)
// add method for updates
const changeNickname = (firstName, nickname) => promisify(callback =>
dynamoDb.update({
TableName: process.env.DYNAMODB_TABLE,
Key: { firstName },
UpdateExpression: 'SET nickname = :nickname',
ExpressionAttributeValues: {
':nickname': nickname
}
}, callback))
.then(() => nickname)
const typeDefs = `
type Query {
greeting(firstName: String!): String
}
type Mutation {
changeNickname(
firstName: String!
nickname: String!
): String
}
`;
const resolvers = {
Query: {
greeting: (_, { firstName }) => getGreeting(firstName),
},
Mutation: {
changeNickname: (_, { firstName, nickname }) => changeNickname(firstName, nickname),
}
};
exports.graphql = function (event, context, callback) {
const callbackFilter = function (error, output) {
output.headers = output.header || {};
output.headers['Access-Control-Allow-Origin'] = '*';
callback(error, output);
};
const handler = server.graphqlLambda({ schema: makeExecutableSchema({ typeDefs, resolvers }) });
return handler(event, context, callbackFilter);
};
我试过使用 Apollo 1 和 2,没有用。我回到了版本 1,因为有更多关于它的论坛帖子。大多数情况下我有 "internal server error"。我尝试了在 apollo 文档上找到的不同版本的服务器,但我的所有请求都失败了,在终端上使用 curl 或直接在 AWS 上的 API 网关上测试功能。我按照此文档编写请求正文:https://www.apollographql.com/docs/apollo-server/requests.html
这是我的 cloudwatch 日志:
(node:1) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): SyntaxError: Unexpected token = in JSON at position 8
任何帮助将不胜感激!!
好的,我找到问题了。当你使用 put 函数时,你无法获取刚刚插入到 dynamoDB 中的新项目。你必须把 "ReturnValues: 'ALL_OLD'" 放在你的 params 对象中(put 函数的第一个参数),这样就不会抛出错误,你应该 return 你想要的值,因为你刚刚在数据库中输入了它们.
此处有更多详细信息:
好的,几天前我就一直在处理这个问题。
我试着学习这个教程: https://serverless.com/blog/make-serverless-graphql-api-using-lambda-dynamodb/
并使其与 apollo-server-lambda 一起工作。本教程帮助:
https://medium.com/vessels/apollo-server-serverless-graphql-bliss-68e8e15195ac
问题是当您尝试使用与 DynamoDB 建立真实连接的 apollo 服务器 lambda 时(对我而言)没有任何效果。我得到了一个错误列表,我已经记不起来了,这真令人沮丧。
这是我的代码:
# serverless.yml
service: graphql-api
provider:
name: aws
runtime: nodejs6.10
region: eu-west-3
stage: dev
environment:
DYNAMODB_TABLE: ${self:service}-${self:provider.stage}
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:GetItem
- dynamodb:UpdateItem
Resource: "arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:provider.environment.DYNAMODB_TABLE}"
resources:
Resources:
NicknamesTable:
Type: 'AWS::DynamoDB::Table'
Properties:
AttributeDefinitions:
- AttributeName: firstName
AttributeType: S
KeySchema:
- AttributeName: firstName
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
TableName: ${self:provider.environment.DYNAMODB_TABLE}
functions:
graphql:
handler: handler.graphql
events:
- http:
path: graphql
method: post
cors: true
- http:
path: graphql
method: get
cors: true
我的经纪人:
# handler.js
const AWS = require('aws-sdk');
const server = require("apollo-server-lambda");
const makeExecutableSchema = require('graphql-tools').makeExecutableSchema;
const dynamoDb = new AWS.DynamoDB.DocumentClient();
const promisify = foo => new Promise((resolve, reject) => {
foo((error, result) => {
if (error) {
reject(error)
} else {
resolve(result)
}
})
})
const getGreeting = firstName => promisify(callback =>
dynamoDb.get({
TableName: process.env.DYNAMODB_TABLE,
Key: { firstName },
}, callback))
.then(result => {
if (!result.Item) {
return firstName
}
return result.Item.nickname
})
.then(name => `Hello, ${name}.`)
// add method for updates
const changeNickname = (firstName, nickname) => promisify(callback =>
dynamoDb.update({
TableName: process.env.DYNAMODB_TABLE,
Key: { firstName },
UpdateExpression: 'SET nickname = :nickname',
ExpressionAttributeValues: {
':nickname': nickname
}
}, callback))
.then(() => nickname)
const typeDefs = `
type Query {
greeting(firstName: String!): String
}
type Mutation {
changeNickname(
firstName: String!
nickname: String!
): String
}
`;
const resolvers = {
Query: {
greeting: (_, { firstName }) => getGreeting(firstName),
},
Mutation: {
changeNickname: (_, { firstName, nickname }) => changeNickname(firstName, nickname),
}
};
exports.graphql = function (event, context, callback) {
const callbackFilter = function (error, output) {
output.headers = output.header || {};
output.headers['Access-Control-Allow-Origin'] = '*';
callback(error, output);
};
const handler = server.graphqlLambda({ schema: makeExecutableSchema({ typeDefs, resolvers }) });
return handler(event, context, callbackFilter);
};
我试过使用 Apollo 1 和 2,没有用。我回到了版本 1,因为有更多关于它的论坛帖子。大多数情况下我有 "internal server error"。我尝试了在 apollo 文档上找到的不同版本的服务器,但我的所有请求都失败了,在终端上使用 curl 或直接在 AWS 上的 API 网关上测试功能。我按照此文档编写请求正文:https://www.apollographql.com/docs/apollo-server/requests.html
这是我的 cloudwatch 日志:
(node:1) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): SyntaxError: Unexpected token = in JSON at position 8
任何帮助将不胜感激!!
好的,我找到问题了。当你使用 put 函数时,你无法获取刚刚插入到 dynamoDB 中的新项目。你必须把 "ReturnValues: 'ALL_OLD'" 放在你的 params 对象中(put 函数的第一个参数),这样就不会抛出错误,你应该 return 你想要的值,因为你刚刚在数据库中输入了它们.
此处有更多详细信息: