Dependent Collections
In the following example, the sf_perform_request
function will
be used to develop a custom step. It will take a list of URIs
as its input, make multiple GET requests, and output its data as a
Python dictionary. From there we will further extract out the device
category GUIDs and category names.
To do this, I am going to be using the sf_perform_request
function
available in the REST: Toolkit. This function enables making one or more
HTTP requests within a custom step. We will use the
sf_perform_request
inside our custom step called multi_http
.
See below for sf_perform_request
usage.
- silo.low_code_steps.rest.sf_perform_request(request, debug, step_args=None)
Perform an HTTP request from within the Snippet Framework
This entrypoint enables calling the HTTP requestor from within the Snippet Framework by only requiring the ResultContainer to be present. It will use all logic from the HTTPRequestor without being called as a step. This is helpful if you have a custom step that needs to utilize the HTTPRequestor as a stand-alone call.
If step_args are specified, it will use these values instead of the current current_config within the ResultContainer.
If not specified, this will attempt to auto-convert based on the returned headers from the request. If you do not want to auto-convert the result, you must specify
convert=False
within the step_args that are being utilized during execution.- Parameters:
request (silo.low_code.ResultContainer) – Result container to collect
debug (callable) – AppLogAdapter’s debug function
step_args (dict) – Arguments to use for the HTTP request. If this is value is None, the ResultContainers step_args will be used.
- Return type:
http.http_response
I am going to start with the API’s initial payload. It is accessible via a
GET at api/device_category
. The response has a key called result_set
that holds a list of URI
elements. We will need to select it and then
make our HTTP GET requests.
api/device_category
’s payload:
{
"searchspec": {},
"total_matched": 119,
"total_returned": 100,
"result_set": [
{
"URI": "/api/device_category/88",
"description": "Cloud"
},
{
"URI": "/api/device_category/10",
"description": "Cloud.Account"
},
{
"URI": "/api/device_category/116",
"description": "Cloud.Analytics"
}
]
}
Using JSONPath, I will return a list of the URIs.
This will be the input into the multi_http
step. Below is an example of
making a GET request on one of these URIs.
api/device_category/88
’s payload:
{
"guid": "AD49E0B5AB7073B6927C4607C5F83833",
"ppguid": "7A7322AA30F189B42943C082EFD71217",
"cat_name": "Cloud",
"cat_icon": "/em7/libs/map_icons/cloud.swf",
"edit_date": "1667510932",
"edit_user": "/api/account/1",
"dashboard": "/api/device_dashboard/1",
}
Our end goal output is a list of tuples containing the guid
and the
cat_name
from each payload. The custom step multi_http``will call
``sf_perform_request
and combine all the JSON output into a list. From there
we will use jmespath
to access the desired keys.
Our Snippet Argument will look like this:
low_code:
id: guids_by_category_names
version: 2
steps:
- http:
uri: "/api/device_category"
- json:
- jmespath:
value: "result_set[*].URI"
- multi_http:
- jmespath:
index: true
value: "data[*].{_index: guid, _value: cat_name}"
The multi_http
step will need to replace the URI
in the step_args
for our subsequent GET request. The
step_args
in http
and sf_perform_request
expects that the URI is contained in a dictionary whose key
is uri
. Each URI also needs to be reformatted to avoid duplicating
“/api” in the path. This step will loop through replacing each URI
parameter in the step_args
. After each call to
sf_perform_request
we will append the parsed JSON
into a list. See below for more information on
http_response
.
- silo.low_code_steps.rest.http_response(response, converted)
HTTP response and converted output
- Parameters:
response (Response) –
requests.Response
converted (Union[dict,None]) – Auto-converted output i.e. json, xml, or None
This step will be added to our snippet under the section labeled
User Editable
. See below for its implementation.
from silo.low_code_steps.rest import sf_perform_request
@register_requestor
def multi_http(result, result_container, debug):
"""Executes multiple HTTP/HTTPs requests
:param list result: URIs
:param ResultContainer result_container: input into sf_perform_request
:param callable debug: Debug function for a context-aware logger
:return: responses
:rtype: dict
"""
data = []
for request in result:
# Remove extra "api" from request
request = "/" + request.split('/', 2)[-1]
http_resp = sf_perform_request(result_container, debug, step_args={"uri" : request})
# Rely on auto-conversion feature for HTTP response JSON -> dict
data.append(http_resp.converted)
return {"data": data}