API 連携ガイド
代替フロントエンドは NIE-SLA を資格情報不要・読み取り専用・キャッシュ可能なデータソースとして扱います。管理セッションをプロキシ・再利用せず、バージョン管理されていない内部ルートを直接呼ばないでください。
初期化の順序
- ユーザー入力を正規化し、Worker の
originだけを残す。 GET /api/v1を要求し、api_version === "v1"を検証する。- マニフェストの
endpointsと機能フィールドから利用可能な機能を判断する。 - 初回画面に
/api/v1/status?days=30&lite=1を取得する。 - ユーザーが詳細を開いたときに checks・metrics・pings・latency を要求する。
- ページ非表示時はポーリングを停止し、復帰時はランダムな遅延を追加する。
最小クライアント
js
export function createNieSlaClient(input) {
const base = new URL(input)
if (base.username || base.password) throw new Error('API base must not contain credentials')
if (base.protocol !== 'https:' && !['localhost', '127.0.0.1', '[::1]'].includes(base.hostname)) {
throw new Error('production API must use HTTPS')
}
const origin = base.origin
async function get(path, params = {}, timeoutMs = 12_000) {
const url = new URL(`/api/v1/${path}`.replace(/\/$/, ''), origin)
for (const [key, value] of Object.entries(params)) {
if (value !== undefined && value !== null && value !== '') url.searchParams.set(key, String(value))
}
const controller = new AbortController()
const timer = setTimeout(() => controller.abort(), timeoutMs)
try {
const response = await fetch(url, {
signal: controller.signal,
credentials: 'omit',
headers: { accept: 'application/json' },
})
const body = await response.json().catch(() => null)
if (!response.ok || body?.ok === false) throw new Error(body?.error || `HTTP ${response.status}`)
return body
} finally {
clearTimeout(timer)
}
}
return {
manifest: async () => {
const body = await get('')
if (body?.api_version !== 'v1') throw new Error('response is not a NIE-SLA v1 manifest')
return body
},
status: options => get('status', { days: 30, lite: 1, ...options }),
checks: (targetId, options) => get('checks', { target_id: targetId, ...options }),
metrics: (agentId, options) => get('metrics', { agent_id: agentId, ...options }),
pings: (agentId, options) => get('pings', { agent_id: agentId, ...options }),
latency: (targetId, options) => get('latency', { target_id: targetId, ...options }),
}
}例は HTTP ステータスと body.ok の両方を確認します。互換エンドポイントが HTTP 200 の中にビジネスエラーを返すことがあるためです。本番プロジェクトでは主要フィールドの型も検証し、AbortError をタイムアウト状態として表示してください。
React/Vue の状態モデル
すべてを 1 つの loading 真偽値にまとめないでください。最低限以下を区別します。
ts
type ResourceState<T> =
| { state: 'idle' }
| { state: 'loading'; previous?: T }
| { state: 'ready'; data: T; warnings: string[] }
| { state: 'empty'; data: T; message: string }
| { state: 'error'; error: string; retryAt?: number }更新中は previous を保持してチャートの空白点滅を防ぎます。warnings[] は部分的なデータ劣化であり、成功して読み込まれたメインデータを置き換えるものではありません。
ポーリングとキャッシュ
- Status は 20〜60 秒推奨。
Cache-Controlを尊重し、X-NIE-SLA-Cacheを観察します(X-NStatus-Cacheは v1 互換エイリアスです)。 - マニフェストは既定 300 秒、Metrics は 15 秒、Pings は 20 秒、Latency は 30 秒キャッシュ。
- Checks は正規化された
target_id・hours・limitをキャッシュキーに含める。 - 429 と 5xx は上限付き指数バックオフ。400/403/404 はそのまま再試行しない。
- Worker・Cloudflare キャッシュ回避のためランダムなクエリパラメータを追加しない。
チャートデータ
- 時系列はタイムスタンプで明示的に昇順ソートし、レスポンス順に依存しない。
ok = falseの遅延は障害・故障マーカーであり、0 msとして描画しない。format=columnsではdtと各 values 配列の長さを確認する。history_downsampledまたはpings_downsampledが真ならデータはダウンサンプリング済み。- Cloudflare チェック・Agent Ping・外部 Latency は異なる凡例とソースラベルを使う。
- 温度・GPU など任意フィールドが欠落している場合は系列を非表示にし、ゼロ埋めしない。
サーバー側統合
サーバー側リクエストはブラウザ CORS の制約を受けませんが、レート制限は受けます。共有キャッシュ・適切な User-Agent・タイムアウト・回数制限付き再試行を使い、エンドユーザーのリクエストごとに全履歴を再取得しないでください。公開 API に書き込み能力はなく、サーバーも境界を迂回するために管理・Agent 資格情報を保存すべきではありません。
ブラウザセキュリティ
- fetch では常に
credentials: 'omit'。 - API ベースはデプロイ設定または検証済みユーザー入力から取得し、URL クエリパラメータで本番アドレスを黙って上書きさせない。
- HTTPS オリジンのみ許可。ローカル HTTP は開発時のみ例外。
- API テキストはフレームワーク既定のエスケープまたは
textContentで描画する。 - 完全なレスポンスを公開エラーテレメトリに書き込まない。デプロイ者が公開を選んだとはいえ、識別可能なノードプロフィールが含まれることがあります。
各エンドポイントのフィールドとパラメータは Status、Checks、Metrics、Pings、Latency を参照してください。