EchoScript Extension
When you need to implement complex logic, you can write EchoScript extensions in ANY programming language, such as JavaScript, Python, Java, Go, etc.
EchoScript uses function exec to run extensions in a very convenient way.
exec(name, args...) => string/map/errorYou can use function is_error to check whether the value is error or not.
The return value of exec depends on the output of the command.
| cmd output | cmd exit code | exec return value |
|---|---|---|
json {...} | 0 | map |
not json {...} | 0 | string |
| any | != 0 | error |
The name argument is the command in $PATH, or absolute file path to the command.
The args argument type can be string|file|map|array.
The map|array arguments are transformed to json file automatically.
| args argument type | actual command argument |
|---|---|
string | string |
map | json file path |
array | json file path |
file | file path |
Python
Example 1
Use python to generate uuid and base64. Create a Map Rule with following settings:
MapLocal, GET, Equals, Enabled ✅
URL:https://demo.echolabx.com/
on_response := func(env, res) { // cmd output is json, and exec returns a map r := exec("python3", "~/gen_uuid_base64.py", "Hello, EchoProxy")
return { body: { "uuid": r.uuid, "exec": r } }}Content of python file ~/gen_uuid_base64.py:
import base64import uuidimport jsonimport sys
a = "Hello World"if len(sys.argv) > 1: a = sys.argv[1]
b = base64.b64encode(str.encode(a))
x = { "input": a, "base64": bytes.decode(b), "uuid": str(uuid.uuid4()),}
# convert x into json, print to stdoutprint(json.dumps(x))Visit the URL https://demo.echolabx.com/ again, the new response body data:
{ "exec": { "base64": "SGVsbG8sIEVjaG9Qcm94eQ==", "input": "Hello, EchoProxy", "uuid": "3dcf7b92-bdb0-4363-812c-eb17bd53d94a" }, "uuid": "3dcf7b92-bdb0-4363-812c-eb17bd53d94a"}You can see exec log on Tab Log.
Example 2
When you want to pass more information to exec command, you can use map as argument.
Create a Map Rule with following settings:
MapLocal, GET, Equals, Enabled ✅
URL:https://demo.echolabx.com/
on_response := func(env, res) { // the last argument is a map, and exec returns a map r := exec("python3", "~/use_json.py", { "name": "EchoProxy", "version": "1.0.0" })
return { body: r }}exec automatically transform map argument to a file with to_file function,
the command can read the file and decode the content as json.
{ "name": "EchoProxy", "version": "1.0.0"}Content of python file ~/use_json.py. It loads the first argument as a json file.
import jsonimport sys
def main(): # load json file argv[1] a = load_json(1, {})
x = { "input": a, "name": a.get("name"), }
# convert x into json, print to stdout print(json.dumps(x))
# load json file argv[index], return dictdef load_json(index, default): try: file_name = sys.argv[index] f = open(file_name, "r") content = f.read() f.close() return json.loads(content) except: return default
# run main functionmain()Visit the URL again, the new response body data:
{ "input": { "name": "EchoProxy", "version": "1.0.0" }, "name": "EchoProxy"}You can see exec log on Tab Log.
JavaScript
You can write extensions in JavaScript with Node.js.
Create an example Map Rule with following settings:
MapLocal, GET, Equals, Enabled ✅
URL:https://demo.echolabx.com/
on_response := func(env, res) { // convert map to file arg_file := to_file({ "name": "EchoProxy", "version": "1.0.0" }) // exec returns a map r := exec("node", "~/use_json.js", arg_file) print("name: ", r.name)
return { body: r }}Content of JavaScript file ~/use_json.js. It loads the second argument as a json file.
const fs = require('node:fs');
function main() { let a = load_json(2, {}) let x = { "input": a, "name": a["name"] + " " + a["version"], }
console.log(JSON.stringify(x))}
// load json file argv[index], return objectfunction load_json(index, default_val) { try { let file_name = process.argv[index]; let data = fs.readFileSync(file_name); return JSON.parse(data) } catch (e) { return default_val }}
// run main functionmain()Visit the URL again, the new response body data:
{ "input": { "name": "EchoProxy", "version": "1.0.0" }, "name": "EchoProxy 1.0.0"}You can see exec log on Tab Log.