/api/v1
API 文档
一次 POST 请求就能处理一个文件。不需要密钥、账号或签名——地址加上请求体就是全部约定。
快速开始
压缩一个样式表并打印结果:
curl --data-urlencode 'input=.card { padding: 8px; margin: 0 auto; }' \
https://formatter.nextwell.top/api/v1/minify/css/raw
# .card{padding:8px;margin:0 auto}
把 {css} 换成 {js} 或 {html},把 {minify} 换成 {beautify}。任意组合都可用。
端点
基础地址是 {base}。下面的接口除非另有说明,都是 POST。
| 方法 | 路径 | 用途 |
|---|---|---|
| POST | /api/v1/minify/{lang} | 压缩,返回 JSON |
| POST | /api/v1/minify/{lang}/raw | 压缩,返回纯文本 |
| POST | /api/v1/beautify/{lang} | 格式化,返回 JSON |
| POST | /api/v1/beautify/{lang}/raw | 格式化,返回纯文本 |
| GET | /api/v1/limits | 查看该 IP 的剩余额度,且不消耗请求 |
| GET | /api/v1/health | 存活检查,不受速率限制 |
{lang} 是 css、js 或 html 之一。
发送代码
每个端点都接受三种请求体格式,选客户端最方便的那种即可。
表单编码
一个 {input} 字段,{type}。这正是压缩类 API 惯常接受的格式,已有的脚本只需改地址。
curl --data-urlencode 'input=body{margin:0;padding:0}' \
https://formatter.nextwell.top/api/v1/beautify/css
JSON
{type},其中带有一个 {input} 字符串。
curl -H 'Content-Type: application/json' \
-d '{"input":"const a=1;const b=a+1;console.log(b)"}' \
https://formatter.nextwell.top/api/v1/beautify/js
原始请求体
其他任何内容类型:请求体本身就是代码。用 {example} 时很方便。
curl --data-binary @style.css \
-H 'Content-Type: text/css' \
https://formatter.nextwell.top/api/v1/minify/css
大小
每次请求 2 MB。超过的请求不会被读取,直接返回 413。
查询参数
| 名称 | 取值 | 含义 |
|---|---|---|
engine |
auto upstream local |
由哪个引擎处理这次请求。默认值 {auto} 在额度未用尽时把 CSS 和 JS 的压缩发往上游,用尽后回退到本地。{upstream} 不回退,而是直接报错。{local} 则完全不离开本服务器。 |
indent |
2 4 tab |
仅格式化时有效:一级缩进用什么。 |
curl --data-urlencode 'input=.a{color:red}' \
'https://formatter.nextwell.top/api/v1/beautify/css?indent=tab&engine=local'
响应
调用成功时返回 JSON:
{
"ok": true,
"action": "minify",
"language": "css",
"engine": "upstream",
"input_bytes": 1024,
"output_bytes": 640,
"saved_bytes": 384,
"saved_percent": 37.5,
"duration_ms": 42,
"output": "p{color:red}"
}
| 字段 | 类型 | 含义 |
|---|---|---|
ok | boolean | 成功时恒为 true。 |
action | string | minify 或 beautify——请求的是哪种操作。 |
language | string | css、js 或 html。 |
engine | string | 由外部服务处理时为 upstream,由本服务器处理时为 local。 |
input_bytes | number | 发送内容的大小,单位字节。 |
output_bytes | number | 结果的大小,单位字节。 |
saved_bytes | number | 两者之差;格式化时为负数。 |
saved_percent | number | 同一差值的百分比,保留一位小数。 |
duration_ms | number | 处理耗时,单位毫秒。 |
output | string | 处理后的代码。 |
纯文本响应
在任意一个处理端点后面加上 {raw},响应体就只有结果本身,类型是 {type}。响应头不变。从 shell 调用时很方便:
curl -s --data-binary @app.js \
-H 'Content-Type: text/javascript' \
https://formatter.nextwell.top/api/v1/minify/js/raw > app.min.js
响应头
| 标头 | 含义 |
|---|---|
X-Formatter-Engine | 结果由哪个引擎产生。 |
X-Formatter-Duration | 处理耗时,单位毫秒。 |
X-RateLimit-Remaining-Second … -Month | 该 IP 在每个时间窗口内的剩余额度。 |
Retry-After | 出现 429 时:已用尽的窗口中最严格的那个重新开放还需多少秒。 |
curl -s -D - -o /dev/null --data-urlencode 'input=.a{color:red}' \
https://formatter.nextwell.top/api/v1/minify/css
错误
所有错误都是 JSON,采用这类 API 惯用的形状,因此已经能处理这种形状的客户端也能处理这里的错误:
{
"errors": [
{ "status": 429, "title": "Too many requests", "detail": "…" }
]
}
| 状态码 | 标题 | 触发时机 |
|---|---|---|
| 400 | Missing input Bad request | 没有请求体,或 input 字段为空。 |
| 404 | Not found | 路径不存在。 |
| 405 | Method not allowed | 用 POST 以外的方法调用了处理端点。 |
| 413 | Payload too large | 请求体超过 2 MB。 |
| 415 | Unsupported language | 路径中的语言不是 css、js 或 html。 |
| 422 | Malformed input | 处理器拒绝了这段源码,通常是语法错误。 |
| 429 | Too many requests | 某个速率限制窗口已用尽,请查看 Retry-After。 |
| 502 | Upstream failed | 仅在 engine=upstream 时出现:外部服务没有响应。若不指定该参数,这次请求会回退到本地处理。 |
| 500 | Internal error | 其他情况。 |
速率限制
按 IP 地址计算,五个滑动窗口同时生效。一次请求必须同时满足这五个窗口。
| 窗口 | 上限 |
|---|---|
| 每秒 | {n} 次 |
| 每分钟 | {n} 次 |
| 每小时 | {n} 次 |
| 每天 | {n} 次 |
| 每月 | {n} 次 |
某个窗口用尽时会返回 429,并带上 Retry-After 响应头,给出最严格的那个窗口重新开放所需的秒数。请求不会排队。
计数器保存在磁盘上的一个小数据库里,因此重启服务不会让任何人重新拿到一整天的额度。
{endpoint} 会返回五个窗口的当前状态,而不消耗任何额度。
curl https://formatter.nextwell.top/api/v1/limits
外部压缩服务对整个站点只允许每分钟 30 次请求,而不是每位访客 30 次。一个共享令牌桶跟踪这个额度:桶空时,CSS 和 JS 的压缩改由本地引擎完成,而不是等待或失败。负载高时可能会看到 engine 字段发生变化——两种情况下输出都同样有效。
由哪个引擎完成处理
两条路径,同一套约定。
云端 — CSS 和 JS 的压缩
一个外部压缩服务,又快又保守:能去掉的空白才去掉,不能去掉的保留下来,所以像 {calc} 这样的写法会原样保留。本服务只是把代码转发过去,不添加任何自己的处理。
本地 — 其余全部
HTML 压缩、三种语言的格式化,以及共享的外部额度用尽或服务被设为不联网时的 CSS/JS 压缩。基于 {tools} 实现,只在请求需要时才加载,因此空闲的进程始终很小。
设置 {param} 可以把某次请求固定到其中一条路径。
会保留什么
什么都不保留。代码只在请求期间留在内存中,之后即被丢弃,不会写入磁盘,也绝不会出现在日志里。日志中记录的只有:IP 的截断哈希、语言、操作、字节数、引擎和耗时。
常见问题
需要密钥吗?
不需要。服务是开放的,改用 IP 地址来限流。
我的代码会被发到别处吗?
CSS 和 JavaScript 的压缩会代理到外部服务,因此这部分代码会离开本服务器。格式化以及全部 HTML 处理都在本服务器完成。设置 engine=local 可以让一切都留在这里。
可以在构建脚本里用吗?
可以,raw 端点就是为此准备的。注意不要超出限制,并留意高负载时引擎可能会回退到本地。
为什么压缩后的 JavaScript 里的名字变了?
上游的压缩器会缩短局部变量名,这是安全的,也是体积缩减的主要来源。格式化并不会把原来的名字找回来——任何工具都做不到。
最大能发送多大的文件?
单次请求 2 MB。更大的文件会被以 413 拒绝,而不是被截断。