---
title: SDKミドルウェア
url: https://platform.claude.com/docs/ja/cli-sdks-libraries/middleware
description: SDKのリクエストとレスポンスをインターセプトして変更します。
---

Claude SDKは、リクエストが送信される前とレスポンスを受信した後にコードを実行できる「middleware」（ミドルウェア）フック（「interceptor」（インターセプター）とも呼ばれます）を提供しています。ミドルウェアは、ロギング、カスタムリトライ、リクエストへの注釈付け、拒否時のフォールバック処理など、横断的な関心事に使用します。

```mermaid
sequenceDiagram
    accTitle: How a request and its response pass through middleware
    accDescr: Your code sends the request to Middleware A. Middleware A calls next(request) to pass it to Middleware B, and Middleware B calls next(request) to pass it to the SDK core. The SDK core sends the HTTP request to the Claude API and receives the HTTP response. The response returns through Middleware B, then Middleware A, to your code.
    autonumber
    participant App as Your code
    participant M1 as Middleware A
    participant M2 as Middleware B
    participant Core as SDK core
    participant API as Claude API
    App->>M1: request
    M1->>M2: next(request)
    M2->>Core: next(request)
    Core->>API: HTTP request
    API-->>Core: HTTP response
    Core-->>M2: response
    M2-->>M1: response
    M1-->>App: response
```

各ミドルウェアは、`next()` を呼び出す前にリクエストを、`next()` が返った後にレスポンスを検査または置き換えることができます。

## ミドルウェアの登録

各ミドルウェアは、送信されるリクエストと次のハンドラーを受け取る関数です。`call_next(request)` (typescript: `next(request)`; csharp: `next(request, cancellationToken)`; go: `next(req)`; java: `nextClient.execute(request, requestOptions)`; php: `$next($request)`; ruby: `call_next.call(request)`)を呼び出してリクエストをチェーンの残りの部分（これが最後のミドルウェアの場合はSDKコアに直接）に転送し、そのレスポンスを返します。その呼び出しより前にあるものはすべて送信時に実行され、後にあるものはすべて戻り時に実行されます。

<CodeGroup exclude="shell">
  ```python Python
  def logging_middleware(request: APIRequest, call_next: CallNext) -> APIResponse[Any]:
      # リクエストの前
      print(f"-> {request.method} {request.url}")

      # リクエストをチェーンの残りの部分に転送する
      response = call_next(request)

      # リクエストの後
      print(f"<- {response.status_code}")

      return response


  client = Anthropic(middleware=[logging_middleware])
  ```

  ```typescript TypeScript
  import type { Middleware } from "@anthropic-ai/sdk";

  const loggingMiddleware: Middleware = async (request, next, ctx) => {
    // リクエストの前
    ctx.logger.debug("->", request.method, request.url);

    // リクエストをチェーンの残りに転送する
    const response = await next(request);

    // リクエストの後
    ctx.logger.debug("<-", response.status, request.url);

    return response;
  };

  const client = new Anthropic({ middleware: [loggingMiddleware] });
  ```

  ```csharp C#
  AnthropicClient client = new()
  {
      Handlers =
      [
          Handler.Create(async (request, next, cancellationToken) =>
          {
              // リクエストの前
              Console.WriteLine($"Sending {request.Method} {request.RequestUri}");

              // リクエストを次のハンドラーに転送
              var response = await next(request, cancellationToken);

              // リクエストの後
              Console.WriteLine($"Received {(int)response.StatusCode}");

              return response;
          }),
      ],
  };
  ```

  ```go Go
  client := anthropic.NewClient(
  	option.WithMiddleware(func(req *http.Request, next option.MiddlewareNext) (*http.Response, error) {
  		// リクエストの前
  		start := time.Now()
  		slog.Info("sending request", "method", req.Method, "url", req.URL)

  		// リクエストをチェーンの残りに転送する
  		res, err := next(req)
  		if err != nil {
  			return nil, err
  		}

  		// リクエストの後
  		slog.Info("received response", "status", res.StatusCode, "duration", time.Since(start))

  		return res, nil
  	}),
  )
  ```

  ```java Java
  AnthropicClient client = AnthropicOkHttpClient.builder()
      .fromEnv()
      .addInterceptor(Interceptor.syncOnly((nextClient, request, requestOptions) -> {
          // リクエストの前
          IO.println(request.method() + " /" + String.join("/", request.pathSegments()));

          // リクエストを次のハンドラーに転送する
          HttpResponse response = nextClient.execute(request, requestOptions);

          // リクエストの後
          IO.println(response.statusCode());

          return response;
      }))
      .build();
  ```

  ```php PHP
  $loggingMiddleware = function (RequestInterface $request, callable $next): ResponseInterface {
      // リクエストの前
      error_log("-> {$request->getMethod()} {$request->getUri()}");

      // リクエストをチェーンの残りに転送する
      $response = $next($request);

      // リクエストの後
      error_log("<- {$response->getStatusCode()}");

      return $response;
  };

  $client = new Client(requestOptions: ['middleware' => [$loggingMiddleware]]);
  ```

  ```ruby Ruby
  logging_middleware = lambda do |request, call_next|
    # リクエストの前
    puts "-> #{request.method.upcase} #{request.url}"

    # リクエストをチェーンの残りに転送する
    response = call_next.call(request)

    # リクエストの後
    puts "<- #{response.status}"

    response
  end

  client = Anthropic::Client.new(middleware: [logging_middleware])
  ```
</CodeGroup>

## ミドルウェアの順序

複数のミドルウェアを登録すると、指定した順序で適用されます。最初のミドルウェアの「前」のコードが最初に実行され、その「後」のコードが最後に実行されます。クライアントに登録されたミドルウェアは、リクエストごとのオプションとして渡されたミドルウェアより前に実行されます。

Go SDKでは、`option.WithMiddleware` を繰り返し呼び出すと連結されます（クライアントが先、次にメソッド）。他のSDKでは配列を渡します。後のエントリほど内側をラップします。

## HTTPクライアントの置き換え

SDKはカスタムHTTPクライアント（プロキシ設定、カスタムTLS、またはコネクションプーリング用）も受け付けます。SDKクライアントごとに使用されるHTTPクライアントは1つだけで、設定するとデフォルトが置き換えられます。カスタムHTTPクライアントは、すべてのミドルウェアが実行された後にリクエストを受け取ります。

## 組み込みミドルウェア

SDKには、Claudeが拒否したリクエスト（`stop_reason: "refusal"`）をフォールバックモデルで自動的にリトライする拒否フォールバックミドルウェアが付属しています。[拒否とフォールバック](https://platform.claude.com/docs/ja/build-with-claude/refusals-and-fallback)には安全性分類器がリクエストを拒否する可能性のあるモデルが記載されており、[フォールバックモデルでの検出とリトライ](https://platform.claude.com/docs/ja/build-with-claude/refusals-and-fallback#client-side-fallback)ではセットアップと言語ごとの例を説明しています。
