Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

## Deployment targets
### Cloud Run
* [`cloud_run_http`](./cloud_run_http/) - Deploying an HTTP function to [Cloud Run](http://cloud.google.com/run) with the Functions Framework
* [`cloud_run_http`](./cloud_run_http/) - Deploying an HTTP function to [Cloud Run](http.cloud.google.com/run) with the Functions Framework
* [`cloud_run_event`](./cloud_run_event/) - Deploying a CloudEvent function to [Cloud Run](http://cloud.google.com/run) with the Functions Framework
* [`cloud_run_cloud_events`](cloud_run_cloud_events/) - Deploying a [CloudEvent](https://github.com/cloudevents/sdk-python) function to [Cloud Run](http://cloud.google.com/run) with the Functions Framework
* [`cloud_run_async`](./cloud_run_async/) - Deploying asynchronous HTTP and CloudEvent functions to [Cloud Run](http://cloud.google.com/run) with the Functions Framework
* [`cloud_run_streaming_http`](./cloud_run_streaming_http/) - Deploying streaming HTTP functions to [Cloud Run](http://cloud.google.com/run) with the Functions Framework

## Development Tools
* [`docker-compose`](./docker-compose) -
Expand Down
58 changes: 58 additions & 0 deletions examples/cloud_run_async/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Deploying async functions to Cloud Run

This sample shows how to deploy asynchronous functions to [Cloud Run](http://cloud.google.com/run) with the Functions Framework. It includes examples for both HTTP and CloudEvent functions, which can be found in the `main.py` file.

## Dependencies
Install the dependencies for this example:
```sh
pip install -r requirements.txt
```

## Running locally

### HTTP Function
To run the HTTP function locally, use the `functions-framework` command:
```sh
functions-framework --target=hello_async_http
```
Then, send a request to it from another terminal:
```sh
curl localhost:8080
# Output: Hello, async world!
```

### CloudEvent Function
To run the CloudEvent function, specify the target and set the signature type:
```sh
functions-framework --target=hello_async_cloudevent --signature-type=cloudevent
```
Then, in another terminal, send a sample CloudEvent using the provided script:
```sh
python send_cloud_event.py
```

## Deploying to Cloud Run
You can deploy these functions to Cloud Run using the `gcloud` CLI.

### HTTP Function
```sh
gcloud run deploy async-http-function \
--source . \
--function hello_async_http \
--base-image python312 \
--region <YOUR_REGION> \
--allow-unauthenticated
```

### CloudEvent Function
```sh
gcloud run deploy async-cloudevent-function \
--source . \
--function hello_async_cloudevent \
--base-image python312 \
--region <YOUR_REGION> \
--set-env-vars=FUNCTION_SIGNATURE_TYPE=cloudevent \
--allow-unauthenticated
```
After deploying, you can invoke the CloudEvent function by sending an HTTP POST request with a CloudEvent payload to its URL.

36 changes: 36 additions & 0 deletions examples/cloud_run_async/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import functions_framework.aio

@functions_framework.aio.http
async def hello_async_http(request):
"""
An async HTTP function.
Args:
request (starlette.requests.Request): The request object.
Returns:
The response text, or an instance of any Starlette response class
(e.g. `starlette.responses.Response`).
"""
return "Hello, async world!"

@functions_framework.aio.cloud_event
async def hello_async_cloudevent(cloud_event):
"""
An async CloudEvent function.
Args:
cloud_event (cloudevents.http.CloudEvent): The CloudEvent object.
"""
print(f"Received event with ID: {cloud_event['id']} and data {cloud_event.data}")
5 changes: 5 additions & 0 deletions examples/cloud_run_async/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Function dependencies
functions-framework

# For testing
httpx
39 changes: 39 additions & 0 deletions examples/cloud_run_async/send_cloud_event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/local/bin/python

# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import asyncio
import httpx

from cloudevents.http import CloudEvent, to_structured

async def main():
# Create a cloudevent
attributes = {
"Content-Type": "application/json",
"source": "from-galaxy-far-far-away",
"type": "cloudevent.greet.you",
}
data = {"name": "john"}

event = CloudEvent(attributes, data)

# Send the event to the local functions-framework server
headers, data = to_structured(event)

async with httpx.AsyncClient() as client:
await client.post("http://localhost:8080/", headers=headers, data=data)

if __name__ == "__main__":
asyncio.run(main())
56 changes: 56 additions & 0 deletions examples/cloud_run_streaming_http/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Deploying streaming functions to Cloud Run

This sample shows how to deploy streaming functions to [Cloud Run](http://cloud.google.com/run) with the Functions Framework. The `main.py` file contains examples for both synchronous and asynchronous streaming.

## Dependencies
Install the dependencies for this example:
```sh
pip install -r requirements.txt
```

## Running locally

### Synchronous Streaming
To run the synchronous streaming function locally:
```sh
functions-framework --target=hello_stream
```
Then, send a request to it from another terminal:
```sh
curl localhost:8080
```

### Asynchronous Streaming
To run the asynchronous streaming function locally:
```sh
functions-framework --target=hello_stream_async
```
Then, send a request to it from another terminal:
```sh
curl localhost:8080
```

## Deploying to Cloud Run
You can deploy these functions to Cloud Run using the `gcloud` CLI.

### Synchronous Streaming
```sh
gcloud run deploy streaming-function \
--source . \
--function hello_stream \
--base-image python312 \
--region <YOUR_REGION> \
--allow-unauthenticated
```

### Asynchronous Streaming
```sh
gcloud run deploy streaming-async-function \
--source . \
--function hello_stream_async \
--base-image python312 \
--region <YOUR_REGION> \
--allow-unauthenticated
```

```
59 changes: 59 additions & 0 deletions examples/cloud_run_streaming_http/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import time
import asyncio
import functions_framework
import functions_framework.aio
from starlette.responses import StreamingResponse

# Helper function for the synchronous streaming example.
def slow_numbers(minimum, maximum):
yield '<html><body><ul>'
for number in range(minimum, maximum + 1):
yield '<li>%d</li>' % number
time.sleep(0.5)
yield '</ul></body></html>'

@functions_framework.http
def hello_stream(request):
"""
A synchronous HTTP function that streams a response.
Args:
request (flask.Request): The request object.
Returns:
A generator, which will be streamed as the response.
"""
generator = slow_numbers(1, 10)
return generator, {'Content-Type': 'text/html'}

# Helper function for the asynchronous streaming example.
async def slow_numbers_async(minimum, maximum):
yield '<html><body><ul>'
for number in range(minimum, maximum + 1):
yield '<li>%d</li>' % number
await asyncio.sleep(0.5)
yield '</ul></body></html>'

@functions_framework.aio.http
async def hello_stream_async(request):
"""
An asynchronous HTTP function that streams a response.
Args:
request (starlette.requests.Request): The request object.
Returns:
A starlette.responses.StreamingResponse.
"""
generator = slow_numbers_async(1, 10)
return StreamingResponse(generator, media_type='text/html')
2 changes: 2 additions & 0 deletions examples/cloud_run_streaming_http/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Function dependencies
functions-framework
Loading