---
title: SDK 中介軟體
url: https://platform.claude.com/docs/zh-TW/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>

## 中介軟體順序

當您註冊多個中介軟體時，它們會依照給定的順序套用：第一個中介軟體的「before」程式碼最先執行，而其「after」程式碼最後執行。在用戶端上註冊的中介軟體會先於以單次請求選項傳入的中介軟體執行。

在 Go SDK 中，重複呼叫 `option.WithMiddleware` 會進行串接（先是用戶端，然後是方法）。在其他 SDK 中，請傳入一個陣列；較後面的項目會包裹在內層。

## 替換 HTTP 用戶端

SDK 也接受自訂的 HTTP 用戶端（用於代理伺服器設定、自訂 TLS 或連線池）。每個 SDK 用戶端只會使用一個 HTTP 用戶端；設定它會取代預設值。自訂 HTTP 用戶端會在所有中介軟體執行完畢後接收請求。

## 內建中介軟體

SDK 內建一個拒絕備援中介軟體，會自動在備援模型上重試 Claude 拒絕的請求（`stop_reason: "refusal"`）。[拒絕與備援](https://platform.claude.com/docs/zh-TW/build-with-claude/refusals-and-fallback)列出了其安全分類器可能拒絕請求的模型，而[偵測並在備援模型上重試](https://platform.claude.com/docs/zh-TW/build-with-claude/refusals-and-fallback#client-side-fallback)則涵蓋設定方式以及各語言的範例。
