UNPKG

@trpc/server

Version:

The tRPC server library

222 lines (167 loc) • 10.6 kB
--- name: adapter-aws-lambda description: Deploy tRPC on AWS Lambda with awsLambdaRequestHandler() from @trpc/server/adapters/aws-lambda for API Gateway v1 (REST, APIGatewayProxyEvent) and v2 (HTTP, APIGatewayProxyEventV2), and Lambda Function URLs. Enable response streaming with awsLambdaStreamingRequestHandler() wrapped in awslambda.streamifyResponse(). CreateAWSLambdaContextOptions provides event and context for context creation. Use one {proxy+} resource for httpBatchLink, or httpLink for a resource per procedure. requires: - server-setup sources: - www/v11/docs/server/adapters/aws-lambda.md - www/v11/docs/server/adapters.md metadata: type: core library: trpc library_version: 11.23.0 --- <!-- Generated from www/v11/docs/server/adapters/aws-lambda.md by www/build/skills.ts. Edit the docs instead. --> # AWS Lambda + API Gateway Adapter From https://trpc.io/docs/server/adapters/aws-lambda ## AWS Lambda adapter The AWS Lambda adapter is supported for API Gateway [REST API(v1)](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-rest-api.html) and [HTTP API(v2)](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api.html), and [Lambda Function URL](https://docs.aws.amazon.com/lambda/latest/dg/urls-configuration.html) use cases. > `httpBatchLink` requires the router to work on a single API Gateway Resource (as shown in the [example](https://github.com/trpc/trpc/tree/main/examples/lambda-api-gateway)). > If you'd like to have a Resource per procedure, you can use the `httpLink` instead ([more info](https://github.com/trpc/trpc/issues/5738#issuecomment-2130001522)). ## Example apps <table> <thead> <tr> <th>Description</th> <th>Links</th> </tr> </thead> <tbody> <tr> <td>API Gateway with NodeJS client.</td> <td> <ul> <li><a href="https://github.com/trpc/trpc/tree/main/examples/lambda-api-gateway">Source</a></li> </ul> </td> </tr> <tr> <td>API Gateway REST API with response streaming.</td> <td> <ul> <li><a href="https://github.com/trpc/trpc/tree/main/examples/lambda-api-gateway-streaming">Source</a></li> </ul> </td> </tr> </tbody> </table> ## How to add tRPC ### 1. Install deps ```bash yarn add @trpc/server ``` ### 2. Create a tRPC router Implement your tRPC router. A sample router is given below: ```ts no-check title="server.ts" import { initTRPC } from '@trpc/server'; import { z } from 'zod'; export const t = initTRPC.create(); const appRouter = t.router({ getUser: t.procedure.input(z.string()).query((opts) => { opts.input; // string return { id: opts.input, name: 'Bilbo' }; }), }); // export type definition of API export type AppRouter = typeof appRouter; ``` ### 3. Use the Amazon API Gateway adapter tRPC includes an adapter for API Gateway out of the box. This adapter lets you run your routes through the API Gateway handler. ```ts no-check title="server.ts" import type { APIGatewayProxyEventV2 } from 'aws-lambda'; import type { CreateAWSLambdaContextOptions } from '@trpc/server/adapters/aws-lambda'; import { awsLambdaRequestHandler } from '@trpc/server/adapters/aws-lambda'; import { appRouter } from './router'; // created for each request const createContext = ({ event, context, }: CreateAWSLambdaContextOptions<APIGatewayProxyEventV2>) => ({}); // no context type Context = Awaited<ReturnType<typeof createContext>>; export const handler = awsLambdaRequestHandler({ router: appRouter, createContext, }) ``` `awsLambdaRequestHandler` accepts the [options every adapter takes](https://trpc.io/docs/server/adapters#common-options), like `onError` and `maxBatchSize`. Build & deploy your code, now use your API Gateway URL to call your function. | Endpoint | HTTP URI | | --------- | ------------------------------------------------------------------------------------------------------------ | | `getUser` | `GET https://<execution-api-link>/getUser?input=INPUT` <br/><br/>where `INPUT` is a URI-encoded JSON string. | #### A word about payload format version API Gateway has two different event data formats when it invokes a Lambda. For REST APIs they should be version "1.0"(`APIGatewayProxyEvent`), but you can choose which for HTTP APIs by stating either version "1.0" or "2.0". - Version 1.0: `APIGatewayProxyEvent` - Version 2.0: `APIGatewayProxyEventV2` To infer what version you might have, supply the context as following: ```ts no-check function createContext({ event, context, }: CreateAWSLambdaContextOptions<APIGatewayProxyEvent>) { // ... } // CreateAWSLambdaContextOptions<APIGatewayProxyEvent> or CreateAWSLambdaContextOptions<APIGatewayProxyEventV2> ``` [Read more here about payload format version](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html) ## AWS Lambda Response Streaming Adapter AWS Lambda supports streaming responses to clients with both Lambda Function URLs and API Gateway REST APIs. > Response streaming is supported for Lambda Function URLs and API Gateway REST APIs. For API Gateway REST APIs, you need to configure the integration with `responseTransferMode: STREAM`. [Read more about Lambda response streaming](https://aws.amazon.com/blogs/compute/introducing-aws-lambda-response-streaming/) and [API Gateway response streaming](https://aws.amazon.com/blogs/compute/building-responsive-apis-with-amazon-api-gateway-response-streaming/). ### Response Streaming The signature of a streaming handler is different from the default handler. The streaming handler additionally receives a writable stream parameter, `responseStream`, besides the default node handler parameters, `event` and `context`. To indicate that Lambda should stream your responses, you must wrap your function handler with the `awslambda.streamifyResponse()` decorator. > Note that the `awslambda` namespace is automatically provided by the Lambda execution environment. You can import the types from `@types/aws-lambda` to augment the global namespace with the `awslambda` namespace. With streaming, a procedure that returns an async generator, like `iterable` below, sends each value as it's yielded to clients using [`httpBatchStreamLink`](https://trpc.io/docs/client/links/httpBatchStreamLink). ```ts no-check title="server.ts" /// <reference types="aws-lambda" /> import type { APIGatewayProxyEventV2 } from 'aws-lambda'; import type { CreateAWSLambdaContextOptions } from '@trpc/server/adapters/aws-lambda'; import { awsLambdaStreamingRequestHandler } from '@trpc/server/adapters/aws-lambda'; import { appRouter } from './router'; // created for each request const createContext = ({ event, context, }: CreateAWSLambdaContextOptions<APIGatewayProxyEventV2>) => ({ // your context }); type Context = Awaited<ReturnType<typeof createContext>>; export const handler = awslambda.streamifyResponse( awsLambdaStreamingRequestHandler({ router: appRouter, createContext, }), ); ``` ## Common mistakes - **Using `httpBatchLink` with a resource per procedure.** A batch request puts several procedures in one path, like `/getUser,createUser`, which none of those resources match. Use one greedy resource like `/trpc/{proxy+}`, which tRPC reads the procedure path from, or switch to `httpLink`. - **Forgetting `awslambda.streamifyResponse()`.** Without it, Lambda calls `awsLambdaStreamingRequestHandler` as a regular handler, which has no response stream to write to. - **Expecting the default handler to stream.** `awsLambdaRequestHandler` buffers the whole response before returning it, so `httpBatchStreamLink` responses arrive all at once. Use the [streaming handler](https://trpc.io/docs/server/adapters/aws-lambda#response-streaming) instead. ## Common options Every HTTP adapter accepts these options, next to its own (like `endpoint` for Fetch, or `basePath` for Standalone): | Option | Description | | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | | `router` | Your app router. Required. | | `createContext` | Creates the [context](https://trpc.io/docs/server/context) for each request. It receives the adapter's own objects (e.g. `req` and `res`) plus `info`. | | `onError` | Called with `{ error, type, path, input, ctx, req }` for every error, e.g. to report it. See [Error handling](https://trpc.io/docs/server/error-handling#handling-errors). | | `responseMeta` | Returns `{ status, headers }` for the response, e.g. for [caching](https://trpc.io/docs/server/caching). | | `allowBatching` | Set to `false` to reject batch requests. Defaults to `true`. | | `maxBatchSize` | Rejects batch requests with more calls than this with a `400 Bad Request`. Set `maxItems` on your batch link to the same or a lower value. | | `allowMethodOverride` | Accepts queries sent as `POST`, for clients that set `methodOverride: 'POST'` on their link. Defaults to `false`. | The Node.js adapters (Standalone, Express and Next.js) also accept: - `maxBodySize`: the largest request body in bytes; larger ones are rejected with `413 PAYLOAD_TOO_LARGE`. - `middleware`: a connect-style `(req, res, next)` function that runs before tRPC, e.g. [`cors()`](https://trpc.io/docs/server/adapters/standalone#handling-cors--options). ```ts no-check title="server.ts" import { createHTTPServer } from '@trpc/server/adapters/standalone'; import { appRouter } from './router'; createHTTPServer({ router: appRouter, createContext: () => ({}), onError({ error, path }) { console.error(`tRPC error on '${path}':`, error); }, maxBatchSize: 10, maxBodySize: 1_000_000, // 1 MB }).listen(3000); ``` From https://trpc.io/docs/server/adapters#common-options ## Related skills - `server-setup` (https://trpc.io/docs/server/overview): `npx @tanstack/intent@latest load @trpc/server#server-setup`