This article is an extension of this one, explaining the OCI Functions context and data.
Let’s say that you have an OCI function that is used to get, insert, and delete customers from a database.
You want to expose the function through an API Gateway to implement authentication and/or authorization for example, or maybe you want to limit the number of requests to the back-end, etc.
You could create three different functions for each action and you would expose each one under a separate endpoint on API Gateway like:
- /myproject/v1/get-all-customers
- /myproject/v1/create-customer
- /myproject/v1/delete-customer
but, this is bad practice.
You should create all three actions under the same endpoint:
- /myproject/v1/customers
- use GET to get all customers
- use POST to insert new customers
- use DELETE to delete customers
Let’s see how we can do that with OCI Functions and OCI API Gateway.
Function Configuration
Create the function
When writing the function, you would want to know whether the invocation was a GET, POST, or DELETE. We can get that information from the function context object.
Let’s start by generating a new hello-world sample in python:
fn init --runtime python oci-fn-http-method
Note: If you need help generating new functions, you can check this article about setting up the environment for OCI Functions.
Now let’s modify the func.py so it does different things depending on the HTTP verb:
import io import json import logging from fdk import response def handler(ctx, data: io.BytesIO=None): resp = {} if ctx.Method() == "GET": # do smth when the function is invoked using the GET verb resp = get_method() if ctx.Method() == "POST": # do smth when the function is invoked using the PSOT verb resp = post_method() if ctx.Method() == "DELETE": # do smth when the function is invoked using the DELETE verb resp = delete_method() return response.Response( ctx, response_data=json.dumps(resp), headers={"Content-Type": "application/json"} ) def get_method(): return {"method": "GET", "message" : "The function was called using a GET verb"} def post_method(): return {"method": "POST", "message" : "The function was called using a POST verb"} def delete_method(): return {"method": "DELETE", "message" : "The function was called using a DELETE verb"}
Note: If you want to know more about the context object, check this article out.
When calling the function, the ctx object passed to the handler contains a lot of information about the function, the environment, the caller, and the invocation. We can take out the HTTP verb from ctx.Method() and do different actions depending on the HTTP method.
Deploy the function
Before deploying the function to OCI, we must first create an application that will hold the function.
We can do that by going in the main menu, under Developer Services – Functions click on Create Application:
From inside the function folder, deploy to the application created from the OCI Console – mine was create-bucket-app
fn -v deploy --app create-bucket-app
Note: If you need help deploying the function, check this OCI Functions Quickstart.
API Gateway Configuration
Create the endpoint
Once the function is deployed to OCI, we can expose it through an API Gateway.
Create a new API Gateway, from the main menu – Developer Services – API Gateway.
In the API Gateway, create a new deployment, and first, give your deployment a name, a path prefix and select the compartment where you want to deploy it: Then, create a new route:
- Give a path (this is the path to the resource, you can have multiple routes for a single deployment, like /fn/resource1, /fn/resource2, etc.)
- The HTTP method(s)
- The back-end type: at the moment it can be HTTP, Oracle Functions and Stock Response – I’ll select Oracle Functions
- Select the application where you deployed your function – mine was create-bucket-app
- Select the function you want to call – mine was oci-fn-http-method
Click Next and Create.
Wait a couple of seconds until the deployment changes state to Active and then, copy the endpoint:
Test the endpoint
Let’s give it a try and call the endpoint using GET, POST and DELETE as HTTP methods to see that it works. I’m going to use Postman for this, but you can use any other tool you want to make the calls.
After copying the deployment endpoint, don’t forget to add the resource path – in my case, it was: …/fn (endpoint path) /hello (resource path)
- GET
- POST – a little side note, you need to send an empty raw body for this to work via Postman
- DELETE
Conclusions
OCI Functions offers an easy solution for this kind of use cases – get the HTTP method from the Function’s context object. Like this, we can deploy a function on a single resource path in API Gateway for multiple HTTP methods.
This is a good way to avoid creating multiple resource paths in API Gateway for the same kind of resource. Now, it is safe to say that the function should not do too many things, it is supposed to be a single-purpose piece of code, so try to keep it as simple as possible.