IMPORTANT NOTE: ‘Raw functions’ is an advanced option for users with more experience using the UbiFunctions module.
1. Introduction
By default, UbiFunctions doesn't support custom paths, setting the response code or receive/send custom headers. But, what if your application needs such level of customization?
Raw UbiFunctions offer an advanced level of customization for experienced users. This guide will walk you through how to use these functions to customize endpoint paths, headers and response codes.
2. What are Raw Functions?
Raw functions allow you to:
Use a custom endpoint path in addition to the UbiFunction’s native. This allows executing different routines based on the endpoint path.
Receive and respond custom headers. For instance, Authorization headers.
Set custom response codes 20X, 40X, 50X, beyond the standard 200 in UbiFunctions. This allows the HTTP client to know the exact result of the execution.
Receive and respond custom Content-Type headers for the request body and response: application/json, plain/text, etc.
3. Enabling Raw Functions
To enable ‘raw functions’, just toggle the option in the left-side panel of the UbiFunction.
4. Understanding the Structure of arguments in Raw Functions
Once toggled on, the “args
“ argument received in the UbiFunction’s main function will follow the below structure:
{
"path" : "/prv/<YOUR_USERNAME>/<FUNCTION_NAME>/<YOUR_PATH>",
"headers":{
"Content-Type":"plain/text"
},
"body":"A2BF0D"
}
Where:
Key | Value/Type | Example |
Path |
String representing the raw UbiFunction's path. Defaults to: /prv/<YOUR_USERNAME>/<FUNCTION_NAME> | /prv/john-doe/get-measurements/temperature
|
Headers |
Dictionary with all the headers in the request that triggered the function. | {"Content-Type":"plain/text",
|
Body | Contains the body with which the request was issued, parsed as a string. | "A2BF0D" |
5. Raw UbiFunction's path
At the time of making the request to the UbiFunction, its basic URL structure should remain intact, otherwise, the request will point to a different UbiFunction.
For example, say you have the following UbiFunction URL: https://parse.ubidots.com/prv/iot-expo/raw-function/API/Login
Here, 'https://parse.ubidots.com/prv/iot-expo/raw-function' is the typical UbiFunction URL.
The part '
/API/Login
' is the custom path that you'll be able to access and parse at will from the code in the “path
” key of “args
”.
With this, you could, for example, execute multiple different logics based on the received path.
Consider that you want to offer three different logic on this endpoint, a login, a logout and a main logic, based on what path is used to make the request. You could make something like:
def main(args):
if args["path"] == "prv/iot-expo/raw-function":
return main_page_logic()
elif args["path"] == "prv/iot-expo/raw-function/API/login":
return login_function(args["body"])
elif args["path"] == "prv/iot-expo/raw-function/API/logout":
return log_out_function()
return {
"status_code": int,
"headers": object,
"body": string,
}
Then, in order to execute the main page logic, all it takes is to make the HTTP request to:
https://parse.ubidots.com/prv/iot-expo/raw-function/
For the login logic:
https://parse.ubidots.com/prv/iot-expo/raw-function/login
And, lastly, for the logout logic:
https://parse.ubidots.com/prv/iot-expo/raw-function/logout
6. Incoming arguments in the Body key
The contents of the body in the HTTP request are parsed to a string. For example:
Consider the following request to the UbiFunction mentioned above:
curl -X POST "https://parse.ubidots.com/prv/iot-expo/raw-function/" \
-H "Content-Type: plain/text" \
-d 24
Note that the number 24 was sent in the body (-d option), however what comes into the arguments to the UbiFunction is actually said number casted to a string, just as:
{"body" : "24"}
Suppose now that it is required to send a hexadecimal string such as AFD0E1. You'd have to make the request as:
curl -X POST "https://parse.ubidots.com/prv/iot-expo/raw-function/" \
-H "Content-Type: plain/text" \
-d "AFD0E1"
Then, the body key will look like on Ubidots as:
{"body" : "AFD0E1"}
In summary, you can send any content on the body of the request, as long as it parsed as a string, and the UbiFunction will receive it as so.
7. Raw UbiFunctions' Response
In the case of a non-raw UbiFunction, when its execution finishes, it will normally reply with its predefined response codes. However, with Raw functions, you can customize the response code, body, and headers at will, that way, the HTTP client making the request will know the precise result of the execution.
The following is the JSON structure to customize the response:
{
"status_code": 200,
"headers": {"Content-Type": "application/json"},
"body": string,
}
Key | Value (possible values)/Type | Example |
status_code | Integer number: 200, 20x, 40x, 50x | "status_code" : 200 |
headers | Dictionary containing response headers. | {"Content-Type": "text/plain"} |
body |
String value. | {"body" : "[INFO] Successful request"} |
For example, if the request is valid and the execution successful, the response JSON would be like this:
{
"status_code": 200,
"headers": {"Content-Type": "plain/text"},
"body": "[INFO] Successful request",
}
On the other hand, if based out of your code logic the request is not valid, it should reply a 400 response code, and the JSON response should look like as the follows:
{
"status_code": 400,
"headers": {"Content-Type": "plain/text"},
"body": "[ERROR] Bad Request, please check your request",
}