脚本
RelayCore 包含一个 Deno/V8 运行时,用于使用 JavaScript 或 TypeScript 动态修改请求和响应。
概述
脚本可以在各个阶段拦截和修改流量:
onRequest— 在请求被转发之前onResponse— 在响应被接收之后onWebSocket— 用于 WebSocket 消息
基本脚本
import { Flow, FlowAction } from "relay:script";
async function onRequest(flow: Flow): Promise<FlowAction> {
console.log(`Request: ${flow.method} ${flow.url}`);
// 添加自定义 header
flow.request.headers["X-Script-Ran"] = "true";
// 记录并继续
return FlowAction.Continue;
}
async function onResponse(flow: Flow): Promise<FlowAction> {
console.log(`Response: ${flow.status} for ${flow.url}`);
// 为特定 URL 返回模拟响应
if (flow.path === "/api/mocked") {
return FlowAction.Mock({
status: 200,
headers: { "content-type": "application/json" },
body: JSON.stringify({ mocked: true }),
});
}
return FlowAction.Continue;
} Flow 对象
interface Flow {
id: string;
timestamp: Date;
method: string;
url: string;
host: string;
path: string;
protocol: string;
status?: number;
request: {
headers: Record<string, string>;
body?: Uint8Array;
bodyText?: string;
bodyJson?: unknown;
};
response?: {
headers: Record<string, string>;
body?: Uint8Array;
bodyText?: string;
bodyJson?: unknown;
};
duration_ms: number;
size: number;
} FlowAction
enum FlowAction {
Continue = "continue", // 正常继续
Drop = "drop", // 丢弃流量
Mock = "mock", // 返回模拟响应
Intercept = "intercept", // 暂停以供检查
Redirect = "redirect", // 重定向到 URL
} 高级示例
import { Flow, FlowAction } from "relay:script";
// 用于测试的模拟 API 响应
const mocks = new Map([
["/api/users", { users: [{ id: 1, name: "Alice" }] }],
["/api/products", { products: [{ id: 1, name: "Widget" }] }],
]);
async function onRequest(flow: Flow): Promise<FlowAction> {
// 如果缺少则注入 auth token
if (flow.path.startsWith("/api/") && !flow.request.headers["authorization"]) {
flow.request.headers["authorization"] = "Bearer test-token-123";
}
return FlowAction.Continue;
}
async function onResponse(flow: Flow): Promise<FlowAction> {
if (flow.response && flow.response.bodyJson) {
// 记录所有 API 响应
console.log(`API Response for ${flow.path}:`, flow.response.bodyJson);
// 向响应注入元数据
if (Array.isArray(flow.response.bodyJson)) {
flow.response.bodyJson._meta = {
mocked: true,
timestamp: new Date().toISOString(),
};
}
}
return FlowAction.Continue;
} 加载脚本
# 加载脚本
relay-core-cli scripts load ./path/to/script.ts
# 列出已加载的脚本
relay-core-cli scripts list
# 卸载脚本
relay-core-cli scripts unload my-script 脚本配置
# 在 config.toml 中
[scripting]
enabled = true
deno_dir = "~/.relay-core/deno"
auto_reload = true