No-as-a-Service

NaaS — ランダムな「ノー」と、その裏側のミニマル Express サーバ。

1 — 概要

No-as-a-Service は、GET /no ひとつで JSON 形式の断り文句を返す小さな API。真面目なビジネス文面からシュールな言い訳まで、reasons.json に載った大量の短文から毎回ランダムに選ぶ。ボット・デモ・社内ツールのネタ用途向け。

1055reasons.json 行(配列要素数)
120req / 分 / IP(上限)
1公開エンドポイント
Expressランタイム
公開ホスト例: 作者のデプロイではベース https://naas.isalman.dev/no が README に記載されている。利用条件・可用性は当該ホストのポリシーに従う。
2 — API
項目値
メソッドGET
パス/no
レスポンス{ "reason": "<string>" }(Content-Type: application/json 想定)
レート制限1 分あたり 120 リクエスト / IP。超過時は { "error": "Too many requests, ..." } 形式(実装依存)
CORScors ミドルウェアで全オリジン許可(ローカル検証向け。本番では絞り込みを検討)

リクエスト例

GET /no HTTP/1.1
Host: localhost:3000

レスポンス例

{
  "reason": "This feels like something Future Me would yell at Present Me for agreeing to."
}
3 — 実装
HTTP GET /no → express-rate-limit → メモリ上の reasons[] → 乱数 1 件 → res.json({ reason })
  • データ読み込み: 起動時に reasons.json を同期読み込みし配列を保持。リクエストごとにディスク I/O はしない。
  • レート制限キー: cf-connecting-ip ヘッダがあればそれを優先し、なければ req.ip。trust proxy を有効にしてプロキシ背後の IP を扱う。
  • 依存関係(ローカル clone): express, cors, express-rate-limit(package.json 準拠)。
const express = require('express');
const cors = require("cors");
const rateLimit = require('express-rate-limit');
const fs = require('fs');

const app = express();
app.use(cors());
app.set('trust proxy', true);
const PORT = process.env.PORT || 3000;

const reasons = JSON.parse(fs.readFileSync('./reasons.json', 'utf-8'));

const limiter = rateLimit({
  windowMs: 60 * 1000,
  max: 120,
  keyGenerator: (req, res) => {
    return req.headers['cf-connecting-ip'] || req.ip;
  },
  message: { error: "Too many requests, please try again later. (120 reqs/min/IP)" }
});

app.use(limiter);

app.get('/no', (req, res) => {
  const reason = reasons[Math.floor(Math.random() * reasons.length)];
  res.json({ reason });
});

app.listen(PORT, () => {
  console.log(`No-as-a-Service is running on port ${PORT}`);
});
4 — セルフホスト
  1. リポジトリを clone し、ディレクトリに入る。
  2. npm install
  3. npm start(内部で node index.js)
  4. 既定では http://localhost:3000/no が有効。
ポート: 環境変数 PORT で上書き可能(例: PORT=5000 npm start)。

コンテナ開発向けに .devcontainer.json と Dockerfile が同梱されている。ライセンスは MIT。