Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions google/genai/_api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -988,7 +988,7 @@ def _ensure_httpx_ssl_ctx(
else None
)

if not ctx:
if ctx is None:
# Initialize the SSL context for the httpx client.
# Unlike requests, the httpx package does not automatically pull in the
# environment variables SSL_CERT_FILE or SSL_CERT_DIR. They need to be
Expand All @@ -1000,7 +1000,7 @@ def _ensure_httpx_ssl_ctx(

def _maybe_set(
args: Optional[_common.StringDict],
ctx: ssl.SSLContext,
ctx,
) -> _common.StringDict:
"""Sets the SSL context in the client args if not set.

Expand All @@ -1013,7 +1013,7 @@ def _maybe_set(
Returns:
The client args with the SSL context included.
"""
if not args or not args.get(verify):
if not args or args.get(verify) is None:
args = (args or {}).copy()
args[verify] = ctx
# Drop the args that isn't used by the httpx client.
Expand Down Expand Up @@ -1044,15 +1044,15 @@ def _ensure_aiohttp_ssl_ctx(options: HttpOptions) -> _common.StringDict:
async_args = options.async_client_args
ctx = async_args.get(verify) if async_args else None

if not ctx:
if ctx is None:
ctx = ssl.create_default_context(
cafile=os.environ.get('SSL_CERT_FILE', certifi.where()),
capath=os.environ.get('SSL_CERT_DIR'),
)

def _maybe_set(
args: Optional[_common.StringDict],
ctx: ssl.SSLContext,
ctx,
) -> _common.StringDict:
"""Sets the SSL context in the client args if not set.

Expand All @@ -1065,7 +1065,7 @@ def _maybe_set(
Returns:
The client args with the SSL context included.
"""
if not args or not args.get(verify):
if not args or args.get(verify) is None:
args = (args or {}).copy()
args[verify] = ctx
# Drop the args that isn't in the aiohttp RequestOptions.
Expand Down Expand Up @@ -1097,7 +1097,7 @@ def _ensure_websocket_ssl_ctx(options: HttpOptions) -> _common.StringDict:
async_args = options.async_client_args
ctx = async_args.get(verify) if async_args else None

if not ctx:
if ctx is None:
# Initialize the SSL context for the httpx client.
# Unlike requests, the aiohttp package does not automatically pull in the
# environment variables SSL_CERT_FILE or SSL_CERT_DIR. They need to be
Expand All @@ -1110,7 +1110,7 @@ def _ensure_websocket_ssl_ctx(options: HttpOptions) -> _common.StringDict:

def _maybe_set(
args: Optional[_common.StringDict],
ctx: ssl.SSLContext,
ctx,
) -> _common.StringDict:
"""Sets the SSL context in the client args if not set.

Expand All @@ -1123,7 +1123,7 @@ def _maybe_set(
Returns:
The client args with the SSL context included.
"""
if not args or not args.get(verify):
if not args or args.get(verify) is None:
args = (args or {}).copy()
args[verify] = ctx
# Drop the args that isn't in the aiohttp RequestOptions.
Expand Down
36 changes: 36 additions & 0 deletions google/genai/tests/client/test_http_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,39 @@ def test_base_url_resource_scope_not_set_by_default():
def test_retry_options_not_set_by_default():
options = types.HttpOptions()
assert options.retry_options is None


def test_ensure_httpx_ssl_ctx_preserves_verify_false():
"""verify=False in client_args must not be overridden by the default SSL context."""
options = types.HttpOptions(client_args={'verify': False})
client_args, _ = _api_client.BaseApiClient._ensure_httpx_ssl_ctx(options)
assert client_args.get('verify') is False


def test_ensure_httpx_ssl_ctx_preserves_verify_false_async():
"""verify=False in async_client_args must not be overridden."""
options = types.HttpOptions(async_client_args={'verify': False})
_, async_client_args = _api_client.BaseApiClient._ensure_httpx_ssl_ctx(options)
assert async_client_args.get('verify') is False


def test_ensure_httpx_ssl_ctx_sets_default_ctx_when_absent():
"""When verify is absent, a default SSLContext is injected."""
import ssl
options = types.HttpOptions()
client_args, _ = _api_client.BaseApiClient._ensure_httpx_ssl_ctx(options)
assert isinstance(client_args.get('verify'), ssl.SSLContext)


def test_ensure_aiohttp_ssl_ctx_preserves_ssl_false():
"""ssl=False in async_client_args must not be overridden."""
options = types.HttpOptions(async_client_args={'ssl': False})
result = _api_client.BaseApiClient._ensure_aiohttp_ssl_ctx(options)
assert result.get('ssl') is False


def test_ensure_websocket_ssl_ctx_preserves_ssl_false():
"""ssl=False in async_client_args must not be overridden for WebSocket."""
options = types.HttpOptions(async_client_args={'ssl': False})
result = _api_client.BaseApiClient._ensure_websocket_ssl_ctx(options)
assert result.get('ssl') is False
Loading