---
title: Middleware в SDK
url: https://platform.claude.com/docs/ru/cli-sdks-libraries/middleware
description: Перехват и изменение запросов и ответов SDK.
---

Claude SDK предоставляет хук «middleware» (промежуточное ПО), или «interceptor» (перехватчик), который позволяет выполнять код до отправки запроса и после получения ответа. Используйте middleware для сквозных задач, таких как логирование, пользовательские повторные попытки, аннотирование запросов и обработка резервного переключения при отказах.

```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
```

Каждое middleware может проверять или заменять запрос перед вызовом `next()`, а также ответ после возврата из `next()`.

## Регистрация middleware

Каждое middleware — это функция, которая получает исходящий запрос и следующий обработчик. Вызовите `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, если это последнее middleware), и верните его ответ. Всё, что находится до этого вызова, выполняется на пути туда; всё, что после, — на обратном пути.

<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>

## Порядок выполнения middleware

Когда вы регистрируете несколько middleware, они применяются в указанном порядке: код «до» первого middleware выполняется первым, а его код «после» — последним. Middleware, зарегистрированное на клиенте, выполняется раньше middleware, переданного в качестве параметра отдельного запроса.

В Go SDK повторные вызовы `option.WithMiddleware` объединяются (сначала клиентские, затем уровня метода). В остальных SDK передавайте массив; более поздние элементы оборачивают внутренние.

## Замена HTTP-клиента

SDK также принимает пользовательский HTTP-клиент (для настройки прокси, пользовательского TLS или пула соединений). Для каждого клиента SDK используется только один HTTP-клиент; его установка заменяет клиент по умолчанию. Пользовательский HTTP-клиент получает запросы после выполнения всех middleware.

## Встроенное middleware

SDK поставляется с middleware резервного переключения при отказах, которое автоматически повторяет запрос, отклонённый Claude (`stop_reason: "refusal"`), на резервной модели. В разделе [Отказы и резервная обработка](https://platform.claude.com/docs/ru/build-with-claude/refusals-and-fallback) перечислены модели, классификаторы безопасности которых могут отклонять запросы, а в разделе [Обнаружение и повтор на резервной модели](https://platform.claude.com/docs/ru/build-with-claude/refusals-and-fallback#client-side-fallback) описаны настройка и примеры для каждого языка.
