← Runnable Projects

阅读中文版本

Node.js JSON API with the Standard Library

A dependency-free HTTP API with health, list, and 404 endpoints, plus an automated test that starts the server on an ephemeral port and verifies each response.

beginnerjavascriptverified-runnable

Project

node-json-api

Entry point: server.mjs

Install

node --version

Run

node server.mjs

Test

node --test server.test.mjs

Expected output

GET /health returns {"status":"ok"}, GET /items returns two rows, and an unknown path returns 404.

Dependencies

  • node >=20

Verification evidence

Node 24.15: node --test -> 1 passed; live curl checks returned {"status":"ok"}, two items, and 404 for /nope.

Security note

Binds to localhost only in this example; add authentication and input validation before exposing list endpoints publicly.

What it does

A small JSON API built only with node:http. It exposes /health, /items, and a JSON 404 response. The test starts the server on an ephemeral port, so it can run in CI without port conflicts.

import { createServer } from 'node:http';
import { pathToFileURL } from 'node:url';

const items = [{ id: 1, name: 'alpha' }, { id: 2, name: 'beta' }];

export function createApp() {
  return createServer((req, res) => {
    const send = (status, body) => {
      res.writeHead(status, { 'content-type': 'application/json' });
      res.end(JSON.stringify(body));
    };
    if (req.url === '/health') return send(200, { status: 'ok' });
    if (req.url === '/items') return send(200, items);
    return send(404, { error: 'not found' });
  });
}

if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
  createApp().listen(3000, () => console.log('listening on 3000'));
}
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { createApp } from './server.mjs';

test('health and items endpoints', async () => {
  const server = createApp().listen(0);
  const { port } = server.address();
  try {
    const health = await fetch(`http://127.0.0.1:${port}/health`);
    assert.equal(health.status, 200);
    assert.deepEqual(await health.json(), { status: 'ok' });
    const items = await fetch(`http://127.0.0.1:${port}/items`);
    assert.equal(items.status, 200);
    assert.equal((await items.json()).length, 2);
    const missing = await fetch(`http://127.0.0.1:${port}/nope`);
    assert.equal(missing.status, 404);
  } finally {
    server.close();
  }
});

Run and verify

node --test server.test.mjs
node server.mjs
curl -s http://127.0.0.1:3000/health

Expected output: {"status":"ok"}, a two-item JSON array, and a 404 {"error":"not found"}. The test asserts all three paths without external dependencies. Verified with Node 24.15: the test passed and live curl checks matched.

Limitations

Responses are static, there is no persistence or authentication, and the server has no graceful shutdown handler. It is a starting point for a real service, not a production API.