-
Notifications
You must be signed in to change notification settings - Fork 1.1k
feature(function): add custom functions documentation for AWS Amplify-backend #8176
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
josefaidt
merged 7 commits into
aws-amplify:main
from
MarlonJD:feature/function-custom-runtimes
Jan 8, 2025
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
63f71b5
feature(function): add custom functions documentation for AWS Amplify…
MarlonJD 03e2733
chore(function): rename function handler and update handler file path…
MarlonJD 4b0242f
docs(functions): improve documentation for Python and Go functions, c…
MarlonJD eb92ef5
docs(functions): clarify function invocation instructions and improve…
MarlonJD 4989b85
chore: fix capitalization in documentation.
MarlonJD 1ca323f
Update src/pages/[platform]/build-a-backend/functions/custom-function…
MarlonJD 724c4f4
Update src/pages/[platform]/build-a-backend/functions/custom-function…
josefaidt File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
230 changes: 230 additions & 0 deletions
230
src/pages/[platform]/build-a-backend/functions/custom-functions/index.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
import { getCustomStaticPath } from '@/utils/getCustomStaticPath'; | ||
|
||
export const meta = { | ||
title: 'Custom functions', | ||
description: | ||
'Use another AWS Lambda runtimes like Python, Golang to perform tasks and customize workflows.', | ||
platforms: [ | ||
'android', | ||
'angular', | ||
'flutter', | ||
'javascript', | ||
'nextjs', | ||
'react', | ||
'react-native', | ||
'swift', | ||
'vue' | ||
] | ||
}; | ||
|
||
export function getStaticPaths() { | ||
return getCustomStaticPath(meta.platforms); | ||
} | ||
|
||
export function getStaticProps(context) { | ||
return { | ||
props: { | ||
platform: context.params.platform, | ||
meta | ||
} | ||
}; | ||
} | ||
|
||
AWS Amplify Gen 2 functions are AWS Lambda functions that can be used to perform tasks and customize workflows in your Amplify app. Functions can be written in Node.js, Python, Go, or any [other language supported by AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html). | ||
|
||
<Callout warning> | ||
|
||
**Note:** [Fullstack Git-based environments](https://docs.amplify.aws/react/how-amplify-works/concepts/#fullstack-git-based-environments) do not support Docker for functions bundling out of the box. | ||
|
||
</Callout> | ||
|
||
In this guide, you will learn how to create Python and Go functions with Amplify functions. The examples shown in this guide do not use Docker to build functions. Instead, the examples use commands that run on your host system to build, and as such require the necessary tooling for the language you are using for your functions. | ||
|
||
## Python | ||
|
||
To get started, create a new directory and a resource file, `amplify/functions/say-hello/resource.ts`. Then, define the function with `defineFunction`: | ||
```ts title="amplify/functions/say-hello/resource.ts" | ||
import { execSync } from "node:child_process"; | ||
import * as path from "node:path"; | ||
import { fileURLToPath } from "node:url"; | ||
import { defineFunction } from "@aws-amplify/backend"; | ||
import { DockerImage, Duration } from "aws-cdk-lib"; | ||
import { Code, Function, Runtime } from "aws-cdk-lib/aws-lambda"; | ||
|
||
const functionDir = path.dirname(fileURLToPath(import.meta.url)); | ||
|
||
export const sayHelloFunctionHandler = defineFunction( | ||
(scope) => | ||
new Function(scope, "say-hello", { | ||
handler: "index.handler", | ||
runtime: Runtime.PYTHON_3_9, // or any other python version | ||
timeout: Duration.seconds(20), // default is 3 seconds | ||
code: Code.fromAsset(functionDir, { | ||
bundling: { | ||
image: DockerImage.fromRegistry("dummy"), | ||
local: { | ||
tryBundle(outputDir: string) { | ||
execSync( | ||
`python3 -m pip install -r ${path.join(functionDir, "requirements.txt")} -t ${path.join(outputDir)} --platform manylinux2014_x86_64 --only-binary=:all:` | ||
); | ||
execSync(`rsync -rLv ${functionDir}/* ${path.join(outputDir)}`); | ||
return true; | ||
}, | ||
}, | ||
}, | ||
}), | ||
}) | ||
); | ||
``` | ||
|
||
Next, create the corresponding handler file at `amplify/functions/say-hello/index.py`. This is where your function code will go. | ||
|
||
```ts title="amplify/functions/say-hello/index.py" | ||
import json | ||
|
||
def handler(event, context): | ||
return { | ||
"statusCode": 200, | ||
"body": json.dumps({ | ||
"message": "Hello World", | ||
}), | ||
} | ||
``` | ||
|
||
The handler file _must_ export a function named "handler". This is the entry point to your function. For more information on writing functions, refer to the [AWS documentation for Lambda function handlers using Python](https://docs.aws.amazon.com/lambda/latest/dg/python-handler.html). | ||
|
||
If you need Python packages, you can add them to a `requirements.txt` file in the same directory as your handler file. The `bundling` option in the `Code.fromAsset` method will install these packages for you. | ||
Create a `requirements.txt` file in the same directory as your handler file. This file should contain the names of the packages you want to install. For example: | ||
|
||
```txt title="amplify/functions/say-hello/requirements.txt" | ||
request==2.25.1 | ||
some-other-package>=1.0.0 | ||
``` | ||
|
||
You're now ready to deploy your python function. Next is the same process as the Node.js/TypeScript function. Go to [Common steps for all languages](#common-steps-for-all-languages) to continue. | ||
|
||
## Go | ||
To get started, Create a new directory and a resource file, `amplify/functions/say-hello/resource.ts`. Then, define the function with `defineFunction`: | ||
|
||
```ts title="amplify/functions/say-hello/resource.ts" | ||
import { execSync } from "node:child_process"; | ||
import * as path from "node:path"; | ||
import { fileURLToPath } from "node:url"; | ||
import { defineFunction } from "@aws-amplify/backend"; | ||
import { DockerImage, Duration } from "aws-cdk-lib"; | ||
import { Code, Function, Runtime } from "aws-cdk-lib/aws-lambda"; | ||
import { defineFunction } from "@aws-amplify/backend"; | ||
import { DockerImage, Duration } from "aws-cdk-lib"; | ||
import { Code, Function, Runtime } from "aws-cdk-lib/aws-lambda"; | ||
export const sayHelloFunctionHandler = defineFunction( | ||
(scope) => | ||
new Function(scope, "say-hello", { | ||
handler: "bootstrap", | ||
runtime: Runtime.PROVIDED_AL2023, | ||
timeout: Duration.seconds(3), // default is 3 seconds | ||
code: Code.fromAsset(functionDir, { | ||
bundling: { | ||
image: DockerImage.fromRegistry("dummy"), | ||
local: { | ||
tryBundle(outputDir: string) { | ||
execSync(`rsync -rLv ${functionDir}/* ${path.join(outputDir)}`); | ||
execSync( | ||
`cd ${path.join(outputDir)} && GOARCH=amd64 GOOS=linux go build -tags lambda.norpc -o ${path.join(outputDir)}/bootstrap ${functionDir}/main.go` | ||
); | ||
return true; | ||
}, | ||
}, | ||
}, | ||
}), | ||
}), | ||
); | ||
``` | ||
|
||
Next, create the corresponding handler file at `amplify/functions/say-hello/main.go`. This is where your function code will go. | ||
|
||
```go title="amplify/functions/say-hello/main.go" | ||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/aws/aws-lambda-go/lambda" | ||
) | ||
|
||
type Event struct { | ||
Arguments Arguments `json:"arguments"` | ||
} | ||
|
||
type Arguments struct { | ||
Title string `json:"phone"` | ||
Msg string `json:"msg"` | ||
} | ||
|
||
func HandleRequest(ctx context.Context, event Event) (string, error) { | ||
fmt.Println("Received event: ", event) | ||
|
||
// fmt.Println("Message sent to: ", event.Arguments.Msg) | ||
// You can use lambda arguments in your code | ||
|
||
return "Hello World!", nil | ||
} | ||
|
||
func main() { | ||
lambda.Start(HandleRequest) | ||
} | ||
``` | ||
|
||
Then you should run the following command to build the go function: | ||
```bash title="terminal" showLineNumbers={false} | ||
go mod init lambda | ||
``` | ||
then run to install the dependencies. | ||
|
||
```bash title="terminal" showLineNumbers={false} | ||
go mod tidy | ||
``` | ||
|
||
You're now ready to deploy your golang function. Next is the same process as the Node.js/TypeScript function. | ||
|
||
## Common steps for all languages | ||
|
||
Regardless of the language used, your function needs to be added to your backend. | ||
```ts title="amplify/backend.ts" | ||
// highlight-next-line | ||
import { sayHelloFunctionHandler } from './functions/say-hello/resource'; | ||
|
||
defineBackend({ | ||
// highlight-next-line | ||
sayHelloFunctionHandler, | ||
}); | ||
``` | ||
|
||
Now when you run `npx ampx sandbox` or deploy your app on Amplify, it will include your function. | ||
|
||
To invoke your function, we recommend adding your [function as a handler for a custom query with your Amplify Data resource](/[platform]/build-a-backend/data/custom-business-logic/). To get started, open your `amplify/data/resource.ts` file and specify a new query in your schema: | ||
|
||
```ts title="amplify/data/resource.ts" | ||
import { sayHelloFunctionHandler } from "../functions/say-hello/resource" | ||
|
||
const schema = a.schema({ | ||
// highlight-start | ||
sayHello: a | ||
.query() | ||
.arguments({ | ||
name: a.string(), | ||
}) | ||
.returns(a.string()) | ||
.handler(a.handler.function(sayHelloFunctionHandler)), | ||
// highlight-end | ||
}) | ||
|
||
export type Schema = ClientSchema<typeof schema> | ||
|
||
export const data = defineData({ | ||
schema, | ||
authorizationModes: { | ||
defaultAuthorizationMode: "iam", | ||
}, | ||
}) | ||
``` |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.