MethodSwitchingClient class

A client wrapper that dynamically routes requests between HTTP clients based on request type and content.

This client is useful when different requests should take different paths, such as AI requests, file uploads, streamed requests, or any request that should bypass interceptors.

It provides a single entry point that routes each request to the most appropriate underlying client at runtime.

The default routing behavior stays lightweight:

  • http.StreamedRequest uses the plain client
  • Gemini SSE-style requests use the plain client
  • OpenAI and Anthropic streaming requests also use the plain client when their JSON body contains "stream": true

If you only need simple per-request routing, pass useDefaultClientWhen at construction time. This callback has the highest priority and is a convenient way to override the default routing behavior.

If you need finer-grained control, extend this class and override shouldUseDefaultClient. That lets you implement custom routing based on the request method, URL, headers, or body content.

This client is especially useful when:

  • some requests should keep interceptor behavior
  • some requests must bypass interceptors, such as long-lived connections, SSE, or streaming uploads
  • different third-party APIs need different HTTP client paths

Example:

import 'dart:io';

import 'package:basic_http_interceptor/basic_http_interceptor.dart';
import 'package:googleai_dart/googleai_dart.dart';
import 'package:http/io_client.dart';
import 'package:logging/logging.dart';

final logger = Logger('google-ai');

final proxy = {
  'no_proxy': 'localhost,127.0.0.1,::1',
  'https_proxy': 'https://127.0.0.1:7890/',
  'http_proxy': 'http://127.0.0.1:7890/',
  'all_proxy': 'socks5://127.0.0.1:7891/',
};

final interceptedClient = interceptedClient(
  proxy: proxy,
  interceptors: [
    InterceptorLogger(logger, true),
  ],
);

final defaultClient = IOClient(
  HttpClient()
    ..findProxy = (url) =>
        HttpClient.findProxyFromEnvironment(url, environment: proxy),
);

final client = MethodSwitchingClient(
  interceptedClient,
  defaultClient,
  useDefaultClientWhen: (request) {
    return request.url.host.contains('api.openai.com') ||
        request.url.host.contains('api.anthropic.com');
  },
);

final gaiClient = GoogleAIClient(
  httpClient: client,
  config: GoogleAIConfig.googleAI(
    authProvider: ApiKeyProvider(apikey),
  ),
);

If you need even more control, extend this class and override shouldUseDefaultClient to fully customize the routing logic.

Constructors

MethodSwitchingClient(Client _intercepted, Client _defaulted, {bool useDefaultClientWhen(BaseRequest request)?})

Properties

defaultClient → Client
The plain client used for requests that should bypass interceptors.
no setter
hashCode int
The hash code for this object.
no setterinherited
interceptedClient → Client
The client that applies interceptors.
no setter
runtimeType Type
A representation of the runtime type of the object.
no setterinherited

Methods

close() → void
Closes the client and cleans up any resources associated with it.
delete(Uri url, {Map<String, String>? headers, Object? body, Encoding? encoding}) Future<Response>
Sends an HTTP DELETE request with the given headers to the given URL.
inherited
get(Uri url, {Map<String, String>? headers}) Future<Response>
Sends an HTTP GET request with the given headers to the given URL.
inherited
Sends an HTTP HEAD request with the given headers to the given URL.
inherited
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
patch(Uri url, {Map<String, String>? headers, Object? body, Encoding? encoding}) Future<Response>
Sends an HTTP PATCH request with the given headers and body to the given URL.
inherited
post(Uri url, {Map<String, String>? headers, Object? body, Encoding? encoding}) Future<Response>
Sends an HTTP POST request with the given headers and body to the given URL.
inherited
put(Uri url, {Map<String, String>? headers, Object? body, Encoding? encoding}) Future<Response>
Sends an HTTP PUT request with the given headers and body to the given URL.
inherited
read(Uri url, {Map<String, String>? headers}) Future<String>
Sends an HTTP GET request with the given headers to the given URL and returns a Future that completes to the body of the response as a String.
inherited
readBytes(Uri url, {Map<String, String>? headers}) Future<Uint8List>
Sends an HTTP GET request with the given headers to the given URL and returns a Future that completes to the body of the response as a list of bytes.
inherited
send(BaseRequest request) Future<StreamedResponse>
Sends an HTTP request and asynchronously returns the response.
shouldUseDefaultClient(BaseRequest request) bool
Returns true when request should be sent through defaultClient.
toString() String
A string representation of this object.
inherited

Operators

operator ==(Object other) bool
The equality operator.
inherited