iii 0.21:把任意函数变成 REST 端点的完整路径
【免费下载链接】iiiEffortlessly compose, extend, and observe every service in real-time for the first time ever.项目地址: https://gitcode.com/GitHub_Trending/mo/iii
这篇文章带你用 iii 0.21 内置的httpworker 把一个普通函数绑定成一条 REST 路由:启动引擎、注册函数、挂一个http触发器,然后用一条curl命令拿到 JSON 响应。全程不需要 Express、FastAPI 或 Axum 这类 Web 框架,跑完之后你会得到一条"从curl到函数执行"的完整闭环。
最终结果:在 3111 端口上 curl 一个端点
先看目标形态。端点注册好之后,调用它只需要一条命令,请求直接打到引擎的 HTTP 端口(默认3111):
curl -X POST http://localhost:3111/math/add -H 'content-type: application/json' -d '{"a":2,"b":3}'预期行为:返回状态码200,响应体为{"c":5},响应头含Content-Type: application/json。
这里有个容易误解的点:监听3111端口的不是你自己写的代码,而是 http worker——一个项目级 worker,由引擎按 engine/worker-compose.yaml 里的容器定义拉起来。你的 worker 只负责提供函数,路由的"管道"是引擎给的。
最小闭环:从启动引擎到 worker add
搭建只需要三条命令,按顺序执行:
- 启动引擎(若尚未运行):
iii --config config.yaml- 脚手架生成一个 worker:
iii worker init my-worker --language typescript- 指向 worker 目录把它加入引擎:
iii worker add ./my-worker执行成功后 worker 进程会被拉起并连接到引擎,iii worker add http这类内置 worker 同理。
这里要注意 engine/config.yaml 的分工:config.yaml只放引擎生命周期内的内置 worker(iii-stream、configuration等),文件注释里明确写着http、state、cron、queue、pubsub、bridge这类项目级 worker 应放在worker-compose.yaml管理——iii worker add http的行为正对应后者。
用一个触发器把函数绑到路由上
worker 源码里只做两件事:注册处理函数、注册http触发器。处理函数的入参是请求内容(body、headers、method 等),返回值经引擎拆解后成为 HTTP 响应。
Node / TypeScript 版本:
import { registerWorker } from "iii-sdk"; const url = process.env.III_URL; if (!url) throw new Error("III_URL must be set"); const worker = registerWorker(url, { workerName: "my-worker" }); worker.registerFunction("http::add", async (payload: { body: { a: number; b: number } }) => ({ status_code: 200, body: { c: payload.body.a + payload.body.b }, headers: { "Content-Type": "application/json" }, })); worker.registerTrigger({ type: "http", function_id: "http::add", config: { api_path: "/math/add", http_method: "POST" }, });Python 等价写法
import os from iii import register_worker, InitOptions worker = register_worker( os.environ["III_URL"], InitOptions(worker_name="my-worker"), ) def add(payload: dict) -> dict: body = payload["body"] return { "status_code": 200, "body": {"c": body["a"] + body["b"]}, "headers": {"Content-Type": "application/json"}, } worker.register_function("http::add", add) worker.register_trigger({ "type": "http", "function_id": "http::add", "config": {"api_path": "/math/add", "http_method": "POST"}, })Rust 等价写法
use iii_sdk::builtin_triggers::{HttpMethod, HttpTriggerConfig}; use iii_sdk::trigger::IIITrigger; use iii_sdk::{InitOptions, RegisterFunction, register_worker}; use schemars::JsonSchema; use serde::Deserialize; use serde_json::json; #[derive(Deserialize, JsonSchema)] struct AddRequest { body: AddBody, } #[derive(Deserialize, JsonSchema)] struct AddBody { a: i64, b: i64, } let url = std::env::var("III_URL").expect("III_URL must be set"); let worker = register_worker(&url, InitOptions::default()); worker.register_function( "http::add", RegisterFunction::new(|req: AddRequest| { Ok(json!({ "status_code": 200, "body": { "c": req.body.a + req.body.b }, "headers": { "Content-Type": "application/json" } })) }), ); worker.register_trigger( IIITrigger::Http(HttpTriggerConfig::new("/math/add").method(HttpMethod::Post)) .for_function("http::add"), )?;三种语言遵守同一份契约:
- 函数 id用
http::add这种带命名空间前缀的命名,触发器通过function_id与函数关联; - 返回值映射:
status_code、body、headers三个字段分别成为 HTTP 状态码、响应体、响应头(注意字段名是status_code,不是status); - 触发器配置只有两个关键字段:
api_path定路由,http_method定方法。
HttpTriggerConfig 源码字段逐条解读
触发器配置结构体定义在引擎侧 engine/src/trigger_formats.rs:
pub struct HttpTriggerConfig { /// HTTP endpoint path (e.g. `/users/:id`) pub api_path: String, /// HTTP method (defaults to GET) #[serde(default = "default_http_method")] pub http_method: Option<HttpMethod>, /// Optional function ID to evaluate before invoking handler pub condition_function_id: Option<String>, }字段级含义:
api_path:路由路径,支持/users/:id这类模式,路径参数是内置能力,函数入参里可以直接取到;http_method:可省略,default_http_method()返回GET——不写就是 GET 端点,枚举值覆盖GET/POST/PUT/DELETE/PATCH/HEAD/OPTIONS;condition_function_id:可选的前置函数 id,引擎在调用处理函数前先求值它,适合做路由级的前置校验,对应引擎的 trigger 条件机制。
同文件里还定义了响应信封HttpCallResponse,对返回值缺失字段的行为有明确默认:status_code省略时默认200,headers省略时不带响应头,body省略时返回空对象,且会按你设置的Content-Type序列化为 JSON、文本或字节。
默认端口 3111 的出处
3111不是魔法数字,在两处有依据。
第一处是 engine/worker-compose.yaml 里 http 容器的配置块:
http: worker: package://api.workers.iii.dev/http version: "0.21.3" config_name: http config_override: port: 3111 host: 127.0.0.1 default_timeout: 30000 concurrency_request_limit: 1024 cors: allowed_origins: - http://localhost:3000 - http://localhost:5173 allowed_methods: [GET, POST, PUT, DELETE, OPTIONS]port: 3111就是curl里那个端口的来源,host绑定127.0.0.1说明默认只在本机可达。
第二处是 configuration worker 的配置模板语法${HTTP_PORT:3111}。engine/src/workers/configuration/store.rs 的测试里专门针对它做了断言:port: ${HTTP_PORT:3111}这类模板必须先展开再做 schema 校验,校验的是展开后的整数3111,而不是把模板字符串当字符串放行——否则端口值会静默变成字符串类型。
改端口和 CORS:走 configuration worker 的运行时通道
http worker 的服务器设置(端口、host、CORS、超时)不写死在 worker 定义里,而是注册进 configuration worker,运行时可改。按 docs/using-iii/configuration.mdx 的用法,每个 worker 有独立条目(http、state、queue……),修改走触发器即可:
iii trigger configuration::get --json '{"id": "http"}' iii trigger configuration::set --json '{"id": "http", "value": {"port": 8080, "host": "127.0.0.1"}}'预期行为:set成功后新值按 schema 校验并生效,http的 CORS、超时、端口这类设置多数在变更后立即应用,无需重启 worker。配置值支持与config.yaml相同的${VAR:default}模板语法,模板按原文存储、每次读取时重新展开,所以换个环境变量就能换默认值。
如何验证端点与常见排查
除curl外,console 的 Triggers 页可以直接验证:左侧列出全部 HTTP 触发器(方法与路径),右侧有 TEST API 面板,选方法和查询参数后点 SEND REQUEST 发真实请求,底部同步展示该触发器的配置 JSON(api_path、http_method)。
等价的第二次curl验证(换一组入参,确认是函数在算而不是回显):
curl -X POST http://localhost:3111/math/add -H 'content-type: application/json' -d '{"a":10,"b":32}' # 预期:200,响应体 {"c":42}排查清单:
- 连接被拒:先确认 http 容器在跑(
worker-compose.yaml里有没有 http 条目),再确认端口没被占用;改端口用上面的configuration::set或容器config_override; - 404/打不中函数:核对触发器
api_path与方法是否和请求完全一致,方法省略时默认GET,POST请求不会命中 GET 触发器; - 响应与预期不符:检查返回值三个字段名,
status_code拼错或缺省会落到默认200+ 空 body 的组合。
四句话收束
- 装什么:
iii worker add http,由worker-compose.yaml的容器定义托管,服务器管道归引擎; - 怎么绑:函数 +
{ type: "http", function_id, config: { api_path, http_method } }触发器,一一对应; - 默认值:方法省略为
GET,端口3111、host127.0.0.1,状态码缺省200; - 去哪改:端口/CORS/超时走 configuration worker 运行时
configuration::set,不用重新部署 worker。
【免费下载链接】iiiEffortlessly compose, extend, and observe every service in real-time for the first time ever.项目地址: https://gitcode.com/GitHub_Trending/mo/iii
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考