news 2026/9/15 11:01:57

iii 0.21:把任意函数变成 REST 端点的完整路径

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
iii 0.21:把任意函数变成 REST 端点的完整路径

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

搭建只需要三条命令,按顺序执行:

  1. 启动引擎(若尚未运行):
iii --config config.yaml
  1. 脚手架生成一个 worker:
iii worker init my-worker --language typescript
  1. 指向 worker 目录把它加入引擎:
iii worker add ./my-worker

执行成功后 worker 进程会被拉起并连接到引擎,iii worker add http这类内置 worker 同理。

这里要注意 engine/config.yaml 的分工:config.yaml只放引擎生命周期内的内置 worker(iii-streamconfiguration等),文件注释里明确写着httpstatecronqueuepubsubbridge这类项目级 worker 应放在worker-compose.yaml管理——iii worker add http的行为正对应后者。

用一个触发器把函数绑到路由上

worker 源码里只做两件事:注册处理函数、注册http触发器。处理函数的入参是请求内容(bodyheaders、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"), )?;

三种语言遵守同一份契约:

  • 函数 idhttp::add这种带命名空间前缀的命名,触发器通过function_id与函数关联;
  • 返回值映射status_codebodyheaders三个字段分别成为 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>, }

字段级含义:

  1. api_path:路由路径,支持/users/:id这类模式,路径参数是内置能力,函数入参里可以直接取到;
  2. http_method:可省略,default_http_method()返回GET——不写就是 GET 端点,枚举值覆盖GET/POST/PUT/DELETE/PATCH/HEAD/OPTIONS
  3. condition_function_id:可选的前置函数 id,引擎在调用处理函数前先求值它,适合做路由级的前置校验,对应引擎的 trigger 条件机制。

同文件里还定义了响应信封HttpCallResponse,对返回值缺失字段的行为有明确默认:status_code省略时默认200headers省略时不带响应头,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 有独立条目(httpstatequeue……),修改走触发器即可:

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_pathhttp_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与方法是否和请求完全一致,方法省略时默认GETPOST请求不会命中 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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 10:52:45

如何异步导出excel

当用户点击导出按钮时&#xff0c;我们不希望用户等待数据导出的整个过程&#xff0c;因为这可能会很长时间&#xff0c;导致页面超时或者用户体验下降。所以&#xff0c;我们采用异步处理的方式来完成这个任务。这就像是你去餐厅点了一份需要很长时间烹饪的食物&#xff0c;服…

作者头像 李华
网站建设 2026/9/15 10:52:06

C语言实现快速排序算法

1. 什么是快速排序算法快速排序的核心思想是通过分治法&#xff08;Divide and Conquer&#xff09;来实现排序。算法的基本步骤是:1. 选择一个基准值&#xff08;通常是数组中的某个元素&#xff09;&#xff0c;将数组分成两部分&#xff0c;使得左边的部分所有元素都小于基准…

作者头像 李华
网站建设 2026/9/15 10:49:36

Loop:免费开源的 Mac 窗口管理工具,5 分钟就能上手

Loop&#xff1a;免费开源的 Mac 窗口管理工具&#xff0c;5 分钟就能上手 【免费下载链接】Loop Window management made elegant. 项目地址: https://gitcode.com/GitHub_Trending/lo/Loop 第三次把浏览器窗口拖歪、又得手动对齐之后&#xff0c;你终于受够了。Loop 是…

作者头像 李华