ice-jade

ice-jade 是一个基于 Ruby 标准库的轻量级工具集,零外部依赖。最初定位是 IM Webhook SDK,现已扩展为包含多个独立分支的通用 HTTP 工具包:

  • Quantum — IM Webhook 客户端
  • Poster — 通用 HTTP POST 客户端
  • HttpPoster — 独立模块级 HTTP POST 工具
  • Cradle — HTTP 测试服务器
  • YAMLServer — YAML 配置驱动的测试服务器实例

安装

gem 'ice-jade'
bundle install

或本地安装:

gem build ice-jade.gemspec
gem install ice-jade-*.gem

分支一:Quantum IM

Quantum 是企业 IM 群机器人的 Webhook 客户端,支持文本、图片、文件、图文消息的发送,以及附件上传。

快速开始

require 'ice_jade'

client = IceJade::Quantum::Client.new('your-webhook-key')

# 发送文本
client.send_text("hello world")

# @所有人
client.send_text("紧急通知", mention_all: true)

# 图文消息
client.send_news("标题", "https://example.com", description: "描述")

# 上传并发送图片
client.upload_and_send_image("/path/to/photo.jpg", height: 1080, width: 1920)

# 上传并发送文件
client.upload_and_send_file("/path/to/report.pdf")

详细文档:documents/im-quantum-api.md


分支二:Poster

IceJade::Poster::Client 是通用 HTTP POST 客户端,面向对象设计,支持 JSON / Form / Multipart,内置超时重试和统一 Response 包装。

快速开始

require 'ice_jade'

poster = IceJade::Poster::Client.new(
  base_url: 'https://api.example.com',
  headers:  { 'Authorization' => 'Bearer token' },
  timeout:  30
)

# POST JSON
resp = poster.post_json('/users', { name: 'Alice' })
puts resp.data if resp.success?

# POST Form
resp = poster.post_form('/login', { username: 'admin', password: 'secret' })

# POST Multipart(文件上传)
resp = poster.post_multipart('/upload', { file: '/path/to/image.png' })

# 通用 post(自定义 Content-Type)
resp = poster.post('/hook', '<xml>...</xml>', content_type: 'application/xml')

与 Quantum 的关系

分支 定位 典型场景
Quantum IM Webhook 专用 SDK 向企业 IM 群机器人发消息
Poster 通用 HTTP POST 客户端 调用任意 REST API、Webhook

两者共享 IceJade::ResponseIceJade::Error,响应处理风格一致。

详细文档:documents/poster-api.md


分支三:HttpPoster(独立模块)

HttpPosterlib/http_poster.rb 中定义的纯标准库 HTTP POST 工具,零 gem 依赖。它是独立于 ice-jade gem 的扁平化脚本,适合不想引入任何 gem 的场景。

快速开始

require_relative 'lib/http_poster'

# POST JSON(模块静态方法)
res = HttpPoster.post_json(
  'https://api.example.com/users',
  { name: 'Alice' },
  { 'Authorization' => 'Bearer token' },
  { timeout: 30 }
)
puts res  # => Hash(解析后的 JSON)

与 Poster 的对比

维度 HttpPoster IceJade::Poster::Client
调用方式 模块静态方法 new 实例化再调用
URL 处理 只能传完整 URL 支持 base_url + 相对路径
参数风格 位置参数 (url,p,h,opts) 关键字参数 (headers:)
成功返回 Hash / String IceJade::Response
错误处理 TimeoutError / HttpError 包装为 Response(不抛异常)
所属体系 独立脚本(无依赖) ice-jade gem 分支
典型场景 快速脚本、教学、零依赖 正式项目、与 Quantum 混用

详细文档:documents/http-poster-api.md


分支四:Cradle(HTTP 测试服务器)

Cradle 是轻量级 HTTP 测试服务器,基于 Ruby 标准库 socket + thread,零外部依赖。用于本地测试 Poster、Quantum 或其他 HTTP 客户端。

命令行启动

cradle              # 默认监听 0.0.0.0:8765
cradle -p 3000      # 监听 0.0.0.0:3000
cradle -h 127.0.0.1 # 仅本地访问

代码启动

require 'ice_jade'

server = IceJade::Cradle::Server.new(port: 8765)

# 注册自定义路由
server.route(:post, '/echo') do |req|
  [200, { 'Content-Type' => 'application/json' },
   JSON.generate(method: req.method, body: req.parsed_body)]
end

server.start

详细文档:documents/cradle-api.md


分支五:YAMLServer(YAML 配置驱动的测试实例)

YAMLServer 通过载入 YAML 配置文件启动定制化的 HTTP 测试实例,无需写 Ruby 代码注册路由,适合频繁切换测试场景。

命令行启动

cradle-instance config/cradle/poster_test.yml

YAML 配置示例

port: 8765
host: 127.0.0.1

routes:
  - method: POST
    path: /echo
    handler: echo_json

  - method: POST
    path: /error
    handler: static
    status: 500
    headers:
      Content-Type: application/json
    body: '{"error":"Internal Server Error"}'

内置 handler:echo_jsonecho_formecho_uploadstaticdelay

详细文档:documents/yaml-server-api.md


扩展 Cradle / YAMLServer

Cradle 和 YAMLServer 都可以通过扩展代码添加新功能,变成满足实际需求的 HTTP 服务器:

  • Cradle::Server:通过 route(method, path) { |req| ... } 注册自定义路由
  • YAMLServer:通过 HANDLERS['name'] = lambda { |req, cfg| ... } 注册自定义处理器
  • 混合模式:YAML 启动基础路由,Ruby 代码追加动态路由

扩展能力包括:自定义响应格式、路径参数、请求头校验、状态计数器、随机延迟、分页模拟、代理转发等。也可以把扩展封装为独立 gem 复用 Cradle 内核。

详细文档:documents/cradle-extension.md


文件结构

lib/
  ice_jade.rb                  # 主入口
  http_poster.rb               # 独立模块(零依赖)
  ice_jade/
    version.rb
    error.rb
    response.rb
    client_base.rb
    quantum/
      client.rb
      message.rb
    poster/
      client.rb
    cradle/
      server.rb               # 原生服务器
      yaml_server.rb          # YAML 配置层

bin/
  cradle                      # 命令行:启动原生服务器
  cradle-instance             # 命令行:启动 YAML 实例

config/cradle/
  poster_test.yml             # Poster 测试专用配置

examples/
  quantum_usage.rb            # Quantum 用法示例
  poster_usage.rb             # Poster + YAMLServer 联测
  comparison_poster.rb        # HttpPoster vs Poster 对比
  cradle_usage.rb             # Cradle 服务器用法

documents/
  im-quantum-api.md           # Quantum API 文档
  poster-api.md               # Poster API 文档
  http-poster-api.md          # HttpPoster 文档
  cradle-api.md               # Cradle 文档
  yaml-server-api.md          # YAMLServer 文档
  cradle-extension.md         # 扩展指南

架构设计

分支关系

ice-jade/
├── Quantum        # IM Webhook 客户端
├── Poster         # 通用 HTTP POST 客户端
├── HttpPoster     # 独立模块(零 gem 依赖)
├── Cradle         # HTTP 测试服务器
└── YAMLServer     # YAML 配置层(基于 Cradle)

添加新 IM(Quantum 模式)

每个 IM 独占一个命名空间,内部包含自己的 ClientMessage(如果有)。

lib/ice_jade/
  quantum/
    client.rb   # Quantum::Client < ClientBase
    message.rb  # Quantum::Message
  feishu/       # 未来其他IM
    client.rb
  dingtalk/     # 未来其他IM#2
    client.rb

步骤:

  1. lib/ice_jade/ 下新建目录
  2. 实现 client.rb,继承 IceJade::ClientBase
  3. lib/ice_jade.rbrequire_relative

模板见 README.md 原 Quantum 扩展章节。

统一接口(可选工厂)

def build_im_client(config)
  case config[:type]
  when 'quantum' then IceJade::Quantum::Client.new(config[:key])
  when 'feishu'  then IceJade::Feishu::Client.new(config[:webhook_url])
  else raise "Unknown IM type: #{config[:type]}"
  end
end

依赖

  • Ruby >= 2.5
  • 仅使用标准库(net/httpsocketjsonuriyaml 等)

限制

  • Quantum:文件上传 30MB,消息频率 20条/分钟
  • Cradle:不支持 WebSocket、HTTPS、持久连接