@as-integrations/aws-lambda
开始
阿波罗服务器作为您Lambda处理器的一部分运行,处理GraphQL请求. 这个软件包可以方便地将阿波罗服务器与AWS Lambda集成. 此集成包含为 ProxyV1, ProxyV2 和 ALB 事件的内置请求处理功能 带有可扩展打字功能。您也可以通过 自定义处理器 如果其他人认为它们有价值,作为公关提交.
首先,安装阿波罗服务器,graphql-js,以及Lambda处理器包:
npm install @apollo/server graphql @as-integrations/aws-lambda
然后,写下以下 server.mjs.(通过使用.mjs扩展名,节点将文件作为模块,使我们能够使用无害环境管理) import 语法. )
import { ApolloServer } from '@apollo/server';
import {
startServerAndCreateLambdaHandler,
handlers,
} from '@as-integrations/aws-lambda';
// The GraphQL schema
const typeDefs = `#graphql
type Query {
hello: String!
}
`;
// A map of functions which return data for the schema.
const resolvers = {
Query: {
hello: () => 'world',
},
};
// Set up Apollo Server
const server = new ApolloServer({
typeDefs,
resolvers,
});
export default startServerAndCreateLambdaHandler(
server,
handlers.createAPIGatewayProxyEventV2RequestHandler(),
);
A. 背景情况
如同所有阿波罗服务器4集成一样,上下文解析是在集成中完成的. 就Lambda一体化而言,它看起来将如下:
import { ApolloServer } from '@apollo/server';
import {
startServerAndCreateLambdaHandler,
handlers,
} from '@as-integrations/aws-lambda';
type ContextValue = {
isAuthenticated: boolean;
};
// The GraphQL schema
const typeDefs = `#graphql
type Query {
hello: String!
isAuthenticated: Boolean!
}
`;
// Set up Apollo Server
const server = new ApolloServer<ContextValue>({
typeDefs,
resolvers: {
Query: {
hello: () => 'world',
isAuthenticated: (root, args, context) => {
// For context typing to be valid one of the following must be implemented
// 1. `resolvers` defined inline in the server config (not particularly scalable, but works)
// 2. Add the type in the resolver function. ex. `(root, args, context: ContextValue)`
// 3. Propagate the type from an outside definition like GraphQL Codegen
return context.isAuthenticated;
},
},
},
});
export default startServerAndCreateLambdaHandler(
server,
handlers.createAPIGatewayProxyEventV2RequestHandler(),
{
context: async ({ event }) => {
// Do some parsing on the event (parse JWT, cookie, auth header, etc.)
return {
isAuthenticated: true,
};
},
},
);
中间软件
因在传递到 @apollo/server 在返回之前,可以使用中间软件.
注意,此中间软件严格用于事件和结果突变,不应用于任何GraphQL修改. 为此, 插件 从
@apollo/server那样更合适.
例如,如果需要设置带有 V2 代理结果的饼干头,请参见以下代码示例:
import {
startServerAndCreateLambdaHandler,
handlers,
} from '@as-integrations/aws-lambda';
import type { APIGatewayProxyEventV2 } from 'aws-lambda';
import { server } from './server';
async function regenerateCookie(event: APIGatewayProxyEventV2) {
// ...
return 'NEW_COOKIE';
}
export default startServerAndCreateLambdaHandler(
server,
handlers.createAPIGatewayProxyEventV2RequestHandler(),
{
middleware: [
// Both event and result are intended to be mutable
async (event) => {
const cookie = await regenerateCookie(event);
return (result) => {
result.cookies.push(cookie);
};
},
],
},
);
中间软件打字
如果您想在中间软件阵列外定义严格输入的中间软件,那么最简单的方法是将您的请求处理器提取到变量中并使用 typeof typescript中的关键词。 您也可以手动使用 RequestHandler 键入并填入事件和结果值.
import {
startServerAndCreateLambdaHandler,
middleware,
handlers,
} from '@as-integrations/aws-lambda';
import type {
APIGatewayProxyEventV2,
APIGatewayProxyStructuredResultV2,
} from 'aws-lambda';
import { server } from './server';
const requestHandler = handlers.createAPIGatewayProxyEventV2RequestHandler();
// Utilizing typeof
const cookieMiddleware: middleware.MiddlewareFn<typeof requestHandler> = (
event,
) => {
// ...
return (result) => {
// ...
};
};
// Manual event filling
const otherMiddleware: middleware.MiddlewareFn<
RequestHandler<APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2>
> = (event) => {
// ...
return (result) => {
// ...
};
};
export default startServerAndCreateLambdaHandler(server, requestHandler, {
middleware: [
// cookieMiddleware will always work here as its signature is
// tied to the `requestHandler` above
cookieMiddleware,
// otherMiddleware will error if the event and result types do
// not sufficiently overlap, meaning it is your responsibility
// to keep the event types in sync, but the compiler may help
otherMiddleware,
],
});
中间软件短路
在某些情况下,中相软件功能可能需要执行端才能到达阿波罗服务器. 这可能是一个全球认证的守护者或会话符号查询.
为此,请求的中间软件函数接受 ResultType 或者说 Promise<ResultType> 作为返回类型。 如果中间软件决心达到这种值,则返回结果,不再执行.
import {
startServerAndCreateLambdaHandler,
middleware,
handlers,
} from '@as-integrations/aws-lambda';
import type {
APIGatewayProxyEventV2,
APIGatewayProxyStructuredResultV2,
} from 'aws-lambda';
import { server } from './server';
const requestHandler = handlers.createAPIGatewayProxyEventV2RequestHandler();
// Utilizing typeof
const sessionMiddleware: middleware.MiddlewareFn<typeof requestHandler> = (
event,
) => {
// ... check session
if (!event.headers['X-Session-Key']) {
// If header doesn't exist, return early
return {
statusCode: 401
body: 'Unauthorized'
}
}
};
export default startServerAndCreateLambdaHandler(server, requestHandler, {
middleware: [
sessionMiddleware,
],
});
事件延期
如果您有自定义的授权人, 或如果您需要的事件类型有自定义, 您必须自行通过 。 例如, 这里有一个请求, 可以访问 Lambda 授权者 :
import {
startServerAndCreateLambdaHandler,
middleware,
handlers,
} from '@as-integrations/aws-lambda';
import type { APIGatewayProxyEventV2WithLambdaAuthorizer } from 'aws-lambda';
import { server } from './server';
export default startServerAndCreateLambdaHandler(
server,
handlers.createAPIGatewayProxyEventV2RequestHandler<
APIGatewayProxyEventV2WithLambdaAuthorizer<{
myAuthorizerContext: string;
}>
>(), // This event will also be applied to the MiddlewareFn type
);
自定义请求处理器
当手动引用羊肉达时,或者当使用事件源时,我们目前不支持(free to create a PR),也许需要自定义请求处理器. 使用 handlers.createHandler 函数,它需要两个函数参数 eventParser 财务报告和审定财务报表 resultGenerator参数 EventType 财务报告和审定财务报表 ResultType。 。 。 .
eventParser 参数
有两种类型签名可用于解析事件:
方法 A: 帮助对象
此帮助对象有 4 个属性, 将完成全解析链, 并摘要列出将当前事件强制化为 HTTPGraphQLRequest。这是分析事件的建议方式.
parseHttpMethod(event: EventType): string
从请求中返回 HTTP 动词.
示例返回值: GET
parseQueryParams(event: EventType): string
从请求中返回原始查询参数字符串。 如果请求是预选类型, 您可能需要使用 URLSearchParams {\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}把它重新绑起来 {\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}你应该去查一下.
示例返回值: foo=1&bar=2
parseHeaders(event: EventType): HeaderMap
从这里导入 : import {HeaderMap} from "@apollo/server"· ;
从事件返回阿波罗服务器头图 . HeaderMap 为你自动规范外壳.
parseBody(event: EventType, headers: HeaderMap): string
还原出一具平正文字活体. 一定要解析任何基础64或字符集编码. 此处提供信头是为了方便,因为某些身体分析可能依赖于 content-type
方法 B: 解析器函数
如果帮助对象对您的使用大小写限制性太强, 则另一个选项是创建函数 (event: EventType): HTTPGraphQLRequest 作为签名。 在这里,你可以做任何分析, 你的责任是创建一个有效的 HTTPGraphQLRequest。 。 。 .
resultGenerator 参数
有两种可能的结果类型, success 财务报告和审定财务报表 error,它们将被定义为对象上的函数属性。 中间软件将 永远 运行,无论生成的结果来自成功还是出错。 属性有下列签名:
success(response: HTTPGraphQLResponse): ResultType
如果有完整的响应,则生成所期望的结果类型.
error(e: unknown): ResultType
鉴于未知类型错误, 生成结果 。 如果您想要创建一个基本解析器来捕捉所有东西, 请使用 Typescript 中的类型守护实例 .
error(e) {
if(e instanceof Error) {
return {
...
}
}
// If error cannot be determined, panic and use lambda's default error handler
// Might be advantageous to add extra logging here so unexpected errors can be properly handled later
throw e;
}
自定义处理器示例
import {
startServerAndCreateLambdaHandler,
handlers,
} from '@as-integrations/aws-lambda';
import type { APIGatewayProxyEventV2 } from 'aws-lambda';
import { HeaderMap } from '@apollo/server';
import { server } from './server';
type CustomInvokeEvent = {
httpMethod: string;
queryParams: string;
headers: Record<string, string>;
body: string;
};
type CustomInvokeResult =
| {
success: true;
body: string;
}
| {
success: false;
error: string;
};
const requestHandler = handlers.createRequestHandler<
CustomInvokeEvent,
CustomInvokeResult
>(
{
parseHttpMethod(event) {
return event.httpMethod;
},
parseHeaders(event) {
const headerMap = new HeaderMap();
for (const [key, value] of Object.entries(event.headers)) {
headerMap.set(key, value);
}
return headerMap;
},
parseQueryParams(event) {
return event.queryParams;
},
parseBody(event) {
return event.body;
},
},
{
success({ body }) {
return {
success: true,
body: body.string,
};
},
error(e) {
if (e instanceof Error) {
return {
success: false,
error: e.toString(),
};
}
console.error('Unknown error type encountered!', e);
throw e;
},
},
);
export default startServerAndCreateLambdaHandler(server, requestHandler);