From 00ff7b13f1d26bf9862131e1f21da0067647cec8 Mon Sep 17 00:00:00 2001 From: Burak Eyler Date: Wed, 23 Sep 2026 15:44:59 +0300 Subject: [PATCH] fix: do not mutate caller-provided client_kwargs in LinkContentFetcher Signed-off-by: Burak Eyler Co-Authored-By: Claude Opus 5 --- haystack/components/fetchers/link_content.py | 3 ++- ...-fetcher-copies-client-kwargs-3e9a71c05d24bf18.yaml | 6 ++++++ test/components/fetchers/test_link_content_fetcher.py | 10 ++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/link-content-fetcher-copies-client-kwargs-3e9a71c05d24bf18.yaml diff --git a/haystack/components/fetchers/link_content.py b/haystack/components/fetchers/link_content.py index 172c8b7afb7..2933ecaf6de 100644 --- a/haystack/components/fetchers/link_content.py +++ b/haystack/components/fetchers/link_content.py @@ -143,7 +143,8 @@ def __init__( self.retry_attempts = retry_attempts self.timeout = timeout self.http2 = http2 - self.client_kwargs = client_kwargs or {} + # Copy so that applying the defaults below does not change the caller's dictionary. + self.client_kwargs = dict(client_kwargs or {}) self.request_headers = request_headers or {} # Configure default client settings diff --git a/releasenotes/notes/link-content-fetcher-copies-client-kwargs-3e9a71c05d24bf18.yaml b/releasenotes/notes/link-content-fetcher-copies-client-kwargs-3e9a71c05d24bf18.yaml new file mode 100644 index 00000000000..eb251393acf --- /dev/null +++ b/releasenotes/notes/link-content-fetcher-copies-client-kwargs-3e9a71c05d24bf18.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + `LinkContentFetcher` no longer adds its `timeout` and `follow_redirects` defaults to the `client_kwargs` + dictionary passed by the caller. The dictionary is copied before the defaults are applied, so sharing one + HTTP-client configuration between components is safe. diff --git a/test/components/fetchers/test_link_content_fetcher.py b/test/components/fetchers/test_link_content_fetcher.py index 33e21452fb3..ca1d354e690 100644 --- a/test/components/fetchers/test_link_content_fetcher.py +++ b/test/components/fetchers/test_link_content_fetcher.py @@ -80,6 +80,16 @@ def test_init_with_params(self): assert "verify" in fetcher.client_kwargs assert fetcher.client_kwargs["verify"] is False + def test_init_does_not_mutate_client_kwargs(self): + """The caller's dictionary must not pick up the component's defaults.""" + client_kwargs = {"headers": {"X-Request-ID": "example"}} + + fetcher = LinkContentFetcher(timeout=10, client_kwargs=client_kwargs) + + assert client_kwargs == {"headers": {"X-Request-ID": "example"}} + assert fetcher.client_kwargs["timeout"] == 10 + assert fetcher.client_kwargs["follow_redirects"] is True + def test_run_text(self): """Test fetching text content""" correct_response = b"Example test response"