API Overview
ESB3024 Router provides two different types of API:s:
- A content request API that is used by video clients to ask for content, normally using port 80 for HTTP and port 443 for HTTPS.
- A few REST API:s used by administrators to configure and monitor the router installation, using port 5001 over HTTPS by default.
The content API won’t be described further in this document, since it’s a simple HTTP interface serving content as regular files or redirect responses.
Raw configuration – /v2/configuration
Used to check and update the raw configuration of ESB3024 Router. Note that this API is considered an implementation detail and is not documented further.
| REQUEST Method | Content-Type | RESPONSE Result | Status Code | Content-Type |
|---|---|---|---|---|
GET | <N/A> | Success | 200 OK | application/json |
PUT | application/json | Success | 204 No Content | <N/A> |
PUT | application/json | Failure | 400 Bad Request | application/json1 |
Validate Configuration – /v2/validate_configuration
Used to determine if a JSON payload is correctly formatted without actually applying its configuration. A successful return status does not guarantee that the applied configuration will work, it only validates the JSON structure.
| REQUEST Method | Content-Type | RESPONSE Result | Status Code | Content-Type |
|---|---|---|---|---|
PUT | application/json | Success | 204 No Content | <N/A> |
PUT | application/json | Failure | 400 Bad Request | application/json1 |
Example request
When an expected field is missing from the payload, the validation will show which one and return an appropriate error message in its payload:
$ curl -i -X PUT \
-d '{"routing": {"log_level": 3}}' \
-H "Content-Type: application/json" \
https://router.example:5001/v2/validate_configuration
HTTP/1.1 400 Bad Request
Access-Control-Allow-Origin: *
Content-Length: 132
Content-Type: application/json
X-Service-Identity: router.example-5fc78d
"Configuration validation: Configuration parsing failed. \
Exception: [json.exception.out_of_range.403] (/routing) key 'id' not found"
Selection Input
There are two versions of the selection input API, /v1/selection_input and
/v3/selection_input. The former is the legacy version and the latter is the
new version. It is recommended that all new integrations use the
/v3/selection_input API.
/v3/selection_input
The /v3/selection_input API supports the GET, POST, PUT, and DELETE
methods.
PUTreplaces the data at the specified path with the provided data. If the path does not exist, it will be created.POSTis only used for appending data to arrays. The last element in the path must be an array. If the path does not exist, it will be created, with the last segment as an array.GETrequests fetch the current selection input data at the given path.DELETErequests remove the data at the given path.
Example PUT request
$ curl -i -X PUT \
-d '{"bitrate": 13000, "capacity": 50000}' \
-H "Content-Type: application/json" \
https://router.example.com:5001/v3/selection_input/hosts/host1
HTTP/1.1 201 Created
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin: *
Content-Length: 0
X-Service-Identity: router.example.com-5fc78d
Example POST request
$ curl -i -X POST \
-d '"server1"' \
-H "Content-Type: application/json" \
https://router.example.com:5001/v3/selection_input/modules/allowed_servers
HTTP/1.1 201 Created
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin: *
Content-Length: 0
X-Service-Identity: router.example.com-5fc78d
Example GET request
$ curl -i https://router.example.com:5001/v3/selection_input
HTTP/1.1 200 OK
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin: *
Content-Length: 156
Content-Type: application/json
X-Service-Identity: router.example.com-5fc78d
{
"hosts": {
"host1": {
"bitrate": 13000,
"capacity": 50000
}
},
"modules": {
"allowed_servers": [
"server1"
]
}
}
Example DELETE request
$ curl -i -X DELETE \
https://router.example.com:5001/v3/selection_input/modules/allowed_servers
HTTP/1.1 204 No Content
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin: *
Content-Length: 0
X-Service-Identity: router.example.com-5fc78d
/v1/selection_input
The /v1/selection_input API supports the GET, PUT, and DELETE methods.
When performing GET or DELETE requests, specific selection input values can
be accessed or deleted by including a path to the request. Note that not
specifying a path will select all selection input values. PUT requests do not
support supplying paths, the path to the element to be modified is deduced by
the keys in the provided JSON object.
| REQUEST Method | Content-Type | RESPONSE Result | Status Code | Content-Type |
|---|---|---|---|---|
PUT | application/json | Success | 204 No Content | <N/A> |
PUT | application/json | Failure | 400 Bad Request | application/json |
GET | <N/A> | Success | 200 OK | application/json |
DELETE | <N/A> | Success | 204 No Content | <N/A> |
DELETE | <N/A> | Failure | 404 Not Found | <N/A> |
Example successful request (PUT)
$ curl -i -X PUT \
-d '{"host1_bitrate": 13000, "host1_capacity": 50000}' \
-H "Content-Type: application/json" \
https://router.example.com:5001/v1/selection_input
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: *
Content-Length: 0
X-Service-Identity: router.example.com-5fc78d
Example unsuccessful request (PUT)
$ curl -i -X PUT \
-d '{"cdn-status": {"session-count": 12345, "load-percent" 98}}' \
-H "Content-Type: application/json" \
https://router.example.com:5001/v1/selection_input
HTTP/1.1 400 Bad Request
Access-Control-Allow-Origin: *
Content-Length: 169
Content-Type: application/json
X-Service-Identity: router.example.com-5fc78d
{
"error": "[json.exception.parse_error.101] parse error at line 1, column 57: \
syntax error while parsing object separator - \
unexpected number literal; expected ':'"
}
Example successful request (GET)
curl -i https://router.example.com:5001/v1/selection_input
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Length: 129
Content-Type: application/json
X-Service-Identity: router.example.com-5fc78d
{
"host1_bitrate": 13000,
"host1_capacity": 50000
}
Example successful specific value request (GET)
curl -i https://router.example.com:5001/v1/selection_input/path/to/value
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Length: 129
Content-Type: application/json
X-Service-Identity: router.example.com-5fc78d
1
Example successful request (DELETE)
curl -i -X DELETE https://router.example.com:5001/v1/selection_input
HTTP/1.1 204 OK
Access-Control-Allow-Origin: *
Content-Length: 129
X-Service-Identity: router.example.com-5fc78d
Example successful specific value request (DELETE)
curl -i -X DELETE https://router.example.com:5001/v1/selection_input/value/to/delete
HTTP/1.1 204 OK
Access-Control-Allow-Origin: *
Content-Length: 129
X-Service-Identity: router.example.com-5fc78d
Example unsuccessful request (DELETE)
curl -i -X DELETE https://router.example.com:5001/v1/selection_input/non/existent/value
HTTP/1.1 404 Not Found
Access-Control-Allow-Origin: *
Content-Length: 129
X-Service-Identity: router.example.com-5fc78d
Subnets – /v1/subnets
An API for managing named subnets that can be used for routing and block lists. See Subnets for more details.
PUT requests inject key value pairs with the form {<subnet>: <value>}, where
<subnet> is a valid CIDR string, into ACD, e.g.:
$ curl -i -X PUT \
-d '{"255.255.255.255/24": "area1", "1.2.3.4/24": "area2"}' \
-H "Content-Type: application/json" \
https://router.example:5001/v1/subnets
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: *
Content-Length: 0
X-Service-Identity: router.example-5fc78d
GET requests are used to fetch injected subnets, e.g.:
# Fetch all injected subnets
$ curl -i https://router.example:5001/v1/subnets
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Length: 411
Content-Type: application/json
X-Service-Identity: router.example-5fc78d
{
"1.2.3.4/16": "area2",
"1.2.3.4/24": "area1",
"1.2.3.4/8": "area3",
"255.255.255.255/16": "area2",
"255.255.255.255/24": "area1",
"255.255.255.255/8": "area3",
"2a02:2e02:9bc0::/16": "area8",
"2a02:2e02:9bc0::/32": "area7",
"2a02:2e02:9bc0::/48": "area6",
"2a02:2e02:9de0::/44": "combined_area",
"2a02:2e02:ada0::/44": "combined_area",
"5.5.0.4/8": "area5",
"90.90.1.3/16": "area4"
}
DELETE requests are used to delete injected subnets, e.g.:
# Delete all injected subnets
$ curl -i https://router.example:5001/v1/subnets -X DELETE
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: *
Content-Length: 0
X-Service-Identity: router.example-5fc78d
Both GET and DELETE requests can be specified with the paths /byKey/ and
/byValue/ to filter which subnets to GET or DELETE.
# Fetch subnet with the CIDR string 1.2.3.4/8 if it exists
$ curl -i https://router.example:5001/v1/subnets/byKey/1.2.3.4/8
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Length: 26
Content-Type: application/json
X-Service-Identity: router.example-5fc78d
{
"1.2.3.4/8": "area3"
}
# Fetch all subnets whose CIDR string begins with the IP 1.2.3.4
$ curl -i https://router.example:5001/v1/subnets/byKey/1.2.3.4
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Length: 76
Content-Type: application/json
X-Service-Identity: router.example-5fc78d
{
"1.2.3.4/16": "area2",
"1.2.3.4/24": "area1",
"1.2.3.4/8": "area3"
}
# Fetch all subnets whose value equals 'area1'
$ curl -i https://router.example:5001/v1/subnets/byValue/area1
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Length: 60
Content-Type: application/json
X-Service-Identity: router.example-5fc78d
{
"1.2.3.4/24": "area1",
"255.255.255.255/24": "area1"
}
# Delete subnet with the CIDR string 1.2.3.4/8 if it exists
$ curl -i https://router.example:5001/v1/subnets/byKey/1.2.3.4/8
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: *
Content-Length: 0
X-Service-Identity: router.example-5fc78d
# Delete all subnets whose CIDR string begins with the IP 1.2.3.4
$ curl -i https://router.example:5001/v1/subnets/byKey/1.2.3.4
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: *
Content-Length: 0
X-Service-Identity: router.example-5fc78d
# Delete all subnets whose value equals 'area1'
$ curl -i https://router.example:5001/v1/subnets/byValue/area1
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: *
Content-Length: 0
X-Service-Identity: router.example-5fc78d
| REQUEST Method | Content-Type | RESPONSE Result | Status Code | Content-Type |
|---|---|---|---|---|
PUT | application/json | Success | 204 No Content | <N/A> |
PUT | application/json | Failure | 400 Bad Request | application/json |
GET | <N/A> | Success | 200 OK | application/json |
GET | <N/A> | Failure | 400 Bad Request | application/json |
DELETE | <N/A> | Success | 204 No Content | application/json |
DELETE | <N/A> | Failure | 400 Bad Request | application/json |
Subrunner Resource Usage – /v1/usage
Used to monitor the load on subrunners, the processes performing those tasks that are possible to run in parallel.
| REQUEST Method | Content-Type | RESPONSE Result | Status Code | Content-Type |
|---|---|---|---|---|
GET | <N/A> | Success | 200 OK | application/json |
Example request
$ curl -i https://router.example:5001/v1/usage
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Length: 1234
Content-Type: application/json
X-Service-Identity: router.example-5fc78d
{
"total_usage": {
"content": {
"lru": 0,
"newest": "-",
"oldest": "-",
"total": 0
},
"sessions": 0,
"subrunner_usage": {
[...]
}
},
"usage_per_subrunner": [
{
"subrunner_usage": {
[...]
}
},
[...]
]
}
Metrics – /m1/v1/metrics
An interface intended to be scraped by Prometheus. It is possible to scrape it manually to see current values, but doing so will reset some counters and cause actual Prometheus data to become faulty.
| REQUEST Method | Content-Type | RESPONSE Result | Status Code | Content-Type |
|---|---|---|---|---|
GET | <N/A> | Success | 200 OK | text/plain |
Example request
$ curl -i https://router.example:5001/m1/v1/metrics
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Length: 1234
Content-Type: text/plain
X-Service-Identity: router.example-5fc78d
# TYPE num_configuration_changes counter
num_configuration_changes 12
# TYPE num_log_errors_total counter
num_log_errors_total 0
# TYPE num_log_warnings_total counter
num_log_warnings_total{category=""} 123
# TYPE num_log_warnings_total counter
num_log_warnings_total{category="cdn"} 0
# TYPE num_log_warnings_total counter
num_log_warnings_total{category="content"} 0
# TYPE num_log_warnings_total counter
num_log_warnings_total{category="generic"} 10
# TYPE num_log_warnings_total counter
num_log_warnings_total{category="repeated_session"} 0
# TYPE num_ssl_errors_total counter
[...]
Node Visit Counters – /v1/node_visits
Used to gather statistics about the number of visits to each node in the routing tree. The returned value is a JSON object containing node ID names and their corresponding counter values.
| REQUEST Method | Content-Type | RESPONSE Result | Status Code | Content-Type |
|---|---|---|---|---|
GET | <N/A> | Success | 200 OK | application/json |
See Routing Rule Evaluation Metrics for more details.
Example request
$ curl -i https://router.example:5001/v1/node_visits
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Length: 73
Content-Type: application/json
X-Service-Identity: router.example-5fc78d
{
"cache1.tv": "99900",
"offload": "100"
"routingtable": "100000"
}
Node Visit Graph – /v1/node_visits_graph
Creates a GraphML representation of the node visitation data that can be rendered into an image to make it easier to understand the data.
| REQUEST Method | Content-Type | RESPONSE Result | Status Code | Content-Type |
|---|---|---|---|---|
GET | <N/A> | Success | 200 OK | application/xml |
See Routing Rule Evaluation Metrics for more details.
Example request
> curl -i -k https://router.example:5001/v1/node_visits_graph
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Length: 731
Content-Type: application/xml
X-Service-Identity: router.example-5fc78d
<?xml version="1.0"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="visits" for="node" attr.name="visits" attr.type="string" />
<graph id="G" edgedefault="directed">
<node id="routingtable">
<data key="visits">100000</data>
</node>
<node id="cache1.tv">
<data key="visits">99900</data>
</node>
<node id="offload">
<data key="visits">100</data>
</node>
<edge id="e0" source="routingtable" target="cache1.tv" />
<edge id="e1" source="routingtable" target="offload" />
</graph>
</graphml>
Session list - /v1/sessions
Used to monitor the load on subrunners, the processes performing those tasks that are possible to run in parallel.
| REQUEST Method | Content-Type | RESPONSE Result | Status Code | Content-Type |
|---|---|---|---|---|
GET | <N/A> | Success | 200 OK | application/json |
Example request
$ curl -k -i https://router.example:5001/v1/sessions
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Length: 12345
Content-Type: application/json
X-Service-Identity: router.example-5fc78d
{
"sessions": [
{
"age_seconds": 103,
"cdn": "edgeware",
"cdn_is_redirecting": false,
"client_ip": "1.2.3.4",
"host": "cdn.example:80",
"id": "router.example-5fc78d-00000001",
"idle_seconds": 103,
"last_request_time": "2022-12-02T14:05:05Z",
"latest_request_path": "/__cl/s:storage1/__c/v/f/0/5/v_sintel3v_f05a05f07d352e891d79863131ef4df7/__op/hls-default/__f/index.m3u8",
"no_of_requests": 1,
"requested_bytes": 0,
"requests_redirected": 0,
"requests_served": 0,
"session_groups": [
"all"
],
"session_groups_generation": 2,
"session_path": "/__cl/s:storage1/__c/v/f/0/5/v_sintel3v_f05a05f07d352e891d79863131ef4df7/__op/hls-default/__f/index.m3u8",
"start_time": "2022-12-02T14:05:05Z",
"type": "instream",
"user_agent": "libmpv"
},
[...]
]
}
Session details - /v1/sessions/<id: str>
Used to get details about a specific session from the above session list. The
id part of the URL corresponds to the id field in one of the
returned session entries in the above response.
| REQUEST Method | Content-Type | RESPONSE Result | Status Code | Content-Type |
|---|---|---|---|---|
GET | <N/A> | Success | 200 OK | application/json |
GET | <N/A> | Failure | 404 Not Found | application/json |
Example request
$ curl -k -i https://router.example:5001/v1/sessions/router.example-5fc78d-00000001
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Length: 763
Content-Type: application/json
X-Service-Identity: router.example-5fc78d
{
"age_seconds": 183,
"cdn": "edgeware",
"cdn_is_redirecting": false,
"client_ip": "1.2.3.4",
"host": "cdn.example:80",
"id": "router.example-5fc78d-00000001",
"idle_seconds": 183,
"last_request_time": "2022-12-02T14:05:05Z",
"latest_request_path": "/__cl/s:storage1/__c/v/f/0/5/v_sintel3v_f05a05f07d352e891d79863131ef4df7/__op/hls-default/__f/index.m3u8",
"no_of_requests": 1,
"requested_bytes": 0,
"requests_redirected": 0,
"requests_served": 0,
"session_groups": [
"all"
],
"session_groups_generation": 2,
"session_path": "/__cl/s:storage1/__c/v/f/0/5/v_sintel3v_f05a05f07d352e891d79863131ef4df7/__op/hls-default/__f/index.m3u8",
"start_time": "2022-12-02T14:05:05Z",
"type": "instream",
"user_agent": "libmpv"
}
Content List - /v1/content
| REQUEST Method | Content-Type | RESPONSE Result | Status Code | Content-Type |
|---|---|---|---|---|
GET | <N/A> | Success | 200 OK | application/json |
Example request
$ curl -k -i https://router.example:5001/v1/content
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Length: 572
Content-Type: application/json
X-Service-Identity: router.example-5fc78d
{
"content": [
[
"/__cl/s:storage1/__c/v/f/0/5/v_sintel3v_f05a05f07d352e891d79863131ef4df7/__op/hls-default/__f/index.m3u8",
{
"cached_count": 0,
"content_requested": false,
"content_set": false,
"expiration_time": "2022-12-02T14:05:05Z",
"key": "/__cl/s:storage1/__c/v/f/0/5/v_sintel3v_f05a05f07d352e891d79863131ef4df7/__op/hls-default/__f/index.m3u8",
"listeners": 0,
"manifest": "",
"request_count": 4,
"state": "HLS:MANIFEST-PENDING",
"wait_count": 0
}
]
]
}
Lua scripts – /v1/lua/<path str>.lua
Used to upload, retrieve and delete custom named Lua scripts on the router.
Global functions in uploaded scripts automatically become available to Lua code
in the configuration (which effectively may be viewed as hooks). Upload a
script by PUTing a application/x-lua to the endpoint, and retrieve it by
GETing the endpoint without payload.
| REQUEST Method | Content-Type | RESPONSE Result | Status Code | Content-Type |
|---|---|---|---|---|
PUT | application/x-lua | Success | 204 No Content | <N/A> |
PUT | application/x-lua | Failure | 400 Bad Request | application/json |
GET | <N/A> | Success | 200 OK | application/x-lua |
GET | <N/A> | Failure | 404 Not Found | application/json |
DELETE | <N/A> | Success | 204 No Content | <N/A> |
DELETE | <N/A> | Failure | 400 Bad Request | application/json |
DELETE | <N/A> | Failure | 404 Not Found | application/json |
Example request (PUT)
Save a Lua script under the name advanced_functions/f1.lua:
$ curl -i -X PUT \
-d 'function fun1() return 1 end' \
-H "Content-Type: application/x-lua" \
https://router.example:5001/v1/lua/advanced_functions/f1.lua
HTTP/1.1 204 Successfully saved Lua file
Access-Control-Allow-Origin: *
Content-Length: 0
X-Service-Identity: router.example-5fc78d
Example request (PUT, from file)
Upload an entire Lua file under the name advanced_functions/f1.lua:
First put your code in a file.
$ cat f1.lua
function fun1()
return 1
end
Then upload it using the --data-binary flag to preserve newlines
$ curl -i -X PUT \
--data-binary @f1.lua \
-H "Content-Type: application/x-lua" \
https://router.example:5001/v1/lua/advanced_functions/f1.lua
HTTP/1.1 204 Successfully saved Lua file
Access-Control-Allow-Origin: *
Content-Length: 0
X-Service-Identity: router.example-5fc78d
Example request (GET)
Request the Lua script named advanced_functions/f1.lua using a GET request:
$ curl -i https://router.example:5001/v1/lua/advanced_functions/f1.lua
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Length: 28
Content-Type: application/x-lua
X-Service-Identity: router.example-5fc78d
function fun1() return 1 end
Example request (DELETE)
Delete the Lua script named advanced_functions/f1.lua using a DELETE request:
$ curl -i -X DELETE \
https://router.example:5001/v1/lua/advanced_functions/f1.lua
HTTP/1.1 204 Successfully removed Lua file
Access-Control-Allow-Origin: *
Content-Length: 0
X-Service-Identity: router.example-5fc78d
List Lua scripts – /v1/lua
Used to list previously uploaded custom Lua scripts on the router, retrieving their respective paths and file checksums.
| REQUEST Method | Content-Type | RESPONSE Result | Status Code | Content-Type |
|---|---|---|---|---|
GET | <N/A> | Success | 200 OK | application/json |
Example request
$ curl -k -i https://router.example:5001/v1/lua
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Length: 108
Content-Type: application/json
X-Service-Identity: router.example-5fc78d
[
{
"file_checksum": "d41d8cd98f00b204e9800998ecf8427e",
"path": "advanced_functions/f1.lua"
}
]
Debug a Lua expression – /v1/lua/debug
Used to debug an arbitrary Lua expression on the router in a “sandbox” (with no visible side effects to the state of the router), and inspect the result.
The Lua expression in the body is evaluated inside an isolated copy of the
internal Lua environment including selection input. The stdout field of the
resulting JSON body is populated with a concatenation of every string provided
as argument to the Lua print() function during the course of evaluation.
Upon a successful evaluation, as indicated by the success flag,
return.value and return.lua_type_name capture the resulting Lua value.
Otherwise, if valuation was aborted (e.g. due to a Lua exception), error_msg
reflects any error description arising from the Lua environment.
| REQUEST Method | Content-Type | RESPONSE Result | Status Code | Content-Type |
|---|---|---|---|---|
POST | application/x-lua | Success | 200 OK | application/json |
Example successful request
$ curl -i -X POST \
-d 'fun1()' \
-H "Content-Type: application/x-lua" \
https://router.example:5001/v1/lua/debug
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Length: 123
Content-Type: application/json
X-Service-Identity: router.example-5fc78d
{
"error_msg": "",
"return": {
"lua_type_name": "number",
"value": 1.0
},
"stdout": "",
"success": true
}
Example unsuccessful request
(attempt to invoke unknown function)
$ curl -i -X POST \
-d 'fun5()' \
-H "Content-Type: application/x-lua" \
https://router.example:5001/v1/lua/debug
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Length: 123
Content-Type: application/json
X-Service-Identity: router.example-5fc78d
{
"error_msg": "[string \"function f0() ...\"]:2: attempt to call global 'fun5' (a nil value)",
"return": {
"lua_type_name": "",
"value": null
},
"stdout": "",
"success": false
}