httpie / xh / hurl:替代 curl 做 API 测试的现代选择

起因

每天调几十次 curl 测 API,命令越写越长:

curl -X POST https://api.example.com/v1/users \
  -H 'Authorization: Bearer xxx' \
  -H 'Content-Type: application/json' \
  -d '{"email":"[email protected]","name":"Alice","age":30}' \
  -i -v -s \
  | jq .

curl 强大但 verbose。下面几个现代工具针对"开发期 API 调试"做了大幅
简化。

httpie:人友好的 curl 替代

brew install httpie    # 或 apt install httpie / pipx install httpie
http --version

用法

# GET
http https://api.example.com/users/1
# 自动 pretty-print JSON + 语法高亮

# POST + JSON body
http POST https://api.example.com/users \
  email=[email protected] name=Alice age:=30
# - key=value 是字符串
# - key:=value 是 number/bool/null 等 (JSON 类型)
# - 自动加 Content-Type: application/json

# Authorization
http https://api.example.com/me Authorization:'Bearer xxx'
# 或:
http -A bearer -a xxx https://api.example.com/me

# 上传文件
http POST https://api.example.com/upload file@./photo.jpg

# 看 request / response 头(默认显示 response 头)
http -v POST ...   # -v 把 request 也打印
http -h POST ...   # 只 print headers
http -p Hb POST ...   # 控制哪些部分打印 (H=header, b=body)

# session(保存 cookie + auth)
http --session=alice POST https://api.example.com/login email=[email protected]
http --session=alice https://api.example.com/me   # 复用 cookies

输出:

HTTP/1.1 200 OK
Content-Type: application/json
Date: Mon, 24 May 2026 10:00:00 GMT
Server: nginx

{
    "id": 42,
    "name": "Alice",
    "email": "[email protected]"
}

JSON 自动格式化 + 高亮,headers 区分颜色,整体一眼看清。

xh:Rust 重写的 httpie,启动更快

brew install xh
# 或 cargo install xh
xh --version

API 几乎完全跟 httpie 兼容:

xh POST https://api.example.com/users email=[email protected] name=Alice

httpie 启动 ~150ms(Python),xh ~10ms(Rust)。频繁使用差异明显。

我个人现在用 xh > httpie > curl 这个偏好。

hurl:把 API 测试写成可重放脚本

brew install hurl

.hurl 文件:

# login.hurl
POST https://api.example.com/login
{
    "email": "[email protected]",
    "password": "secret"
}

HTTP 200
[Asserts]
jsonpath "$.token" exists
jsonpath "$.user.email" == "[email protected]"
[Captures]
token: jsonpath "$.token"


GET https://api.example.com/me
Authorization: Bearer {{token}}

HTTP 200
[Asserts]
jsonpath "$.email" == "[email protected]"


POST https://api.example.com/posts
Authorization: Bearer {{token}}
{
    "title": "Hello",
    "body": "..."
}

HTTP 201
[Asserts]
jsonpath "$.title" == "Hello"
[Captures]
post_id: jsonpath "$.id"


GET https://api.example.com/posts/{{post_id}}

HTTP 200

跑:

hurl login.hurl
# 全部 assertion 通过 = exit 0
# 否则 exit 非 0

# 输出更详细
hurl --verbose --variables-file vars.env login.hurl

# 测试 mode
hurl --test login.hurl

适用:

  • E2E API 测试 + CI
  • API 回归验证(每次部署后自动跑)
  • 复制粘贴前端测试用的 request 序列

完整功能:query params、文件上传、cookies、多文件 chain、报告输出(JSON/JUnit/HTML)。

curl 仍然适合什么

curl 不会消失:

  • 服务器 minimal 环境(绝对默认安装)
  • 调试 TLS / HTTP 协议级(-v --trace
  • script / Dockerfile / CI 里(无依赖、跨平台)
  • 二进制下载 / 长文件传输

httpie / xh 是"开发期人调用",curl 是"机器调用"。

与 Postman / Insomnia 对比

GUI 工具优势:

  • 历史记录 + 文档化
  • 团队共享 collection
  • 自动 OAuth 流程

CLI 工具优势:

  • 嵌入 shell 脚本
  • 版本控制(.hurl 进 git)
  • 远程服务器跑(无 GUI 环境)

我个人:探索 / 团队共享用 Bruno(GUI 但
本地文件存储 + git 友好);shell 直接调用 xh / hurl。

bonus: jq / jaq 处理 JSON 响应

xh https://api.example.com/users | jq '.[] | select(.age > 30) | .name'

# jaq(jq 的 Rust 重写,10x 快)
brew install jaq
xh https://api.example.com/users | jaq -r '.[] | .email'

-r raw 输出(无引号),适合 pipe 进 xargs。

实战 workflow

测一个新 API:

# 1. 探索 - GET
xh https://api.example.com/users/1

# 2. 试 POST
xh POST https://api.example.com/users name=Bob email=[email protected]

# 3. 满意后写成 hurl 脚本
cat > tests/create-user.hurl <<'EOF'
POST https://api.example.com/users
{ "name": "{{name}}", "email": "{{email}}" }

HTTP 201
[Asserts]
jsonpath "$.id" exists
EOF

# 4. CI 里跑
hurl --test --variables-file ci-vars.env tests/*.hurl

xh 探索 → hurl 固化。一条 pipeline。

效果

迁移后:

  • 日常 API 调试输入字符 -70%(不用 -X -H -d
  • API 回归测试用 hurl 脚本进 git,新员工看脚本就懂用法
  • ci 端 hurl 测试 10 个 endpoint 用 5 秒
  • 团队同 hurl 文件分享,跨 OS / 跨编辑器一致

踩过的坑

  1. shell 解析 :=
    bash http POST url 'description=hello, world' # 逗号正常 http POST url 'tags:=["a","b"]' # JSON 数组要 quote
    特殊字符记得 quote。

  2. httpie 默认 redirect 不跟-F / --follow 才跟 redirect。
    xh 默认跟。

  3. session 文件路径~/.config/httpie/sessions/。换机器要带,
    --session-read-only 临时用。

  4. hurl asserts 严格类型jsonpath "$.count" == 5== "5"
    不同(数字 vs 字符串)。看 API 返回类型对照写。

  5. 不支持 WebSocket / gRPC:纯 HTTP。WebSocket 用 wscat / websocat;
    gRPC 用 grpcurl。

精确评价 共 0 人评价
可复现性
可复现 · 0 不可复现 · 0
文风
文风流畅 · 0 文风晦涩 · 0
立场
支持 · 0 反对 · 0

登录后即可对本帖作出评价。

评论区 0 条 · 所有人可在此交流

登录后参与评论。

还没有评论,来说两句。