Skip to main content

脚本 API 参考

Hodor 在内置 JavaScript 引擎中运行你的脚本。根据脚本类型,Hodor 会在恰当时机调用下方某个入口函数——只需实现需要的逻辑。如果不需要修改任何内容,删除未使用的入口函数即可避免不必要的调用。

可用的全局对象与类:

分类名称
入口函数onRequest、onResponse、onSessionCompleted、onSchedule、onMock、abort()
$ 原生模块$codec、$hash、$hmac、$crypto、$jwt、$format、$fs、$env、$uuid、$log
Web 标准 APIfetch、HTTPClient、setTimeout / setInterval、btoa / atob / sleep / require / TextEncoder / crypto、console
HTTP 类Request、Response、Body、Headers、URLSearchParams
存储SharedPreferences、sdk 变量
上下文RewriteContext、CompletedContext、ScheduleContext
tip

在脚本任意位置使用 console.log(...) 检查值——输出显示在脚本的日志视图中。

入口函数​

引擎通过扫描 async function 声明识别脚本——每个入口函数的参数个数固定(onRequest/onResponse/onMock 为 3 个,onSessionCompleted 为 4 个,onSchedule 为 1 个)。箭头函数赋值(let onRequest = async (...) => {})不会被识别。参数名可以随意。

onRequest(context, url, request)​

用于重写脚本与快速请求前置脚本。在 HTTP 请求发送到服务器前调用。返回(可能修改过的)request。

参数类型说明
contextRewriteContext上下文对象。
urlstringHTTP 请求的 URL。
requestRequestHTTP 请求对象。
// 修改请求体
async function onRequest(context, url, request) {
// 解析为文本
var text = request.body.parseText()
console.log(text)
request.body = "this is a replaced request text"

// 解析为 JSON
var json = request.body.parseJSON()
json["script_json"] = "JSONValue"
request.body = json

// 解析为 URLSearchParams
var urlencoded = request.body.parseURLSearchParams()
urlencoded.append("script", "parseURLSearchParams")
request.body = urlencoded
// 完成
return request;
}
// 重定向、修改 path / query / header
async function onRequest(context, url, request) {
console.log(url);
// 设置一个参数,可在 onResponse 中获取
context.parameters["custom"] = "custom parameter on request"

// 重定向
request.scheme = "http"
request.path = "/upload/json"
request.host = "192.168.3.30"
request.port = 6000
// 修改方法
request.method = "POST"

// query 操作
request.queries.append("name", "value1") // 添加 query
request.queries.set("name", "value2") // 替换或添加 query
request.queries.get("name") // 按 name 获取 query
request.queries.delete("name") // 按 name 删除 query

// header 操作
request.headers.delete("accept") // 按 name 删除 header
request.headers.append("hodor", "custom value") // 添加键值对
request.headers.forEach((value, name) => {
console.log(name + ":" + value)
});
// 完成
return request;
}

onResponse(context, url, response)​

用于重写脚本与快速请求后置脚本。在 HTTP 响应发送到客户端前调用。返回(可能修改过的)response。

参数类型说明
contextRewriteContext上下文对象。
urlstringHTTP 响应的 URL。
responseResponseHTTP 响应对象。
// 响应体
async function onResponse(context, url, response) {
// 解析为文本
var text = response.body.parseText()
console.log(text)
response.body = "this is a replaced response text"

// 解析为 JSON
var json = response.body.parseJSON()
json["script_json"] = "JSONValue"
response.body = json

// 解析为 URLSearchParams
var urlencoded = response.body.parseURLSearchParams()
urlencoded.append("script", "parseURLSearchParams")
response.body = urlencoded
// 完成
return response;
}
// 修改状态码与 header
async function onResponse(context, url, response) {
// 获取 onRequest 中设置的参数
console.log(context.parameters["custom"]) // 输出 "custom parameter on request"

response.statusCode = 200 // 修改状态码
response.statusPhrase = "OK" // 修改状态短语

response.headers.delete("accept")
response.headers.append("hodor", "custom value")
response.headers.forEach((value, name) => {
console.log(name + ":" + value)
});
// 完成
return response
}

onSessionCompleted(context, url, request, response)​

用于 HTTP 完成脚本。在 HTTP 响应返回后异步调用,不影响 App 与服务器之间的数据传输。适合做数据采集与转发。

参数类型说明
contextCompletedContext上下文对象。
urlstringHTTP 请求的 URL。
requestRequestHTTP 请求对象。
responseResponseHTTP 响应对象。
// 示例:将会话数据转发到自己的服务器
async function onSessionCompleted(context, url, request, response) {
try {
var reqText = request.body.parseText();
var rspText = response.body.parseText()
var params = {
"body": { // HTTPClient 的 POST body 数据
"url": url, // 请求 URL
"reqHeader": request.headers.encode(), // 请求 header
"reqText": reqText, // 请求体
"rspHeader": response.headers.encode(), // 响应 header
"rspText": rspText, // 响应体
},
"headers": { // HTTPClient header
"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)​

用于定时脚本。在计划触发时刻调用(支持 5 或 6 段 cron 表达式)。使用 abort() 停止定时循环。

参数类型说明
contextScheduleContext上下文对象。
async function onSchedule(context) {
// 为下一次运行循环设置自定义参数
context.parameters["custom"] = "custom parameters for next runloop";
// 重复次数
console.log(`repeatedCount ${context.repeatedCount}`);
// 若 repeatedCount 为 2,停止定时
if (context.repeatedCount == 2) {
abort()
}
// 也可以使用 HTTPClient 发送请求
const rsp = await HTTPClient.get("https://www.apple.com")
let text = rsp.body.parseText()
console.log(text)
}

onMock(context, url, request)​

用于 Mock 脚本。代替真实请求被调用——返回什么,客户端就收到什么。

参数类型说明
contextRewriteContext上下文对象。
urlstringHTTP 请求的 URL。
requestRequestHTTP 请求对象。
// 返回一个 Mock 的 JSON 响应
async function onMock(context, url, request) {
const response = new Response({
statusCode: 200,
statusPhrase: 'OK',
headers: {'Content-Type': 'application/json'},
textBody: JSON.stringify({code: 0, message: 'mocked by script', data: {time: Date.now()}}),
});
return response;
}

abort()​

在通道脚本(onRequest / onResponse / onSchedule)内调用 abort() 可立即停止脚本并中断当前执行——它会抛出 AbortError,由 Hodor 上报给你。

// ✅ 正确——abort() 被注入到脚本作用域
async function onRequest(context, url, request) {
if (url.includes("/tracking")) abort();
return request;
}
warning

不要把入口函数写成 onRequest(context, url, request, aborter) 带 4 个参数。入口函数参数个数固定——第 4 个参数会导致入口无法被识别。

原生模块​

所有带 $ 前缀的模块在运行时激活时注入。它们由原生实现、同步返回(除非特别说明),字符串输入按 UTF-8 处理。

$codec — 编码与解码​

Base64 / Hex / URL 百分号编码,用于协议转换与数据传输。

方法返回
$codec.base64Encode(str)Base64 字符串。
$codec.base64Decode(str)解码结果;非法输入返回 ""(不抛异常)。
$codec.hexEncode(str)小写十六进制字符串。
$codec.hexDecode(str)解码结果;非法字符被跳过。
$codec.urlEncode(str)百分号编码字符串。
$codec.urlDecode(str)解码结果;非法序列原样返回。
$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 — 哈希​

摘要计算,用于完整性校验、内容寻址与匿名化。返回小写十六进制。

方法输出长度
$hash.md5(str)32 个十六进制字符
$hash.sha1(str)40 个十六进制字符
$hash.sha256(str)64 个十六进制字符
$hash.sha384(str)96 个十六进制字符
$hash.sha512(str)128 个十六进制字符
$hash.md5("hello"); // "5d41402abc4b2a76b9719d911017c592"
$hash.sha256("hello"); // "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"

// 完整性校验
const checksum = $hash.sha256(JSON.stringify({user: "admin"}));

$hmac — 消息认证码​

带密钥的哈希,用于 API 签名与防篡改。(data, key) 均按 UTF-8 编码;返回小写十六进制。

方法算法
$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

$crypto — 对称加密​

AES-GCM 认证加密(推荐)与 DES(兼容旧场景)。

方法返回
$crypto.encryptAES(plaintext, password, options?)Base64 密文;失败返回 "Error: <原因>" 字符串。
$crypto.decryptAES(ciphertext, password, options?)明文;非法密文返回 "Error: Invalid ciphertext"。
$crypto.encryptDES(plaintext, key)DES-ECB + PKCS7,key 截断到 8 字节 → Base64。
$crypto.decryptDES(ciphertext, key)明文;非 Base64 输入返回 ""。

options:{ keySize: 128 \| 192 \| 256 }(默认 256)。AES 密文格式为 base64(nonce[12] + ciphertext + tag[16])——请与 decryptAES 配对使用;与其他语言互操作时需自行拆解该格式。

const encrypted = $crypto.encryptAES("sensitive data", "my-password");
$crypto.decryptAES(encrypted, "my-password"); // "sensitive data"

// 128 位密钥
const e128 = $crypto.encryptAES("data", "pass", { keySize: 128 });

// 错误以字符串返回、不抛异常——检查前缀
const out = $crypto.decryptAES("not-base64!!", "p");
if (out.startsWith("Error:")) { /* 处理错误 */ }

$jwt — JSON Web Token​

JWT 的创建、解析与签名校验(HMAC 家族),用于认证流程脚本。

方法返回
$jwt.sign(payload, secret, algorithm?)JWT 字符串;默认 HS256。
$jwt.decode(token){header, payload} 对象(不校验签名);非法 token 返回 null。
$jwt.verify(token, secret, algorithm?)boolean——签名校验结果。

algorithm:"HS256" | "HS384" | "HS512"。

// 签名
const payload = JSON.stringify({ sub: "user123", exp: Math.floor(Date.now() / 1000) + 3600 });
const token = $jwt.sign(payload, "my-secret", "HS256");

// 解码——直接返回对象,无需 JSON.parse
const decoded = $jwt.decode(token);
decoded.header.alg; // "HS256"
decoded.payload.sub; // "user123"

// 校验
$jwt.verify(token, "my-secret", "HS256"); // true
$jwt.verify(token, "wrong-secret", "HS256"); // false

// 过期检查
const exp = $jwt.decode(token).payload.exp;
const expired = exp * 1000 < Date.now();

$format — 数据格式化​

JSON/XML 的美化与压缩,用于日志输出与调试。JSON 输出中键按字母序排列。

方法返回
$format.json(str, indent?)美化后的 JSON;indent 限制在 1–8(默认 2);非法输入返回 "Error: Invalid JSON"。
$format.minify(str)压缩后的 JSON(键排序、去除空白);非法输入返回 "Error: Invalid JSON"。
$format.xml(str)简单缩进的 XML。
$format.json('{"b":1,"a":2}');
// {
// "a": 2,
// "b": 1
// }
$format.json('{"a":2}', 4); // 4 空格缩进
$format.minify('{ "a": 2 }'); // '{"a":2}'
$format.xml('<root><child>t</child></root>');
// <root>
// <child>t</child>
// </root>

$fs — 文件系统​

脚本内的轻量文件读写(配置、缓存、导出)。路径支持 ~ 展开;write 会自动创建缺失的父目录。

方法返回
$fs.read(path)UTF-8 内容;失败返回 "Error: Cannot read file at <path>"。
$fs.readBinary(path)字节(Base64);失败返回 ""。
$fs.write(path, content)boolean——是否成功。
$fs.exists(path)boolean。
$fs.delete(path)boolean;文件不存在返回 false。
$fs.list(path)目录条目 string[];失败返回 []。
$fs.info(path)JSON 字符串 {size, modified, isDirectory, path};路径不存在返回 undefined。
const file = $env.tmpDir() + "/hodor-test.txt";
$fs.write(file, "Hello from Hodor!");
$fs.read(file); // "Hello from Hodor!"
$fs.exists(file); // true
$fs.list($env.tmpDir()); // ["hodor-test.txt", ...]

const info = JSON.parse($fs.info(file));
info.size; // 字节数
info.isDirectory; // false

$fs.delete(file); // true
note

各方法的失败形态不同:read 返回 "Error: ..." 字符串、readBinary 返回 ""、list 返回 []、info 返回 undefined——请分别处理。

$env — 环境变量​

进程环境变量与系统路径。注意:$env 是进程环境(各次执行间共享,随进程存续)。如需面向用户的持久变量,请使用 sdk.setEnvVar 或 SharedPreferences。

方法返回
$env.get(key)值;不存在的 key 返回 ""。
$env.set(key, value)boolean——setenv 结果。
$env.all()所有环境变量的 JSON 字符串。
$env.cwd()当前工作目录。
$env.tmpDir()临时目录。
$env.homeDir()用户主目录。
$env.set("APP_VERSION", "1.0.0");
$env.get("APP_VERSION"); // "1.0.0"
const all = JSON.parse($env.all());

$uuid — UUID​

生成与校验 UUID(请求 ID、幂等键)。

方法返回
$uuid.v4()标准 v4 UUID(大写、带连字符),如 "550e8400-E29B-41D4-A716-446655440000"。
$uuid.compact()无连字符的小写形式。
$uuid.validate(str)字符串是否为合法 UUID。
const id = $uuid.v4();
$uuid.compact(); // "550e8400e29b41d4a716446655440000"
$uuid.validate($uuid.v4()); // true
$uuid.validate("not-uuid"); // false
note

validate 只接受带连字符的格式——validate($uuid.compact()) 返回 false。校验紧凑字符串前需先补回连字符。

$log — 结构化日志​

带时间戳、分级的日志行,经引擎 console 系统输出(汇总到脚本的日志视图)。

方法返回
$log.log(level, message, tag?)格式化日志行(同时打印)。
$log.debug / info / warn / error(message)各分级便捷方法,仅输出。

日志行格式:[yyyy-MM-dd'T'HH:mm:ss.SSSZ] [LEVEL] [tag] message(未提供 tag 时省略 [tag] 段)。

$log.info("Server started on port 8080");
// [2025-07-24T01:11:45.548+0800] [INFO] Server started on port 8080
$log.log("info", "Request processed", "API");
// [2025-07-24T01:11:45.548+0800] [INFO] [API] Request processed

Web API​

fetch​

从脚本发送真实 HTTP 请求——Postman 风格工作流的主要通道。

fetch(url: string, options?: object) → Promise<response>

options:

字段类型默认说明
methodstring"GET"大小写不敏感;未知值回退为 GET。
timeoutIntervalnumber30秒。
headers[[k, v]] 或 [{k: v}][]两种形态均可。
textBodystring—请求体文本。
encodingstring—"hex" 表示 textBody 为十六进制字符串。

resolve 的值是普通对象:statusCode(number)、headers(单键对象数组,重复键保留)、textBody()——返回 {text, encoding} 的函数,自动检测字符集(无法解码时回退 {text: <hex>, encoding: "hex"})。reject 的值是错误消息字符串。

// GET
const rsp = await fetch("https://httpbin.org/get");
if (rsp.statusCode === 200) {
const body = rsp.textBody(); // {text: "...", encoding: "utf-8"}
const json = JSON.parse(body.text);
}

// POST JSON
const rsp2 = await fetch("https://httpbin.org/post", {
method: "POST",
headers: [["Content-Type", "application/json"]],
textBody: JSON.stringify({a: 1}),
timeoutInterval: 10,
});

HTTPClient​

HTTPClient 类从任意脚本发送 HTTP 请求(基于 fetch 实现)。所有方法均为 async,返回带 statusCode、headers、textBody() 的响应对象。

方法说明
HTTPClient.get(url, params?)发送 GET 请求。
HTTPClient.post(url, params?)发送 POST 请求。
HTTPClient.put(url, params?)发送 PUT 请求。
HTTPClient.update(url, params?)发送 UPDATE 请求。
HTTPClient.delete(url, params?)发送 DELETE 请求。
HTTPClient.request(url, method, params?)发送自定义方法的请求。

params 为可选对象:

  • headers:请求 header 对象,如 {"key1": "value1"}
  • body:请求体——字符串、JSON 对象(自动序列化)或 URLSearchParams
  • timeoutInterval:超时秒数(默认 60)
try {
var params = {
"headers": {"key1": "value1"},
"body": {"a": "a1", "b": "b1"},
};
const response = await HTTPClient.post("https://dummyjson.com/products/1", params);
console.log(response.textBody().text);
} catch(error) {
console.log(error);
}

定时器​

setTimeout / setInterval / clearTimeout / clearInterval 与浏览器中行为一致。回调派发在引擎的串行队列上,与宿主线程无关,触发可靠。

函数返回
setTimeout(callback, ms)定时器 id(string),触发一次。
setInterval(callback, ms)定时器 id,重复触发。
clearTimeout(id) / clearInterval(id)取消(幂等,未知 id 被忽略)。
await new Promise(resolve => setTimeout(resolve, 500)); // 等待 0.5s
const timer = setInterval(() => console.log("tick"), 1000);
setTimeout(() => clearInterval(timer), 3500);

全局函数​

名称签名说明
btoa(str)(string) → stringBase64 编码——UTF-8 对称语义(与浏览器不同,非 Latin1 字符串也可用)。
atob(str)(string) → stringBase64 解码;非法输入返回 ""。
performance.now()() → number自 epoch 起的毫秒数(非页面加载时间)。
sleep(ms)(number) → Promisems 后 resolve;使用 await sleep(1000)。
require(id)(string) → any按 CommonJS 语义(module.exports)加载脚本库;引用键为 @libs/<键>,解析顺序:脚本库 identifier → 脚本库 name(唯一匹配)→ 内置库;未命中抛错。
TextEncodernew TextEncoder().encode(str)UTF-8 编码为 Uint8Array(encoding 恒为 "utf-8")。
crypto.getRandomValues(n)(Array) → number[]填充 n 个随机 UInt32 值。
crypto.randomUUID()() → string随机 UUID(大写、带连字符)。
btoa("Hello"); // "SGVsbG8="
atob("SGVsbG8="); // "Hello"
btoa("中文"); // 可用——按 UTF-8 字节编码
performance.now(); // 1760000000000.123
await sleep(100);
const { encode } = require("@libs/base64"); // 内置库
const { sign } = require("@libs/sign-lib"); // 你的脚本库
new TextEncoder().encode("hi"); // Uint8Array [104, 105]

脚本库在脚本模块管理中维护。require 引用键固定为 @libs/<键>:先按 identifier 精确匹配你的脚本库(重命名不断链),再按 name 唯一匹配,最后解析内置库 @libs/base64 / @libs/hex。库通过 module.exports 导出、可以再 require 其他库,未命中抛错(前置失败中止发送,后置失败保留原始响应)。完整用法见快速请求 scripting 的 require 引用脚本库。

console​

console.log / info / warn / error 将值打印到脚本的日志视图。多参数会被序列化,可直接输出对象与数组:

console.log("headers", {Accept: "application/json"}, [1, 2, 3]);

$log 提供结构化分级输出(见 $log)——两个通道在 Hodor 的脚本日志视图中均可见。

HTTP 类​

Request​

Request 类是传给 onRequest / onSessionCompleted 的封装 HTTP 请求。

成员类型说明
schemestring(get / set)请求协议,如 https。
hoststring(get / set)请求主机。
portnumber(get / set)请求端口。
pathstring(get / set)请求路径。
methodstring(get / set)HTTP 方法,如 GET。
queriesURLSearchParams(get)请求 query 参数。
headersHeaders(get)请求 header。
bodyBody(get)/ string | Map | Array | URLSearchParams(set)请求体。
note

header 必须通过 .set() / .append() 修改——索引赋值(如 headers["X-Key"] = v)会被忽略。

也可以自行构造请求:

const request = new Request({
scheme: 'https',
host: 'example.com',
port: 8080,
path: '/api',
method: 'GET',
queries: 'param1=value1&param2=value2',
headers: [
['Content-Type', 'application/json'],
['Authorization', 'Bearer token']
],
textBody: '{"key": "value"}'
});
console.log(request.encode());

Response​

Response 类表示传给 onResponse / onSessionCompleted 的 HTTP 响应。

成员类型说明
statusCodenumber(get / set)响应状态码。
statusPhrasestring(get / set)响应状态短语,如 OK。
headersHeaders(get)响应 header。
bodyBody(get)/ string | Map | Array | URLSearchParams(set)响应体。
const response = new Response({
statusCode: 404,
statusPhrase: 'Not Found',
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'no-cache'
},
textBody: '{"error": "Resource not found"}'
});
console.log(response.encode());

Body​

Body 类表示 HTTP 请求或响应的 body。给 request.body / response.body 赋新值会整体替换 body。

方法返回说明
parseText()string | null将 body 解析为文本。
parseJSON()object | null将 body 解析为 JSON。
parseURLSearchParams()URLSearchParams | null将 body 解析为 URL 编码参数。
const bodyInstance = new Body('{"user": "alice"}');
const json = bodyInstance.parseJSON();
if (json) {
console.log('User:' + json.user);
} else {
console.error('Failed to parse JSON');
}

Headers​

Headers 类表示 HTTP header。

方法返回说明
append(name, value)void向指定 header 追加值。
set(name, value)void设置(替换)指定 header 的值。
get(name)string | null获取指定 header 的值。
has(name)boolean检查指定 header 是否存在。
delete(name)void删除指定 header。
forEach(callback, thisArg?)void对每个 header 调用函数。
entries() / keys() / values()Iterator遍历条目 / 键 / 值。
encode()Array将 header 编码为可序列化格式。
const headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.set('Content-Length', '1024');
console.log(headers.get('Content-Type')); // 'application/json'
console.log(headers.has('Authorization')); // false
headers.forEach((value, name) => {
console.log(name + ' ' + value);
});

URLSearchParams​

URLSearchParams 类表示 URL query(或 urlencoded body)参数。

方法返回说明
append(name, value)void向指定参数追加值。
set(name, value)void设置(替换)指定参数的值。
get(name)string | null获取指定参数的值。
has(name)boolean检查指定参数是否存在。
delete(name)void删除指定参数。
forEach(callback, thisArg?)void对每个参数调用函数。
entries() / keys() / values()Iterator遍历条目 / 键 / 值。
sort()void排序参数。
toString()string序列化为 urlencoded 字符串。
const params = new URLSearchParams({ key1: 'value1', key2: 'value2' });
console.log(params.get('key1')); // 'value1'
console.log(params.get('key3')); // null
params.forEach((value, key) => console.log(key + ' ' + value));

SharedPreferences​

SharedPreferences 类提供本地持久化键值存储,跨脚本运行与 App 重启保留(底层为系统 user defaults)。

方法返回说明
SharedPreferences.write(key, value)void写入值(string / number / boolean / object / array)。写 null 删除该 key。
SharedPreferences.read(key)any读取 key 关联的值,不存在返回 null。
SharedPreferences.write("test_key", "test_value");
const value = SharedPreferences.read("test_key");
console.log(value);

SharedPreferences.write("cfg", {a: 1}); // 对象直接存储
SharedPreferences.write("cfg", null); // 删除 "cfg"

sdk——快速请求脚本​

sdk(别名 pm)仅在快速请求前置/后置脚本注入。它桥接 App 的变量存储(环境、全局与运行时变量)并收集断言,API 形态与 Postman 类似。

成员说明
sdk.env.get(key)读取 App 中定义的环境变量。
sdk.env.set(key, value)设置环境变量(同 sdk.setEnvVar)。
sdk.setEnvVar(key, value)写入环境变量——收集后回写到 App。
sdk.setVar(key, value)写入运行时(局部)变量。
sdk.setGlobalVar(key, value)写入全局变量。
sdk.getVar(key)读取运行时变量。
sdk.test(name, fn)运行命名断言块;失败被收集并在 App 中上报。
sdk.expect(value)断言原语:toBe、toEqual、toBeTruthy。
sdk.jsonPath(object, path)点路径查找,如 "$.data.list[0].id"。
sdk.utils.uuid()同 crypto.randomUUID()。
sdk.utils.base64Encode(s) / base64Decode(s)同 btoa / atob。
sdk.utils.md5(s)同 $hash.md5。
// 快速请求前置脚本:给请求签名
async function onRequest(context, url, request) {
// 读取 App 环境中定义的变量
const secret = sdk.env.get("secret") || "test-key";
sdk.expect(secret).toBeTruthy();

const ts = String(Date.now());
const bodyText = request.body && request.body.text ? request.body.text : '';
const sig = $hmac.sha256(ts + bodyText, secret);

// header 必须通过 .set / .append 设置
request.headers.set("X-Signature", sig);
request.headers.set("X-Timestamp", ts);

// 将变量回写到 App
sdk.setEnvVar("lastTs", ts);
sdk.test("signature is 64 hex", () => {
sdk.expect(sig.length).toBe(64);
});

console.log("signed request for", url);
return request;
}
note

断言结果仅在前置脚本中上报。后置脚本中断言会执行,但结果不会被收集。

上下文​

RewriteContext​

传给重写脚本(onRequest / onResponse)的上下文对象。

成员类型说明
isEnableOnRequestboolean(get)onRequest 入口是否启用。
isEnableOnResponseboolean(get)onResponse 入口是否启用。
parametersobject(get / set)onRequest 与 onResponse 之间共享的参数字典。
scriptNamestring(get)脚本名称。

CompletedContext​

传给 HTTP 完成脚本的上下文对象。

成员类型说明
sessionobject(get)与完成脚本关联的会话对象。
scriptNamestring(get)完成脚本名称。

ScheduleContext​

传给定时脚本的上下文对象。

成员类型说明
parametersobject(get / set)设置后传给下一次运行循环的参数。
cronstring(get)定时的 cron 表达式。
repeatedCountnumber(get)脚本已重复执行的次数。
scriptNamestring(get)定时脚本名称。

行为说明​

  • 未捕获异常会导致脚本失败。 错误(包括 abort() 抛出的 AbortError)会传播给 Hodor,执行被上报为失败——错误发生前的部分重写会被丢弃,风险代码块请用 try / catch 保护。
  • 超时看门狗。 每次脚本运行有时间预算;永不结束的脚本(如死循环或挂起的 await)会被强制中断并上报为超时。
  • 错误作为返回值。 部分 API 永不抛异常:$codec.base64Decode 返回 ""、$crypto 返回 "Error: ..." 字符串、$fs.read 返回 "Error: ..." 字符串、$fs.info 返回 undefined。请检查返回值而非依赖 try / catch。
  • console.log 与 $log。 两者在脚本日志视图中均可见;$log 额外带时间戳与分级。
  • 脚本运行时持久化。 sdk.setVar 写入的变量与 $fs 写入的文件对同一脚本的后续执行仍可用;SharedPreferences 跨 App 重启保留。