diff --git a/google/genai/_api_client.py b/google/genai/_api_client.py index e6202815e..6bb0b03be 100644 --- a/google/genai/_api_client.py +++ b/google/genai/_api_client.py @@ -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 @@ -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. @@ -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. @@ -1044,7 +1044,7 @@ 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'), @@ -1052,7 +1052,7 @@ def _ensure_aiohttp_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. @@ -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. @@ -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 @@ -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. @@ -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. diff --git a/google/genai/tests/client/test_http_options.py b/google/genai/tests/client/test_http_options.py index e27808142..f49a996a7 100644 --- a/google/genai/tests/client/test_http_options.py +++ b/google/genai/tests/client/test_http_options.py @@ -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