Документация 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.
Как отправить код
Каждый эндпоинт принимает тело в трёх видах — выбирайте тот, который проще сформировать вашему клиенту.
Форма urlencoded
Поле {input}, {type}. Такой же вид принимают минификаторы Toptal, так что готовому скрипту достаточно поменять адрес.
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
Сырое тело
Любой другой content type: телом идёт сам код. Удобно для {example}.
curl --data-binary @style.css \
-H 'Content-Type: text/css' \
https://formatter.nextwell.top/api/v1/minify/css
Размер
2 МБ на запрос. Всё, что больше, возвращается как 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, если обработал Toptal, local — если этот сервер. |
input_bytes | number | Размер отправленного, в байтах. |
output_bytes | number | Размер результата, в байтах. |
saved_bytes | number | Разница; при форматировании отрицательная. |
saved_percent | number | Та же разница в процентах, с одним знаком после запятой. |
duration_ms | number | Сколько заняла обработка, в миллисекундах. |
output | string | Обработанный код. |
Ответы обычным текстом
Допишите {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-After | При 429: секунды до открытия самого узкого исчерпанного окна. |
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": "…" }
]
}
| Код | Поле title | Когда |
|---|---|---|
400 | Missing input Bad request | Нет тела или поле input пустое. |
404 | Not found | Такого пути нет. |
405 | Method not allowed | К эндпоинту форматирования обратились не через POST. |
413 | Payload too large | Тело больше 2 МБ. |
415 | Unsupported language | Язык в пути не css, не js и не html. |
422 | Malformed input | Форматтер отказался обрабатывать исходник — обычно это синтаксическая ошибка. |
429 | Too many requests | Одно из окон лимита исчерпано. Смотрите Retry-After. |
502 | Upstream failed | Только при engine=upstream: Toptal не ответил. Без этого переопределения запрос ушёл бы на локальный движок. |
500 | Internal error | Всё остальное. |
Лимиты запросов
На IP-адрес, пять скользящих окон, все действуют одновременно. Запрос должен уложиться во все пять.
| Окно | Лимит |
|---|---|
| В секунду | Запросов: {n} |
| В минуту | Запросов: {n} |
| В час | Запросов: {n} |
| В сутки | Запросов: {n} |
| В месяц | Запросов: {n} |
Когда окно исчерпано, приходит 429 с заголовком Retry-After: в нём секунды до открытия самого узкого окна. Ничего не ставится в очередь.
Счётчики лежат в небольшой базе на диске, так что перезапуск сервиса никому не выдаёт новые сутки.
{endpoint} показывает текущее состояние всех пяти окон, не тратя запрос.
curl https://formatter.nextwell.top/api/v1/limits
Toptal разрешает 30 запросов в минуту на весь сервис, а не на каждого посетителя. За этим следит общий счётчик-бакет: когда он пуст, минификацию CSS и JS выполняет локальный движок — вместо ожидания или ошибки. Под нагрузкой поле engine может меняться, но результат в обоих случаях корректен.
Какой движок делает работу
Два пути, один контракт.
Toptal — минификация CSS и JS
Их минификаторы быстрые и осторожные: убирают те пробелы, которые можно убрать, и сохраняют те, которые нельзя, так что конструкции вроде {calc} остаются целыми. Этот сервис пропускает код через них и ничего не добавляет от себя.
Локальный движок — всё остальное
Минификация HTML, все три форматировщика и минификация CSS/JS, когда общий лимит внешнего сервиса исчерпан или сервису задано работать без внешних вызовов. Построен на {tools}, которые подгружаются только тогда, когда их требует запрос, — простаивающий процесс остаётся маленьким.
Задайте {param}, чтобы закрепить запрос за одним путём.
Что сохраняется
Ничего. Код живёт в памяти ровно столько, сколько длится запрос, и удаляется. На диск он не пишется и в логах не появляется. В логи попадают только: укороченный хеш IP, язык, действие, число байт, движок и длительность.
Вопросы
Нужен ли ключ?
Нет. Сервис открыт, вместо ключа действует ограничение по IP-адресу.
Отправляется ли мой код куда-либо?
Минификация CSS и JavaScript проксируется в минификаторы Toptal, так что этот код попадает на их серверы. Форматирование и вся работа с HTML идут на этом сервере. Задайте engine=local, чтобы всё оставалось здесь.
Можно ли использовать это в сборочном скрипте?
Да, для этого и сделаны эндпоинты /raw. Держитесь в пределах лимитов и учитывайте, что под нагрузкой движок может переключиться на локальный.
Почему в минифицированном JavaScript изменились имена?
Внешний минификатор укорачивает имена локальных переменных — это безопасно и даёт основную часть экономии. Форматирование не вернёт исходные имена: их не вернёт уже ничто.
Файл какого размера можно отправить?
2 МБ за один запрос. Файлы больше отклоняются с 413, а не обрезаются.