Serverless Function Examples - hendricksonja/serverless GitHub Wiki

Certainly! Below are two Python programs that can be used as serverless functions. These examples are simple yet demonstrate the core concepts of serverless functions, such as handling HTTP requests and processing data.


Example 1: Hello World Function

This serverless function returns a greeting message. It's a classic example to get started with serverless functions.

def main(args):
    """
    A simple serverless function that returns a greeting message.

    Args:
        args (dict): A dictionary of input arguments (e.g., query parameters or JSON payload).

    Returns:
        dict: A dictionary containing the 'body' of the response.
    """
    # Get the 'name' parameter from the input arguments
    name = args.get("name", "World")

    # Return the greeting message
    return {
        "body": f"Hello, {name}!"
    }

Explanation:

  • Function Entry Point: The main function is the standard entry point for serverless functions on many platforms.
  • Input Arguments: The args dictionary contains input parameters passed to the function.
  • Default Behavior: If no name is provided, it defaults to "World".
  • Response: Returns a dictionary with a body key containing the greeting message.

Usage:

  • Invoke via HTTP GET Request:

    GET https://your-function-url?name=Alice
    
  • Response:

    Hello, Alice!
    

Example 2: Data Summation Function

This function accepts a list of numbers via an HTTP POST request and returns their sum and average.

def main(args):
    """
    A serverless function that sums a list of numbers and calculates the average.

    Args:
        args (dict): A dictionary of input arguments (e.g., JSON payload).

    Returns:
        dict: A dictionary containing the result in JSON format.
    """
    import json

    # Check if 'numbers' is in the input arguments
    if 'numbers' not in args:
        return {
            "statusCode": 400,
            "body": json.dumps({"error": "Missing 'numbers' in input"})
        }

    numbers = args['numbers']

    # Validate that 'numbers' is a list
    if not isinstance(numbers, list):
        return {
            "statusCode": 400,
            "body": json.dumps({"error": "'numbers' must be a list"})
        }

    # Calculate the sum and average
    total = sum(numbers)
    average = total / len(numbers) if numbers else 0

    # Return the results
    return {
        "statusCode": 200,
        "body": json.dumps({
            "total": total,
            "average": average,
            "count": len(numbers)
        })
    }

Explanation:

  • Input Validation: Checks if numbers is provided and is a list.
  • Processing: Calculates the sum and average of the numbers.
  • Response: Returns a JSON-formatted string with the results.

Usage:

  • Invoke via HTTP POST Request:

    POST https://your-function-url
    Content-Type: application/json
    
    {
        "numbers": [10, 20, 30, 40, 50]
    }
    
  • Response:

    {
        "total": 150,
        "average": 30.0,
        "count": 5
    }
    

Deploying on DigitalOcean's App Platform

Directory Structure

Organize your project files as follows:

- my-serverless-functions/
  - hello_world.py
  - data_summation.py
  - requirements.txt

requirements.txt

If your functions use external libraries, list them in a requirements.txt file. For the above examples, only the standard library is used, so this file can be empty or omitted.

# requirements.txt

Steps to Deploy

  1. Create a GitHub Repository:

    • Initialize a new repository and add your function files.
    • Commit and push the changes to GitHub.
  2. Deploy to DigitalOcean:

    • Log in to your DigitalOcean account.
    • Navigate to the App Platform and click on "Launch Your App."
    • Connect your GitHub repository.
    • Configure the build settings:
      • Source Directory: Specify where your function files are located.
      • Build Command: Leave blank if not needed.
      • Run Command: For serverless functions, this is usually auto-detected.
    • Review and deploy your application.
  3. Test Your Functions:

    • Use curl, Postman, or a web browser to send requests to your function URLs.
    • Verify that the responses are as expected.

Additional Example: Image Thumbnail Generator

For a more advanced example, here's a function that generates a thumbnail from an image URL.

def main(args):
    """
    A serverless function that creates a thumbnail of an image from a given URL.

    Args:
        args (dict): A dictionary containing the 'image_url' and optional 'size'.

    Returns:
        dict: A dictionary with the thumbnail image in base64 encoding.
    """
    import requests
    from PIL import Image
    from io import BytesIO
    import base64

    # Get the image URL from the input arguments
    image_url = args.get("image_url")
    if not image_url:
        return {
            "statusCode": 400,
            "body": "Missing 'image_url' parameter."
        }

    # Get the desired thumbnail size
    size = args.get("size", 128)
    try:
        size = int(size)
    except ValueError:
        size = 128

    # Fetch the image from the URL
    response = requests.get(image_url)
    if response.status_code != 200:
        return {
            "statusCode": 400,
            "body": "Failed to fetch image from the provided URL."
        }

    # Open the image and create a thumbnail
    try:
        image = Image.open(BytesIO(response.content))
        image.thumbnail((size, size))
        buffered = BytesIO()
        image.save(buffered, format="PNG")
        img_str = base64.b64encode(buffered.getvalue()).decode('utf-8')
    except Exception as e:
        return {
            "statusCode": 500,
            "body": f"Image processing failed: {str(e)}"
        }

    # Return the thumbnail image in base64 encoding
    return {
        "statusCode": 200,
        "body": img_str,
        "headers": {
            "Content-Type": "image/png"
        }
    }

Explanation:

  • Dependencies: Uses requests for HTTP requests and Pillow for image processing.
  • Input Parameters: Accepts image_url and optional size.
  • Processing: Downloads the image, creates a thumbnail, and encodes it in base64.
  • Response: Returns the base64-encoded thumbnail image.

Usage:

  • Invoke via HTTP GET Request:

    GET https://your-function-url?image_url=https://example.com/image.jpg&size=100
    
  • Response:

    • The body contains the base64-encoded thumbnail image.

Note:

  • You'll need to include requests and Pillow in your requirements.txt:

    requests
    Pillow
    

Tips for Serverless Functions

  • Statelessness: Ensure your functions do not rely on local state between invocations.
  • Execution Time: Keep the execution time short to avoid hitting time limits.
  • Resource Limits: Be mindful of memory usage and other resource constraints.
  • Error Handling: Implement robust error handling to return meaningful HTTP status codes and messages.
  • Logging: Use logging to help debug and monitor your functions.

Testing Your Functions Locally

You can test your functions locally before deploying them by creating a simple test harness.

if __name__ == "__main__":
    # Example input arguments
    args = {
        "numbers": [1, 2, 3, 4, 5]
    }

    # Call the main function and print the result
    result = main(args)
    print(result)

Conclusion

These Python programs serve as foundational examples for serverless functions. They demonstrate how to handle input arguments, perform data processing, and return responses in the expected format. You can expand upon these examples to build more complex serverless applications tailored to your specific use cases.


Feel free to customize these functions or ask for further examples or clarifications. Happy coding!