MeWrite Docs

HTTP 408 Request Timeout

クライアントのリクエスト送信がタイムアウトした場合のエラー

概要

HTTP 408 Request Timeout は、クライアントがサーバーの待機時間内にリクエストを送信完了できなかった場合に返されるステータスコードです。504 Gateway Timeout とは異なり、クライアント側の送信遅延が原因です。

エラーメッセージ

408 Request Timeout
HTTP/1.1 408 Request Timeout
Connection: close
Content-Length: 0

原因

  1. 低速なネットワーク接続: アップロード速度が遅い
  2. 大きなリクエストボディ: ファイルアップロード等
  3. サーバーのタイムアウト設定: 短すぎる設定
  4. 接続の不安定: パケットロス、遅延
  5. Keep-Alive接続の期限切れ: アイドル状態が長い

解決策

1. サーバーのタイムアウト設定を調整

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Nginx
http {
    # クライアントボディ受信タイムアウト
    client_body_timeout 60s;

    # クライアントヘッダー受信タイムアウト
    client_header_timeout 60s;

    # Keep-Alive タイムアウト
    keepalive_timeout 65s;

    # 送信タイムアウト
    send_timeout 60s;
}
1
2
3
4
# Apache
Timeout 300
KeepAliveTimeout 15
RequestReadTimeout header=20-40,minrate=500 body=20-60,minrate=500

2. Node.js サーバー設定

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

const server = http.createServer((req, res) => {
  // リクエスト処理
});

// サーバータイムアウト設定
server.timeout = 120000; // 120秒
server.keepAliveTimeout = 65000; // 65秒
server.headersTimeout = 66000; // 66秒(keepAliveTimeoutより大きく)

server.listen(3000);
1
2
3
4
5
6
7
// Express
const express = require('express');
const app = express();

const server = app.listen(3000);
server.timeout = 120000;
server.keepAliveTimeout = 65000;

3. クライアント側のタイムアウト設定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Fetch API with AbortController
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 30000);

try {
  const response = await fetch('/api/data', {
    signal: controller.signal
  });
  clearTimeout(timeoutId);
} catch (error) {
  if (error.name === 'AbortError') {
    console.log('Request timed out');
  }
}

// Axios
const axios = require('axios');
axios.get('/api/data', { timeout: 30000 })
  .catch(error => {
    if (error.code === 'ECONNABORTED') {
      console.log('Request timed out');
    }
  });

4. 大きなファイルのアップロード対策

1
2
3
4
5
6
7
8
9
# Nginx - 大きなファイル対応
client_max_body_size 100M;
client_body_buffer_size 10M;
client_body_timeout 300s;

# proxy 経由の場合
proxy_read_timeout 300s;
proxy_connect_timeout 75s;
proxy_send_timeout 300s;
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// チャンクアップロード実装
async function uploadInChunks(file, chunkSize = 1024 * 1024) {
  const totalChunks = Math.ceil(file.size / chunkSize);

  for (let i = 0; i < totalChunks; i++) {
    const start = i * chunkSize;
    const end = Math.min(start + chunkSize, file.size);
    const chunk = file.slice(start, end);

    await fetch('/upload', {
      method: 'POST',
      headers: {
        'Content-Range': `bytes ${start}-${end - 1}/${file.size}`,
        'X-Chunk-Index': i,
        'X-Total-Chunks': totalChunks
      },
      body: chunk
    });
  }
}

5. リトライ機能の実装

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
async function fetchWithRetry(url, options = {}, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      const response = await fetch(url, {
        ...options,
        signal: AbortSignal.timeout(30000)
      });

      if (response.status === 408) {
        throw new Error('Request Timeout');
      }

      return response;
    } catch (error) {
      if (i === retries - 1) throw error;

      // 指数バックオフ
      await new Promise(resolve =>
        setTimeout(resolve, Math.pow(2, i) * 1000)
      );
    }
  }
}

408 vs 504 の違い

エラー原因発生箇所
408 Request Timeoutクライアントの送信遅延オリジンサーバー
504 Gateway Timeoutバックエンドの応答遅延プロキシ/ゲートウェイ

HTTP の他のエラー

最終更新: 2026-01-27