Formatter

API ドキュメント

POST リクエスト 1 回でファイルを処理します。キーもアカウントも署名も不要で、アドレスとボディが取り決めのすべてです。

クイックスタート

スタイルシートを圧縮して結果を出力します。

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 のいずれかです。

コードの送り方

どのエンドポイントも 3 種類のボディ形式を受け付けます。クライアントで扱いやすいものを選んでください。

フォームエンコード

{input} フィールドを {type} で送ります。これは Toptal 自身の圧縮器が受け取る形式なので、既存のスクリプトはアドレスを変えるだけで済みます。

curl --data-urlencode 'input=body{margin:0;padding:0}' \
  https://formatter.nextwell.top/api/v1/beautify/css

JSON

{input} 文字列を含む {type} です。

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

サイズ

1 リクエストあたり 2 MB です。これを超えるものは読まれずに 413 が返ります。

クエリパラメータ

名前 意味
engine auto upstream local このリクエストをどのエンジンが処理するかを決めます。既定値の {auto} は、残量があるあいだ CSS と JS の圧縮を上流に送り、尽きたらローカルにフォールバックします。{upstream} はフォールバックせずに失敗を返します。{local} はサーバーの外に出ません。
indent 2 4 tab 整形時のみ有効で、インデント 1 段分の中身を指定します。
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}"
}
フィールド 意味
okboolean成功時は必ず true です。
actionstringminify または beautify で、要求された処理を表します。
languagestringcss、js、html のいずれかです。
enginestringToptal が処理した場合は upstream、このサーバーが処理した場合は local です。
input_bytesnumber送信された内容のサイズ(バイト)です。
output_bytesnumber結果のサイズ(バイト)です。
saved_bytesnumberその差分で、整形のときは負の値になります。
saved_percentnumber同じ差分を百分率で表したもので、小数第 1 位までです。
duration_msnumber処理にかかった時間(ミリ秒)です。
outputstring処理後のコードです。

プレーンテキストの応答

処理用のエンドポイントに {raw} を付けると、ボディは結果だけになり、{type} で返ります。ヘッダーは同じです。呼び出し元がシェルのときに便利です。

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-After429 のとき、使い切ったウィンドウのうち最も厳しいものが空くまでの秒数です。
curl -s -D - -o /dev/null --data-urlencode 'input=.a{color:red}' \
  https://formatter.nextwell.top/api/v1/minify/css

エラー

エラーはすべて JSON で、Toptal の圧縮器と同じ形です。あちらのエラーを扱えるクライアントは、そのままこちらも扱えます。

{
  "errors": [
    { "status": 429, "title": "Too many requests", "detail": "…" }
  ]
}
ステータス タイトル 発生条件
400Missing input Bad requestボディがない、または input フィールドが空です。
404Not foundそのパスはありません。
405Method not allowed処理用のエンドポイントを POST 以外で呼び出しました。
413Payload too largeボディが 2 MB を超えています。
415Unsupported languageパスの言語が css、js、html のいずれでもありません。
422Malformed inputフォーマッタがソースを受け付けませんでした。多くは構文エラーです。
429Too many requestsレート制限のウィンドウのいずれかを使い切りました。Retry-After を見てください。
502Upstream failedengine=upstream のときだけ発生します。Toptal が応答しませんでした。この指定がなければ、リクエストはローカルにフォールバックしていました。
500Internal errorそれ以外のすべてです。

レート制限

IP アドレスごとに 5 つのローリングウィンドウがあり、すべて同時に効きます。リクエストは 5 つすべてに収まる必要があります。

ウィンドウ 上限
1 秒あたり{n} 回
1 分あたり{n} 回
1 時間あたり{n} 回
1 日あたり{n} 回
1 か月あたり{n} 回

ウィンドウを使い切ると 429 が返り、Retry-After ヘッダーに最も厳しいウィンドウが空くまでの秒数が入ります。キューには入りません。

カウンターはディスク上の小さなデータベースに置かれているので、サービスを再起動しても 1 日分の枠が戻ることはありません。

{endpoint} は 5 つのウィンドウの現在の状態を返しますが、枠は消費しません。

curl https://formatter.nextwell.top/api/v1/limits

Toptal が許すのは、訪問者ごとではなくこのサービス全体で 1 分あたり 30 リクエストです。共有のバケットがそれを管理し、空になると CSS と JS の圧縮は待たされたり失敗したりせず、ローカルのエンジンが処理します。負荷が高いときは engine フィールドの値が変わることがありますが、どちらでも出力は正しいままです。

処理を担当するエンジン

経路は 2 つ、取り決めは 1 つです。

Toptal — CSS と JS の圧縮

あちらの圧縮器は速く、かつ保守的です。削れる空白だけを削り、削れない空白は残すので、{calc} のような記述はそのまま保たれます。このサービスはコードをそのまま渡すだけで、独自の処理は加えません。

ローカル — それ以外のすべて

HTML の圧縮、3 言語すべての整形、そして共有の上流の残量が尽きたときや、サービスをオフラインのままにする設定のときの CSS / JS の圧縮を担当します。{tools} を使い、リクエストが必要としたときにだけ読み込むので、待機中のプロセスは小さいままです。

{param} を指定すると、そのリクエストを片方の経路に固定できます。

保存されるもの

何も残しません。コードはリクエストのあいだだけメモリに置かれ、その後破棄されます。ディスクに書き込むことはなく、ログに現れることもありません。ログに残るのは、IP の切り詰めたハッシュ、言語、処理、バイト数、エンジン、所要時間だけです。

よくある質問

キーは必要ですか。

不要です。サービスは公開されていて、代わりに IP アドレスで制限しています。

コードはどこかに送られますか。

CSS と JavaScript の圧縮は Toptal の圧縮器へプロキシされるため、そのコードは先方のサーバーに届きます。整形と HTML の処理はすべてこのサーバーで行います。engine=local を指定すれば、すべてここに留まります。

ビルドスクリプトで使えますか。

使えます。raw のエンドポイントはそのためにあります。制限の範囲内で使い、負荷が高いときはエンジンがフォールバックしうる点に注意してください。

圧縮した JavaScript の名前が変わるのはなぜですか。

上流の圧縮器はローカル変数の名前を短くします。これは安全な処理で、削減量の大半はここから来ています。整形しても元の名前は戻りません。どんな方法でも戻せません。

送れるファイルの最大サイズはどれくらいですか。

1 リクエストにつき 2 MB です。それより大きいファイルは切り詰められず、413 で拒否されます。