From a2f786b6019fe177795c823423647caf727aa395 Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Thu, 13 Aug 2026 16:51:57 +0700 Subject: [PATCH 1/2] fix: support ipv6 --- influxdb_client_3/__init__.py | 11 ++++--- influxdb_client_3/query/query_api.py | 3 +- tests/test_influxdb_client_3.py | 46 ++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/influxdb_client_3/__init__.py b/influxdb_client_3/__init__.py index 1c451b64..b5b3c8f2 100644 --- a/influxdb_client_3/__init__.py +++ b/influxdb_client_3/__init__.py @@ -1,7 +1,6 @@ -import multiprocessing - import importlib.util import json +import multiprocessing import os import urllib.parse from typing import Any, List, Literal, Optional, TYPE_CHECKING @@ -209,7 +208,8 @@ def __init__( """ Initialize an InfluxDB client. - :param host: The hostname or IP address of the InfluxDB server. + :param host: The hostname or IP address of the InfluxDB server. IPv6 must be wrapped inside square brackets, + e.g. http://[2001:db8::1]:8086, and Zone IDs are not supported. :type host: str :param org: The InfluxDB organization name for operations. :type org: str @@ -306,10 +306,11 @@ def __init__( # Parse the host input parsed_url = urllib.parse.urlparse(host) + hostname = parsed_url.hostname if parsed_url.hostname else host + if "[" in parsed_url.netloc and "]" in parsed_url.netloc: + hostname = f"[{hostname}]" - # Determine the protocol (scheme), hostname, and port scheme = parsed_url.scheme if parsed_url.scheme else "https" - hostname = parsed_url.hostname if parsed_url.hostname else host port = parsed_url.port if parsed_url.port else 443 # Construct the clients using the parsed values diff --git a/influxdb_client_3/query/query_api.py b/influxdb_client_3/query/query_api.py index ad50293d..7dc615fe 100644 --- a/influxdb_client_3/query/query_api.py +++ b/influxdb_client_3/query/query_api.py @@ -156,7 +156,8 @@ def __init__(self, """ Initialize defaults. - :param connection_string: Flight/gRPC connection string + :param connection_string: Flight/gRPC connection string. IPv6 must be wrapped inside square brackets, + e.g. 'grpc+tcp://[2001:db8::1]:8086', and Zone IDs are not supported. :param token: access token :param flight_client_options: Flight client options """ diff --git a/tests/test_influxdb_client_3.py b/tests/test_influxdb_client_3.py index ebbdd5a6..1b9f2f5b 100644 --- a/tests/test_influxdb_client_3.py +++ b/tests/test_influxdb_client_3.py @@ -62,6 +62,52 @@ def test_token_auth_scheme_default(self): ) self.assertEqual(client.default_header['Authorization'], "Token my_token") + def test_parse_addresses(self): + tests = [ + {"url": "http://192.168.0.5/db", "expect": "http://192.168.0.5:443"}, + {"url": "http://192.168.0.1:80", "expect": "http://192.168.0.1:80"}, + {"url": "https://[2001:db8::1]", "expect": "https://[2001:db8::1]:443"}, + {"url": "https://[2001:db8::1]:8086/influx", "expect": "https://[2001:db8::1]:8086"}, + {"url": "http://[2001:db8::1]:15000?token=my-token", "expect": "http://[2001:db8::1]:15000"}, + {"url": "http://[2001:db8::1]", "expect": "http://[2001:db8::1]:443"}, + {"url": "http://[2001:db8:a0b:12f0::1]:80", "expect": "http://[2001:db8:a0b:12f0::1]:80"}, + {"url": "http://example.com", "expect": "http://example.com:443"}, + {"url": "http://example.com:3000", "expect": "http://example.com:3000"}, + ] + for test in tests: + client = InfluxDBClient3( + host=test["url"], + org="my_org", + database="my_db", + token="my_token", + ) + self.assertEqual(client.base_url, test["expect"]) + + @patch('influxdb_client_3._QueryApi') + def test_ipv6_QueryApi(self, mock_query_api): + tests = [ + {"url": "https://[2001:db8::1]", "expect": "grpc+tls://[2001:db8::1]:443"}, + {"url": "https://[2001:db8::1]:8086/influx", "expect": "grpc+tls://[2001:db8::1]:8086"}, + {"url": "http://[2001:db8::1]:15000?token=my-token", "expect": "grpc+tcp://[2001:db8::1]:15000"}, + {"url": "http://[2001:db8::1]", "expect": "grpc+tcp://[2001:db8::1]:443"}, + {"url": "http://[2001:db8:a0b:12f0::1]:80", "expect": "grpc+tcp://[2001:db8:a0b:12f0::1]:80"}, + ] + for test in tests: + InfluxDBClient3( + host=test['url'], + org="my_org", + database="my_db", + token="my_token" + ) + mock_query_api.assert_called_with( + connection_string=test['expect'], + token="my_token", + flight_client_options=None, + proxy=None, + options=unittest.mock.ANY + ) + mock_query_api.reset_mock() + # test explicit token auth_scheme def test_token_auth_scheme_explicit(self): client = InfluxDBClient3( From e607ed8bd51068bff88c9796b0220f5dc22f9ee3 Mon Sep 17 00:00:00 2001 From: NguyenHoangSon96 Date: Fri, 14 Aug 2026 14:15:33 +0700 Subject: [PATCH 2/2] fix: support ipv6 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41908b4d..7431a1a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ## 0.21.0 [unreleased] +### Bug Fixes + +1. [#234](https://github.com/InfluxCommunity/influxdb3-python/pull/234): Add support for connecting to InfluxDB servers using IPv6 addresses. + - IPv6 addresses in server URLs must be enclosed in square brackets, for example, http://[2001:db8::1]:8086. + - IPv6 zone identifiers are not currently supported. + ### Breaking Changes 1. [#217](https://github.com/InfluxCommunity/influxdb3-python/pull/217): Makes the writing API simpler and more consistent with other v3 clients.