/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 중 하나가 들어갑니다.
코드 보내기
모든 엔드포인트가 세 가지 본문 형식을 받습니다. 클라이언트에서 다루기 쉬운 것을 고르면 됩니다.
폼 인코딩
{type} 형식의 {input} 필드입니다. 압축 API가 관례적으로 받는 형식과 같아서, 기존 스크립트는 주소만 바꾸면 됩니다.
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
크기
요청 한 번당 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}입니다. 헤더는 같습니다. 호출하는 쪽이 셸일 때 편합니다.
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
오류
모든 오류는 이런 종류의 API에서 관례적으로 쓰는 형태의 JSON입니다. 그 형태를 이미 처리하는 클라이언트라면 이쪽도 그대로 처리합니다.
{
"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건입니다. 공유 버킷이 이를 관리하며, 버킷이 비면 CSS와 JS 압축은 기다리거나 실패하는 대신 로컬 엔진이 처리합니다. 부하가 높을 때는 engine 필드가 바뀔 수 있지만, 어느 쪽이든 출력은 그대로 유효합니다.
작업을 처리하는 엔진
경로는 둘, 규약은 하나입니다.
클라우드 — CSS와 JS 압축
외부 압축 서비스입니다. 빠르면서도 보수적이어서 없앨 수 있는 공백만 없애고 그럴 수 없는 공백은 남기므로, {calc} 같은 표현은 그대로 유지됩니다. 이 서비스는 코드를 그대로 전달할 뿐 자체적인 처리를 더하지 않습니다.
로컬 — 나머지 전부
HTML 압축, 세 언어의 정리 전부, 그리고 공유 외부 한도가 떨어졌거나 서비스를 오프라인으로 두도록 설정한 경우의 CSS/JS 압축을 맡습니다. {tools} 위에 만들어졌고, 요청에 필요할 때만 불러오므로 대기 중인 프로세스는 작게 유지됩니다.
{param} 값을 지정하면 해당 요청을 한쪽 경로에 고정할 수 있습니다.
보관하는 정보
아무것도 남기지 않습니다. 코드는 요청이 처리되는 동안만 메모리에 있다가 버려집니다. 디스크에 기록하지 않고 로그에도 남지 않습니다. 로그에 남는 것은 잘라낸 IP 해시, 언어, 작업, 바이트 수, 엔진, 처리 시간뿐입니다.
자주 묻는 질문
키가 필요한가요?
필요 없습니다. 서비스는 공개되어 있고, 대신 IP 주소로 제한합니다.
제 코드가 어딘가로 전송되나요?
CSS와 JavaScript 압축은 외부 서비스로 프록시되므로 그 코드는 이 서버를 벗어납니다. 정리와 HTML 작업은 모두 이 서버에서 처리합니다. engine=local을 지정하면 모든 처리가 여기에 머무릅니다.
빌드 스크립트에서 쓸 수 있나요?
가능합니다. raw 엔드포인트가 바로 그 용도입니다. 제한 범위 안에서 사용하고, 부하가 높을 때는 엔진이 로컬로 바뀔 수 있다는 점에 유의하세요.
압축한 JavaScript의 이름이 바뀌는 이유는 무엇인가요?
업스트림 압축기는 지역 변수 이름을 짧게 줄입니다. 안전한 처리이며 절감량의 대부분이 여기에서 나옵니다. 정리해도 원래 이름은 돌아오지 않습니다. 어떤 방법으로도 되돌릴 수 없습니다.
보낼 수 있는 파일의 최대 크기는 얼마인가요?
요청 한 번에 2 MB입니다. 더 큰 파일은 잘리지 않고 413으로 거부됩니다.