Node.jsでWebサーバーを構築する際、多くの開発者はExpressやFastifyなどのフレームワークを使用します。しかし、Node.jsには組み込みのhttpモジュールが用意されており、フレームワークなしでもHTTPサーバーを構築できます。

この記事では、Node.js組み込みのhttpモジュールを使用してWebサーバーを構築する方法を解説します。HTTPプロトコルの基礎からリクエスト/レスポンスの処理、サーバーのライフサイクル管理まで、実践的なコード例とともに学んでいきましょう。

実行環境と前提条件

項目 バージョン
Node.js 20.x LTS以上
npm 10.x以上
OS Windows/macOS/Linux

前提条件として、JavaScriptの基礎知識とNode.jsの基本的なAPI理解があることを想定しています。

httpモジュールとは

Node.jsのhttpモジュールは、HTTPサーバーとクライアントの機能を提供する組み込みモジュールです。外部パッケージをインストールすることなく、HTTPプロトコルに基づいた通信を実装できます。

1
2
3
4
5
// CommonJS形式
const http = require('node:http');

// ES Modules形式
import * as http from 'node:http';

httpモジュールは低レベルなAPIを提供しており、リクエストとレスポンスをストリームとして扱います。この設計により、大きなデータを効率的に処理できます。

http.createServer()でサーバーを作成する

基本的なサーバー作成

http.createServer()メソッドを使用して、HTTPサーバーのインスタンスを作成します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
const http = require('node:http');

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
  res.end('Hello, World!');
});

server.listen(3000, () => {
  console.log('サーバーが http://localhost:3000 で起動しました');
});

createServer()メソッドにはリクエストリスナー関数を渡します。この関数は2つの引数を受け取ります。

引数 説明
req http.IncomingMessage クライアントからのリクエスト情報
res http.ServerResponse クライアントへのレスポンス

createServerのオプション

createServer()には様々なオプションを指定できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
const http = require('node:http');

const server = http.createServer({
  // リクエストタイムアウト(ミリ秒)
  requestTimeout: 300000,
  // ヘッダータイムアウト(ミリ秒)
  headersTimeout: 60000,
  // Keep-Aliveタイムアウト(ミリ秒)
  keepAliveTimeout: 5000,
  // 最大ヘッダー数
  maxHeadersCount: 2000
}, (req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello, World!');
});

server.listen(3000);

リクエストオブジェクト(IncomingMessage)の活用

リクエスト情報の取得

http.IncomingMessageオブジェクトには、クライアントからのリクエスト情報が含まれています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
const http = require('node:http');

const server = http.createServer((req, res) => {
  // リクエスト情報を取得
  console.log('HTTPメソッド:', req.method);
  console.log('URL:', req.url);
  console.log('HTTPバージョン:', req.httpVersion);
  console.log('ヘッダー:', req.headers);

  res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
  res.end(JSON.stringify({
    method: req.method,
    url: req.url,
    headers: req.headers
  }));
});

server.listen(3000);

主要なプロパティを以下の表にまとめます。

プロパティ 説明
method string HTTPメソッド(GET、POST等)
url string リクエストURL
headers Object リクエストヘッダー(小文字キー)
httpVersion string HTTPプロトコルバージョン
socket net.Socket 接続ソケット

リクエストボディの取得

リクエストボディはストリームとして受信します。dataイベントでチャンクを受け取り、endイベントで処理を完了します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const http = require('node:http');

const server = http.createServer((req, res) => {
  // POSTリクエストのボディを取得
  if (req.method === 'POST') {
    let body = '';

    req.on('data', (chunk) => {
      body += chunk.toString();
    });

    req.on('end', () => {
      console.log('受信データ:', body);
      
      res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
      res.end(JSON.stringify({ received: body }));
    });

    req.on('error', (err) => {
      console.error('リクエストエラー:', err);
      res.writeHead(500);
      res.end('Internal Server Error');
    });
  } else {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('GET request received');
  }
});

server.listen(3000);

JSONデータの解析

POSTされたJSONデータを解析する例です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
const http = require('node:http');

function parseJSON(body) {
  try {
    return JSON.parse(body);
  } catch {
    return null;
  }
}

const server = http.createServer((req, res) => {
  if (req.method === 'POST' && req.headers['content-type'] === 'application/json') {
    let body = '';

    req.on('data', (chunk) => {
      body += chunk.toString();
    });

    req.on('end', () => {
      const data = parseJSON(body);

      if (data === null) {
        res.writeHead(400, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ error: 'Invalid JSON' }));
        return;
      }

      res.writeHead(200, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify({ success: true, data }));
    });
  } else {
    res.writeHead(405, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ error: 'Method Not Allowed' }));
  }
});

server.listen(3000);

レスポンスオブジェクト(ServerResponse)の操作

ステータスコードの設定

レスポンスのステータスコードはstatusCodeプロパティまたはwriteHead()メソッドで設定します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
const http = require('node:http');

const server = http.createServer((req, res) => {
  // 方法1: statusCodeプロパティを使用
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('OK');

  // 方法2: writeHead()を使用(推奨)
  // res.writeHead(200, { 'Content-Type': 'text/plain' });
  // res.end('OK');
});

server.listen(3000);

よく使用するHTTPステータスコードを以下に示します。

コード 意味 使用場面
200 OK 正常終了
201 Created リソース作成成功
204 No Content 成功(レスポンスボディなし)
301 Moved Permanently 恒久的リダイレクト
302 Found 一時的リダイレクト
400 Bad Request クライアントエラー
401 Unauthorized 認証が必要
403 Forbidden アクセス禁止
404 Not Found リソース未発見
500 Internal Server Error サーバーエラー

ヘッダーの設定

レスポンスヘッダーはsetHeader()メソッドまたはwriteHead()メソッドで設定します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
const http = require('node:http');

const server = http.createServer((req, res) => {
  // 個別にヘッダーを設定
  res.setHeader('Content-Type', 'application/json; charset=utf-8');
  res.setHeader('X-Custom-Header', 'MyValue');
  res.setHeader('Cache-Control', 'no-cache');
  
  // 複数の値を持つヘッダー
  res.setHeader('Set-Cookie', ['session=abc123', 'user=john']);

  res.writeHead(200);
  res.end(JSON.stringify({ message: 'Hello' }));
});

server.listen(3000);

writeHead()を使用すると、ステータスコードとヘッダーを一度に設定できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
const http = require('node:http');

const server = http.createServer((req, res) => {
  res.writeHead(200, {
    'Content-Type': 'application/json; charset=utf-8',
    'X-Custom-Header': 'MyValue',
    'Cache-Control': 'no-cache'
  });
  res.end(JSON.stringify({ message: 'Hello' }));
});

server.listen(3000);

重要なヘッダー操作メソッド

ServerResponseオブジェクトには、ヘッダー操作のための便利なメソッドが用意されています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const http = require('node:http');

const server = http.createServer((req, res) => {
  // ヘッダーを設定
  res.setHeader('Content-Type', 'text/html');
  res.setHeader('X-Powered-By', 'Node.js');

  // ヘッダーの存在確認
  console.log(res.hasHeader('Content-Type')); // true

  // ヘッダーの取得
  console.log(res.getHeader('Content-Type')); // 'text/html'

  // 設定済みヘッダー名の一覧
  console.log(res.getHeaderNames()); // ['content-type', 'x-powered-by']

  // ヘッダーの削除
  res.removeHeader('X-Powered-By');

  res.writeHead(200);
  res.end('<h1>Hello</h1>');
});

server.listen(3000);

様々なレスポンス形式の返却

HTMLレスポンス

HTMLコンテンツを返却する例です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const http = require('node:http');

const server = http.createServer((req, res) => {
  const html = `
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Node.js HTTP Server</title>
  <style>
    body { font-family: sans-serif; padding: 20px; }
    h1 { color: #333; }
  </style>
</head>
<body>
  <h1>Hello from Node.js!</h1>
  <p>現在時刻: ${new Date().toLocaleString('ja-JP')}</p>
</body>
</html>
  `;

  res.writeHead(200, {
    'Content-Type': 'text/html; charset=utf-8',
    'Content-Length': Buffer.byteLength(html)
  });
  res.end(html);
});

server.listen(3000);

JSONレスポンス

REST APIでよく使用されるJSONレスポンスの例です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const http = require('node:http');

const server = http.createServer((req, res) => {
  const data = {
    success: true,
    message: 'データを取得しました',
    data: {
      id: 1,
      name: 'サンプル',
      createdAt: new Date().toISOString()
    }
  };

  const json = JSON.stringify(data, null, 2);

  res.writeHead(200, {
    'Content-Type': 'application/json; charset=utf-8',
    'Content-Length': Buffer.byteLength(json)
  });
  res.end(json);
});

server.listen(3000);

リダイレクト

HTTPリダイレクトを実装する例です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const http = require('node:http');

const server = http.createServer((req, res) => {
  if (req.url === '/old-page') {
    // 301: 恒久的リダイレクト
    res.writeHead(301, {
      'Location': '/new-page'
    });
    res.end();
    return;
  }

  if (req.url === '/temporary') {
    // 302: 一時的リダイレクト
    res.writeHead(302, {
      'Location': 'https://example.com'
    });
    res.end();
    return;
  }

  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Welcome to the page');
});

server.listen(3000);

シンプルなルーティングの実装

フレームワークを使用せずに、基本的なルーティングを実装できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
const http = require('node:http');

// ルートハンドラーの定義
const routes = {
  'GET /': (req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
    res.end('<h1>ホームページ</h1>');
  },

  'GET /about': (req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
    res.end('<h1>このサイトについて</h1>');
  },

  'GET /api/users': (req, res) => {
    const users = [
      { id: 1, name: '田中太郎' },
      { id: 2, name: '山田花子' }
    ];
    res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
    res.end(JSON.stringify(users));
  },

  'POST /api/users': (req, res) => {
    let body = '';
    req.on('data', chunk => body += chunk);
    req.on('end', () => {
      const user = JSON.parse(body);
      res.writeHead(201, { 'Content-Type': 'application/json; charset=utf-8' });
      res.end(JSON.stringify({ id: 3, ...user }));
    });
  }
};

// 404ハンドラー
function notFound(req, res) {
  res.writeHead(404, { 'Content-Type': 'application/json; charset=utf-8' });
  res.end(JSON.stringify({ error: 'Not Found' }));
}

const server = http.createServer((req, res) => {
  const routeKey = `${req.method} ${req.url}`;
  const handler = routes[routeKey] || notFound;
  handler(req, res);
});

server.listen(3000, () => {
  console.log('サーバーが起動しました: http://localhost:3000');
});

サーバーの起動と停止

サーバーの起動オプション

server.listen()メソッドには様々なオプションを指定できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
const http = require('node:http');

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello');
});

// ポート番号のみ指定
server.listen(3000);

// ポートとホストを指定
server.listen(3000, '127.0.0.1');

// オプションオブジェクトを使用
server.listen({
  port: 3000,
  host: '0.0.0.0',
  backlog: 511
}, () => {
  console.log('サーバー起動');
});

優雅な停止(Graceful Shutdown)

本番環境では、接続中のリクエストを適切に処理してからサーバーを停止する必要があります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
const http = require('node:http');

const server = http.createServer((req, res) => {
  // 長時間の処理をシミュレート
  setTimeout(() => {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('処理完了');
  }, 2000);
});

server.listen(3000, () => {
  console.log('サーバー起動: http://localhost:3000');
});

// Graceful Shutdownの実装
function gracefulShutdown(signal) {
  console.log(`${signal} シグナルを受信しました`);

  // 新規接続の受付を停止
  server.close(() => {
    console.log('全ての接続が終了しました');
    process.exit(0);
  });

  // アイドル状態の接続を閉じる
  server.closeIdleConnections();

  // タイムアウト後に強制終了
  setTimeout(() => {
    console.log('タイムアウト: 強制終了します');
    server.closeAllConnections();
    process.exit(1);
  }, 10000);
}

process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
process.on('SIGINT', () => gracefulShutdown('SIGINT'));

サーバーイベントの活用

http.Serverは様々なイベントを発行します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
const http = require('node:http');

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello');
});

// 新規接続時
server.on('connection', (socket) => {
  console.log('新規接続:', socket.remoteAddress);
});

// リクエスト受信時
server.on('request', (req, res) => {
  console.log(`${req.method} ${req.url}`);
});

// サーバー終了時
server.on('close', () => {
  console.log('サーバーが終了しました');
});

// クライアントエラー時
server.on('clientError', (err, socket) => {
  console.error('クライアントエラー:', err.message);
  if (socket.writable) {
    socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
  }
});

server.listen(3000, () => {
  console.log('サーバー起動');
});

エラーハンドリング

堅牢なサーバーを構築するためには、適切なエラーハンドリングが不可欠です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
const http = require('node:http');

const server = http.createServer((req, res) => {
  try {
    // URLのパース
    const url = new URL(req.url, `http://${req.headers.host}`);
    
    if (url.pathname === '/error') {
      throw new Error('意図的なエラー');
    }

    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ 
      path: url.pathname,
      query: Object.fromEntries(url.searchParams)
    }));
  } catch (error) {
    console.error('リクエスト処理エラー:', error);
    
    if (!res.headersSent) {
      res.writeHead(500, { 'Content-Type': 'application/json' });
    }
    res.end(JSON.stringify({ 
      error: 'Internal Server Error',
      message: error.message 
    }));
  }
});

// サーバーレベルのエラーハンドリング
server.on('error', (error) => {
  if (error.code === 'EADDRINUSE') {
    console.error(`ポート ${error.port} は既に使用されています`);
  } else if (error.code === 'EACCES') {
    console.error('ポートへのアクセス権限がありません');
  } else {
    console.error('サーバーエラー:', error);
  }
  process.exit(1);
});

server.listen(3000, () => {
  console.log('サーバー起動: http://localhost:3000');
});

完成したWebサーバーの例

ここまでの内容を統合した、実用的なWebサーバーの例を示します。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
const http = require('node:http');

// 設定
const PORT = process.env.PORT || 3000;
const HOST = process.env.HOST || '127.0.0.1';

// JSONを解析するユーティリティ
async function parseRequestBody(req) {
  return new Promise((resolve, reject) => {
    let body = '';
    req.on('data', chunk => body += chunk.toString());
    req.on('end', () => {
      if (!body) return resolve(null);
      try {
        resolve(JSON.parse(body));
      } catch {
        reject(new Error('Invalid JSON'));
      }
    });
    req.on('error', reject);
  });
}

// レスポンス送信ユーティリティ
function sendJSON(res, statusCode, data) {
  const json = JSON.stringify(data, null, 2);
  res.writeHead(statusCode, {
    'Content-Type': 'application/json; charset=utf-8',
    'Content-Length': Buffer.byteLength(json)
  });
  res.end(json);
}

// インメモリデータストア
const users = new Map([
  [1, { id: 1, name: '田中太郎', email: 'tanaka@example.com' }],
  [2, { id: 2, name: '山田花子', email: 'yamada@example.com' }]
]);
let nextId = 3;

// リクエストハンドラー
async function handleRequest(req, res) {
  const url = new URL(req.url, `http://${req.headers.host}`);
  const path = url.pathname;
  const method = req.method;

  console.log(`${new Date().toISOString()} ${method} ${path}`);

  try {
    // GET /api/users - ユーザー一覧
    if (method === 'GET' && path === '/api/users') {
      return sendJSON(res, 200, { 
        users: Array.from(users.values()) 
      });
    }

    // GET /api/users/:id - ユーザー詳細
    const userMatch = path.match(/^\/api\/users\/(\d+)$/);
    if (method === 'GET' && userMatch) {
      const id = parseInt(userMatch[1], 10);
      const user = users.get(id);
      if (!user) {
        return sendJSON(res, 404, { error: 'User not found' });
      }
      return sendJSON(res, 200, { user });
    }

    // POST /api/users - ユーザー作成
    if (method === 'POST' && path === '/api/users') {
      const body = await parseRequestBody(req);
      if (!body || !body.name || !body.email) {
        return sendJSON(res, 400, { error: 'name and email are required' });
      }
      const newUser = { id: nextId++, name: body.name, email: body.email };
      users.set(newUser.id, newUser);
      return sendJSON(res, 201, { user: newUser });
    }

    // DELETE /api/users/:id - ユーザー削除
    if (method === 'DELETE' && userMatch) {
      const id = parseInt(userMatch[1], 10);
      if (!users.has(id)) {
        return sendJSON(res, 404, { error: 'User not found' });
      }
      users.delete(id);
      return sendJSON(res, 204, null);
    }

    // GET / - ヘルスチェック
    if (method === 'GET' && path === '/') {
      return sendJSON(res, 200, { 
        status: 'ok',
        timestamp: new Date().toISOString()
      });
    }

    // 404 Not Found
    sendJSON(res, 404, { error: 'Not Found' });
  } catch (error) {
    console.error('リクエスト処理エラー:', error);
    sendJSON(res, 500, { error: 'Internal Server Error' });
  }
}

// サーバー作成
const server = http.createServer(handleRequest);

// イベントハンドラー
server.on('error', (error) => {
  console.error('サーバーエラー:', error);
  process.exit(1);
});

server.on('clientError', (err, socket) => {
  if (socket.writable) {
    socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
  }
});

// Graceful Shutdown
function shutdown(signal) {
  console.log(`\n${signal} 受信: サーバーを停止します...`);
  server.close(() => {
    console.log('サーバー停止完了');
    process.exit(0);
  });
  server.closeIdleConnections();
  setTimeout(() => {
    console.log('強制終了');
    process.exit(1);
  }, 5000);
}

process.on('SIGTERM', () => shutdown('SIGTERM'));
process.on('SIGINT', () => shutdown('SIGINT'));

// サーバー起動
server.listen(PORT, HOST, () => {
  console.log(`サーバー起動: http://${HOST}:${PORT}`);
  console.log('Ctrl+C で停止');
});

このサーバーは以下のエンドポイントを提供します。

メソッド パス 説明
GET / ヘルスチェック
GET /api/users ユーザー一覧取得
GET /api/users/:id ユーザー詳細取得
POST /api/users ユーザー作成
DELETE /api/users/:id ユーザー削除

httpモジュール vs フレームワーク

Node.jsのhttpモジュールとExpressなどのフレームワークを比較します。

graph TD
    A[Node.js httpモジュール] --> B[メリット]
    A --> C[デメリット]
    
    B --> B1[依存関係なし]
    B --> B2[軽量]
    B --> B3[HTTPを深く理解できる]
    B --> B4[完全なカスタマイズ性]
    
    C --> C1[ルーティングを自作]
    C --> C2[ミドルウェア機構なし]
    C --> C3[開発工数が増加]
    C --> C4[セキュリティ対策を自作]
    
    D[Express/Fastify等] --> E[メリット]
    D --> F[デメリット]
    
    E --> E1[豊富なミドルウェア]
    E --> E2[ルーティング機能]
    E --> E3[開発効率が高い]
    E --> E4[コミュニティサポート]
    
    F --> F1[依存関係の管理]
    F --> F2[学習コスト]
    F --> F3[オーバーヘッド]

使い分けの指針

用途 推奨
学習・プロトタイプ httpモジュール
シンプルなAPI httpモジュール
マイクロサービス httpモジュール or Fastify
本格的なWebアプリ Express / NestJS
高パフォーマンス要件 Fastify

まとめ

この記事では、Node.jsのhttpモジュールを使用してWebサーバーを構築する方法を解説しました。

学習したポイントは以下のとおりです。

  • http.createServer()でHTTPサーバーを作成する方法
  • IncomingMessageオブジェクトからリクエスト情報を取得する方法
  • ServerResponseオブジェクトでレスポンスを制御する方法
  • ステータスコードとヘッダーの適切な設定方法
  • JSON/HTMLなど様々なレスポンス形式の返却方法
  • サーバーの起動とGraceful Shutdownの実装方法
  • エラーハンドリングのベストプラクティス

httpモジュールを理解することで、HTTPプロトコルの仕組みを深く理解できます。これはExpressやFastifyなどのフレームワークを使用する際にも役立つ知識となります。

参考リンク