Build an HTTP API Endpoint

HTTP endpoints have become one of the most ubiquitous ways of delivering software to end users. Cdev provides a simple interface for creating HTTP APIs and connecting them to Serverless Functions. You can find more information about HTTP in the official documentation.

Set Up
It is assumed that you have already installed the Cdev SDK, which has a pre-filled src/hello_world/resources.py file. This example starts with an empty src/hello_world/resources.py file. You can empty the contents of your file or replace the neccessary lines of code as you go along.

Create an API

Open the src/hello_world/resources.py file and start by importing the following resources:

    
import json from cdev.resources.simple.api import Api from cdev.resources.simple.xlambda import simple_function_annotation from cdev import Project as cdev_project


Create a route

Next, add lines 8, 10 and 12 to define your project, API and create your route.

    
import json from cdev.resources.simple.api import Api from cdev.resources.simple.xlambda import simple_function_annotation from cdev import Project as cdev_project myProject = cdev_project.instance() myApi = Api("demoApi") hello_world_get_route = DemoApi.route("/hello_world", "GET")


Integrate GET route with a Serverless Function

Now, intergrate your route with a Serverless Function by adding lines 10 - 35.

    
import json from cdev.resources.simple.api import Api from cdev.resources.simple.xlambda import simple_function_annotation from cdev import Project as cdev_project myProject = cdev_project.instance() myApi = Api("demoApi") hello_world_get_route = myApi.route("/hello_world", "GET") @simple_function_annotation("demo_function", events=[hello_world_get_route.event()]) def hello_world(event, context): """ This is an example function connected to an example API route """ message = { "message": "Hello World from Lambda!" } return { "isBase64Encoded": False, "status_code": 200, "body": json.dumps(message), "headers": { "Content-Type": "application/json" } } myProject.display_output("Base API URL", myApi.output.endpoint) myProject.display_output("Routes", myApi.output.endpoints)


Get your endpoint

Save and deploy your endpoint with the following commands:

cdev plan
cdev deploy

Get the live url for your endpoint:

cdev output <component_name>.api.demoApi.endpoint

You can test the endpoint with the following commands from your terminal:

curl <your_endpoint>/hello_world

Integrate POST route with data to a Serverless function

Using the same src/hello_world/resources.py file from the GET route example, make the following changes.

Replace lines 12 - 31 with:

send_data_route = myApi.route("/send_data", "POST")


@simple_function_annotation("send_data_handler", events=[send_data_route.event()])
def hello_world(event, context):
    
    """
    This is an example function connected to an example POST API route that can receive data
    """

    print(event)


    data = json.loads(event.get("body"))

    print(data)
    message = {
        "message": "Handled Data"
    }

    return {
        "isBase64Encoded": False,
        "status_code": 200, 
        "body": json.dumps(message),
        "headers": {
            "Content-Type": "application/json"
        }
    }

The src/hello_world/resources.py now looks like:

    
import json from cdev.resources.simple.api import Api from cdev.resources.simple.xlambda import simple_function_annotation from cdev import Project as cdev_project myProject = cdev_project.instance() myApi = Api("demoApi") send_data_route = myApi.route("/send_data", "POST") @simple_function_annotation("send_data_handler", events=[send_data_route.event()]) def hello_world(event, context): """ This is an example function connected to an example POST API route that can receive data """ print(event) data = json.loads(event.get("body")) print(data) message = { "message": "Handled Data" } return { "isBase64Encoded": False, "status_code": 200, "body": json.dumps(message), "headers": { "Content-Type": "application/json" } } myProject.display_output("Base API URL", myApi.output.endpoint) myProject.display_output("Routes", myApi.output.endpoints)


Get your POST endpoint

Save and deploy your endpoint with the following commands:

cdev plan
cdev deploy

Get the live url for your endpoint:

cdev output <component_name>.api.demoApi.endpoint

You can test the endpoint with the follow commands from your terminal:

curl -X POST <your_endpoint>/send_data -H 'Content-Type: application/json' -d "{\"login\":\"my_login\"}"

Check the logs of your function

cdev run function.logs <component_name>.send_data_handler

Return Values from Function

From the AWS Documentation, API Gateway makes the following assumptions if your Lambda function returns valid JSON and does not return a statusCode:

  • isBase64Encoded is false.
  • statusCode is 200.
  • content-type is application/json.
  • body is the function's response.

Examples:

Function Response

return "Hello from Lambda!"

API Gateway Response

{
  "isBase64Encoded": false,
  "statusCode": 200,
  "body": "Hello from Lambda!",
  "headers": {
    "content-type": "application/json"
  }
}

Function Response

return { "message": "Hello from Lambda!" }

API Gateway Response

{
  "isBase64Encoded": false,
  "statusCode": 200,
  "body": "{ \"message\": \"Hello from Lambda!\" }",
  "headers": {
    "content-type": "application/json"
  }
}


If you want to customize your return value completely, it should have the form:

return {
    "cookies" : ["cookie1", "cookie2"],
    "isBase64Encoded": True|False,
    "statusCode": httpStatusCode,
    "headers": { "headername": "headervalue", ... },
    "body": "Hello from Lambda!"
}
Return Custom JSON

If you are going to return a custom value and want the body to be a JSON value, the value must be a JSON encoded string. You can use the std lib json.dumps method to generate the properly encoded string.

return {
    "cookies" : ["cookie1", "cookie2"],
    "isBase64Encoded": True|False,
    "statusCode": httpStatusCode,
    "headers": { "headername": "headervalue", ... },
    "body": json.dumps({
        "message" :"Hello from Lambda!"
    })
}