Skip to content

Commit acbcd4a

Browse files
[kafka_consumer] URL-encode subject names in Schema Registry API calls (DataDog#22924)
* [kafka_consumer] URL-encode subject names in Schema Registry API calls Subjects containing slashes (e.g. Protobuf references like `google/protobuf/timestamp.proto`) were causing 404 errors because the slashes were interpreted as URL path separators instead of being encoded as `%2F`. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * [kafka_consumer] Add changelog entry for URL-encoding fix Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 44d02d1 commit acbcd4a

3 files changed

Lines changed: 33 additions & 2 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
URL-encode subject names in Schema Registry API calls to fix 404 errors for Protobuf reference subjects containing slashes.

kafka_consumer/datadog_checks/kafka_consumer/cluster_metadata.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import time
1111
from concurrent.futures import ThreadPoolExecutor, as_completed
1212
from typing import TypedDict
13+
from urllib.parse import quote
1314

1415
from confluent_kafka.admin import ConfigResource, ResourceType
1516

@@ -163,13 +164,15 @@ def _get_schema_registry_subjects(self):
163164
def _get_schema_registry_versions(self, subject: str) -> list[int]:
164165
"""Fetch the list of version numbers for a subject (lightweight call)."""
165166
base_url = self.config._collect_schema_registry
166-
response = self.http.get(f"{base_url}/subjects/{subject}/versions")
167+
encoded_subject = quote(subject, safe='')
168+
response = self.http.get(f"{base_url}/subjects/{encoded_subject}/versions")
167169
response.raise_for_status()
168170
return response.json()
169171

170172
def _get_schema_registry_latest_version(self, subject):
171173
base_url = self.config._collect_schema_registry
172-
response = self.http.get(f"{base_url}/subjects/{subject}/versions/latest")
174+
encoded_subject = quote(subject, safe='')
175+
response = self.http.get(f"{base_url}/subjects/{encoded_subject}/versions/latest")
173176
response.raise_for_status()
174177
return response.json()
175178

kafka_consumer/tests/test_cluster_metadata.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1324,3 +1324,30 @@ def test_cluster_metadata_with_cluster_id_override(check, dd_run_check, aggregat
13241324
if 'kafka_cluster_id' in payload:
13251325
assert payload['kafka_cluster_id'] == 'my-override-id'
13261326
assert payload['original_kafka_cluster_id'] == 'auto-detected-id'
1327+
1328+
1329+
def test_schema_registry_url_encodes_subject_names(check):
1330+
"""Subjects with slashes (e.g. Protobuf references) must be URL-encoded in API calls."""
1331+
instance = {
1332+
'kafka_connect_str': 'localhost:9092',
1333+
'schema_registry_url': 'http://localhost:8081',
1334+
}
1335+
kafka_check = check(instance)
1336+
collector = kafka_check.metadata_collector
1337+
1338+
mock_response = mock.MagicMock()
1339+
mock_response.json.return_value = [1]
1340+
mock_response.raise_for_status.return_value = None
1341+
collector.http = mock.MagicMock()
1342+
collector.http.get.return_value = mock_response
1343+
1344+
subject = 'google/protobuf/timestamp.proto'
1345+
1346+
collector._get_schema_registry_versions(subject)
1347+
collector.http.get.assert_called_with('http://localhost:8081/subjects/google%2Fprotobuf%2Ftimestamp.proto/versions')
1348+
1349+
collector.http.get.reset_mock()
1350+
collector._get_schema_registry_latest_version(subject)
1351+
collector.http.get.assert_called_with(
1352+
'http://localhost:8081/subjects/google%2Fprotobuf%2Ftimestamp.proto/versions/latest'
1353+
)

0 commit comments

Comments
 (0)