Script API Reference
Hodor runs your scripts in a built-in JavaScript engine. Depending on the script type, Hodor calls one of the entry functions below at the right time — you only implement the logic you need. If you do not modify anything, delete the unused entry function to avoid unnecessary calls.
Available global objects and classes:
| Category | Names |
|---|---|
| Entry functions | onRequest, onResponse, onSessionCompleted, onSchedule, abort() |
Native $ modules | $codec, $hash, $hmac, $crypto, $jwt, $format, $fs, $env, $uuid, $log |
| Web standard APIs | fetch, HTTPClient, setTimeout / setInterval, btoa / atob / sleep / require / TextEncoder / crypto, console |
| HTTP classes | Request, Response, Body, Headers, URLSearchParams |
| Storage | SharedPreferences, sdk variables |
| Contexts | RewriteContext, CompletedContext, ScheduleContext |
Use console.log(...) anywhere in a script to inspect values — output is shown in the script's log view.
Entry Functions
Scripts are detected by scanning for async function declarations — the parameter count of each entry function is fixed (onRequest/onResponse take 3, onSessionCompleted takes 4, onSchedule takes 1). Arrow-function assignments (let onRequest = async (...) => {}) are not detected. Parameter names are free.
onRequest(context, url, request)
Designed for Rewrite Script and Quick Request pre-request scripts. This function is called before the HTTP request is sent to the server. Return the (possibly modified) request.
| Parameter | Type | Description |
|---|---|---|
context | RewriteContext | The context object. |
url | string | The URL of the HTTP request. |
request | Request | The HTTP request object. |
// modify request body
async function onRequest(context, url, request) {
// parse to Text
var text = request.body.parseText()
console.log(text)
request.body = "this is a replaced request text"
// parse to JSON
var json = request.body.parseJSON()
json["script_json"] = "JSONValue"
request.body = json
// parse to URLSearchParams
var urlencoded = request.body.parseURLSearchParams()
urlencoded.append("script", "parseURLSearchParams")
request.body = urlencoded
// Done
return request;
}
// redirect, modify path / queries / headers
async function onRequest(context, url, request) {
console.log(url);
// set a parameter, you can get it in onResponse
context.parameters["custom"] = "custom parameter on request"
// redirect
request.scheme = "http"
request.path = "/upload/json"
request.host = "192.168.3.30"
request.port = 6000
// change method
request.method = "POST"
// queries operation
request.queries.append("name", "value1") // add query
request.queries.set("name", "value2") // replace or add query
request.queries.get("name") // get query by name
request.queries.delete("name") // delete query by name
// headers operation
request.headers.delete("accept") // delete header by name
request.headers.append("hodor", "custom value") // add name-value pair
request.headers.forEach((value, name) => {
console.log(name + ":" + value)
});
// Done
return request;
}
onResponse(context, url, response)
Designed for Rewrite Script and Quick Request post-response scripts. This function is called before the HTTP response is sent to the client. Return the (possibly modified) response.
| Parameter | Type | Description |
|---|---|---|
context | RewriteContext | The context object. |
url | string | The URL of the HTTP response. |
response | Response | The HTTP response object. |
// response body
async function onResponse(context, url, response) {
// parse to Text
var text = response.body.parseText()
console.log(text)
response.body = "this is a replaced response text"
// parse to JSON
var json = response.body.parseJSON()
json["script_json"] = "JSONValue"
response.body = json
// parse to URLSearchParams
var urlencoded = response.body.parseURLSearchParams()
urlencoded.append("script", "parseURLSearchParams")
response.body = urlencoded
// Done
return response;
}
// change status code and headers
async function onResponse(context, url, response) {
// get parameters set in onRequest
console.log(context.parameters["custom"]) // Output "custom parameter on request"
response.statusCode = 200 // change status code
response.statusPhrase = "OK" // change status phrase
response.headers.delete("accept")
response.headers.append("hodor", "custom value")
response.headers.forEach((value, name) => {
console.log(name + ":" + value)
});
// Done
return response
}
onSessionCompleted(context, url, request, response)
Designed for HTTP Completed Script. Called asynchronously after the HTTP response is returned, without affecting data transmission between the app and the server. Useful for data collection and forwarding.
| Parameter | Type | Description |
|---|---|---|
context | CompletedContext | The context object. |
url | string | The URL of the HTTP request. |
request | Request | The HTTP request object. |
response | Response | The HTTP response object. |
// sample: pass session data to your own server
async function onSessionCompleted(context, url, request, response) {
try {
var reqText = request.body.parseText();
var rspText = response.body.parseText()
var params = {
"body": { // HTTPClient post body data
"url": url, // request url
"reqHeader": request.headers.encode(), // request headers
"reqText": reqText, // request body
"rspHeader": response.headers.encode(), // response headers
"rspText": rspText, // response body
},
"headers": { // HTTPClient headers
"from": "onSessionCompleted"
},
}
const rsp = await HTTPClient.post("http://192.168.3.30:8000/upload", params)
let text = rsp.body.parseText()
console.log(text)
} catch(error) {
console.log(error)
}
}
onSchedule(context)
Designed for Schedule Script. Called at the scheduled trigger time (5 or 6-part cron expressions are supported). Use abort() to stop the schedule loop.
| Parameter | Type | Description |
|---|---|---|
context | ScheduleContext | The context object. |
async function onSchedule(context) {
// set custom parameters for next runloop
context.parameters["custom"] = "custom parameters for next runloop";
// repeated count
console.log(`repeatedCount ${context.repeatedCount}`);
// if repeatedCount is 2, abort schedule
if (context.repeatedCount == 2) {
abort()
}
// you can also use HTTPClient to send requests
const rsp = await HTTPClient.get("https://www.apple.com")
let text = rsp.body.parseText()
console.log(text)
}
abort()
Inside channel scripts (onRequest / onResponse / onSchedule), call abort() to stop the script and abort the current execution immediately — it throws an AbortError that Hodor reports back to you.
// ✅ correct — abort() is injected into the script scope
async function onRequest(context, url, request) {
if (url.includes("/tracking")) abort();
return request;
}
Do not declare onRequest(context, url, request, aborter) with a 4th parameter. The parameter count of entry functions is fixed — a 4th parameter makes the entry undetectable.
Native Modules
All $-prefixed modules are injected when the runtime activates. They are implemented natively, return synchronously (unless noted) and treat string inputs as UTF-8.
$codec — Encode & Decode
Base64 / Hex / URL percent encoding for protocol conversion and data transfer.
| Method | Returns |
|---|---|
$codec.base64Encode(str) | Base64 string. |
$codec.base64Decode(str) | Decoded string; invalid input returns "" (does not throw). |
$codec.hexEncode(str) | Lowercase hex string. |
$codec.hexDecode(str) | Decoded string; invalid characters are skipped. |
$codec.urlEncode(str) | Percent-encoded string. |
$codec.urlDecode(str) | Decoded string; invalid sequences are returned as-is. |
$codec.base64Encode("Hello, World!"); // "SGVsbG8sIFdvcmxkIQ=="
$codec.base64Decode("SGVsbG8sIFdvcmxkIQ=="); // "Hello, World!"
$codec.hexEncode("ABC"); // "414243"
$codec.hexDecode("414243"); // "ABC"
$codec.urlEncode("hello world&foo=bar"); // "hello%20world%26foo%3Dbar"
$hash — Hashing
Digest computation for integrity checks, content addressing and anonymization. Returns lowercase hex.
| Method | Output length |
|---|---|
$hash.md5(str) | 32 hex chars |
$hash.sha1(str) | 40 hex chars |
$hash.sha256(str) | 64 hex chars |
$hash.sha384(str) | 96 hex chars |
$hash.sha512(str) | 128 hex chars |
$hash.md5("hello"); // "5d41402abc4b2a76b9719d911017c592"
$hash.sha256("hello"); // "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
// integrity check
const checksum = $hash.sha256(JSON.stringify({user: "admin"}));
$hmac — Message Authentication Code
Keyed hashing for API signing and tamper detection. Both (data, key) are UTF-8 encoded; returns lowercase hex.
| Method | Algorithm |
|---|---|
$hmac.md5(data, key) | HMAC-MD5 |
$hmac.sha1(data, key) | HMAC-SHA1 |
$hmac.sha256(data, key) | HMAC-SHA256 |
$hmac.sha384(data, key) | HMAC-SHA384 |
$hmac.sha512(data, key) | HMAC-SHA512 |
const signature = $hmac.sha256("important data", "my-secret-key");
const isValid = (signature === $hmac.sha256("important data", "my-secret-key")); // true