In this tutorial, we will cover how we can leverage Appwrite’s Cloud functions feature to execute certain tasks when certain events take place in the server. You can find a complete list of available system events here.
In this example, we will demonstrate how we can detect objects in an image that the user has uploaded. This could be useful if you’re building something like google photos where you would like to categorize photos based on objects in the image.
For the sake of this example, we will be using Cloudmersive's People and Object Detection API. A similar concept applies to other API providers like Google’s Vision API or Amazon’s Recognition API. So let’s get started.
Create your Cloud Function
The first step is to create a Cloudmersive account and obtain the free tier API Key. Now it's time to create your Cloud Function in the Appwrite Console. Head over to the Functions section of your console and select Add Function. You can give your function a funky new name and select the preferred environment. We will be using Python for this example.
Let's write some code
The next step is to write the code that will be executed and upload it. Create a directory to hold your Cloud Function. Then create your main code file and a requirements.txt
.
$ mkdir cloud-functions-demo
$ cd cloud-functions-demo
$ touch main.py
$ touch requirements.txt
We will be using two dependencies for this example
- cloudmersive-image-api-client
- appwrite
Add these to your requirements.txt
. We would typically perform a pip install
at this stage but that would install the libraries in the shared libraries path. We need the libraries to be installed in the same folder so that they can be packaged easily.
Run the following command to install the libraries inside the local .appwrite
directory. Appwrite’s Python environment will know how to autoload a file from that directory without any special configuration.
PIP_TARGET=./.appwrite pip install -r ./requirements.txt --upgrade --ignore-installed
Great. It’s time to start editing the main.py
file. We start by importing the relevant libraries.
from __future__ import print_function
import time
from pprint import pprint
import json
import os
# For cloud vision API
import cloudmersive_image_api_client
from cloudmersive_image_api_client.rest import ApiException
# Appwrite SDK
from appwrite.client import Client
from appwrite.services.storage import Storage
We will use a temporary file to access the image during the function execution. Let’s give this file a name. This is required because the Cloudmersive library expects a file path and not binary data as input.
FILENAME = "temp.jpg"
When a function is triggered by an event, we can obtain a lot of metadata about the event from some special environment variables that are set by Appwrite. A complete list is available here. In our case, we need the ID of the file that was uploaded in order to fetch it. Appwrite conveniently exposes this information as an environment variable named APPWRITE_FUNCTION_EVENT_PAYLOAD
. Let’s parse this JSON string to retrieve the file ID.
# Triggered by the storage.files.create event
payload = json.loads(os.environ["APPWRITE_FUNCTION_EVENT_PAYLOAD"])
fileID = payload["$id"]
Now it’s time to set up the Appwrite SDK
# Setup appwrite client
client = Client()
client.set_endpoint('http://192.168.1.6/v1') # PRIVATE IP OF YOUR APPWRITE CONTAINER
client.set_project('5fca866c65afc') # YOUR PROJECT ID
client.set_key(os.environ["APPWRITE_KEY"])
Note: Within the Cloud Function, you cannot use localhost to refer to your Appwrite server, because localhost refers to your own runtime environment. You will have to find the private IP of your default network interface using ifconfig (usually eth0 in linux or en0 in macOS).
Using the SDK, lets fetch the image and save it:
# Get the image file
storage = Storage(client)
result = storage.get_file_preview(fileID)
# Save the file to the container
with open(FILENAME, "wb") as newFile:
newFile.write(result)
We’re almost done. Now we will set up the Cloudmersive SDK and make our API request
# Configure API key authorization: Apikey
configuration = cloudmersive_image_api_client.Configuration()
configuration.api_key['Apikey'] = os.environ['API_KEY']
# create an instance of the API class
api_instance = cloudmersive_image_api_client.RecognizeApi(cloudmersive_image_api_client.ApiClient(configuration))
image_file = FILENAME # file | Image file to perform the operation on. Common file formats such as PNG, JPEG are supported.
try:
# Detect objects including types and locations in an image
api_response = api_instance.recognize_detect_objects(image_file)
pprint(api_response)
except ApiException as e:
print("Exception when calling RecognizeApi->recognize_detect_objects: %s\n" % e)
Packaging the Cloud function
Before we can package our cloud function, we need to ensure that our directory has the following structure.
.
├── .appwrite/
├── main.py
└── requirements.txt
We package the function by creating a tar file out of our folder.
$ cd ..
$ tar -zcvf code.tar.gz cloud-functions-demo
We can now upload this tarfile to our function’s dashboard by selecting the Deploy Tag option. Our entry point command, in this case, would be:
$ python main.py
Note: You can also automate the code upload process using the Appwrite server SDK latest version and your CI server. In future versions, Appwrite will also support this process using a dedicated CLI tool, directly from your terminal.
Once created, we need to define a trigger for the function. In our case, we wish to trigger it whenever a new file is uploaded to the Appwrite server. So we would be interested in the storage.files.create
event. The trigger can be enabled under the Settings tab of the function.
Once the triggers are enabled, it’s time for our final step, Function Variables. Appwrite allows you to securely store secret keys using Appwrite Function Variables which will be available as environment variables to your program. The best part is that these keys are encrypted and stored securely on Appwrite’s internal DB. In this example, we have used two environment variables namely API_KEY
(Cloudmersive API Key) and APPWRITE_KEY
(Appwrite API Key) so let’s add them to the Function Variables. Don’t forget to click the Update option once you’re happy with your settings.
Great! We’re done with all the setup. All that’s left now is to test the Cloud Function.
Testing
Now it’s time to test your shiny new Cloud Function! Head over to the Storage section of Appwrite and create a new file by clicking on the ‘+’ button at the bottom right. Choose an image of your choice and click Create.
Your Cloud Function would now have been triggered. You can check it out by heading over to Functions > Your Function Name > Logs
Once the execution is complete, you can check the response from the API.
And in a few simple steps, we successfully deployed our first Cloud Function. The possibilities with Cloud Functions are endless! Stay tuned for more Cloud Function ideas from the Appwrite Team.
Learn More
- You can find the complete code sample and lots of other demos in our Cloud Functions Demo Repo.
- Check out Appwrite's Github Repo.
- Our Discord Server is the place to be if you ever get stuck.
- You can find all our Documentation here.
Credits
Photo by Arseny Togulev on Unsplash
Top comments (1)
This is some really cool stuff 🥳🤯