Sfoglia il codice sorgente

Add support for http.extraHeader configuration (#1774)

This allows passing additional HTTP headers to the server when
communicating over HTTP(S), following Git's standard configuration
pattern. Users can set single or multiple headers via:

  git config --add http.extraHeader "Authorization: Bearer token"
  git config --add http.extraHeader "X-Custom-Header: value"

The headers are parsed from the config and applied to all HTTP requests
made by the client.

Fixes #1769
Jelmer Vernooij 5 mesi fa
parent
commit
e5ab06be71
3 ha cambiato i file con 53 aggiunte e 0 eliminazioni
  1. 4 0
      NEWS
  2. 15 0
      dulwich/client.py
  3. 34 0
      tests/test_client.py

+ 4 - 0
NEWS

@@ -30,6 +30,10 @@
    unchanged files from appearing as unstaged in status.
    (Jelmer Vernooij, #1770)
 
+ * Add support for ``http.extraHeader`` configuration to pass additional HTTP
+   headers to the server when communicating over HTTP(S).
+   (Jelmer Vernooij, #1769)
+
 0.24.1	2025-08-01
 
  * Require ``typing_extensions`` on Python 3.10.

+ 15 - 0
dulwich/client.py

@@ -2850,6 +2850,19 @@ def default_urllib3_manager(
 
     headers = {"User-agent": user_agent}
 
+    # Check for extra headers in config
+    if config is not None:
+        try:
+            # Git allows multiple http.extraHeader entries
+            extra_headers = config.get_multivar(b"http", b"extraHeader")
+            for extra_header in extra_headers:
+                if extra_header and b": " in extra_header:
+                    # Parse the header (format: "Header-Name: value")
+                    header_name, header_value = extra_header.split(b": ", 1)
+                    headers[header_name.decode("utf-8")] = header_value.decode("utf-8")
+        except KeyError:
+            pass
+
     kwargs = {
         "ca_certs": ca_certs,
     }
@@ -3425,12 +3438,14 @@ class Urllib3HttpGitClient(AbstractHttpGitClient):
         username=None,
         password=None,
         timeout=None,
+        extra_headers=None,
         **kwargs,
     ) -> None:
         """Initialize Urllib3HttpGitClient."""
         self._username = username
         self._password = password
         self._timeout = timeout
+        self._extra_headers = extra_headers or {}
 
         if pool_manager is None:
             self.pool_manager = default_urllib3_manager(

+ 34 - 0
tests/test_client.py

@@ -1589,6 +1589,40 @@ class HttpGitClientTests(TestCase):
         c = HttpGitClient(url, config=config, timeout=15)
         self.assertEqual(c._timeout, 15)
 
+    def test_http_extra_headers_from_config(self) -> None:
+        """Test that http.extraHeader config values are applied."""
+        from dulwich.config import ConfigDict
+
+        url = "https://github.com/jelmer/dulwich"
+        config = ConfigDict()
+        # Set a single extra header
+        config.set((b"http",), b"extraHeader", b"X-Custom-Header: test-value")
+
+        c = HttpGitClient(url, config=config)
+        # Check that the header was added to the pool manager
+        self.assertIn("X-Custom-Header", c.pool_manager.headers)
+        self.assertEqual(c.pool_manager.headers["X-Custom-Header"], "test-value")
+
+    def test_http_multiple_extra_headers_from_config(self) -> None:
+        """Test that multiple http.extraHeader config values are applied."""
+        from dulwich.config import ConfigDict
+
+        url = "https://github.com/jelmer/dulwich"
+        config = ConfigDict()
+        # Set multiple extra headers
+        config.set((b"http",), b"extraHeader", b"X-Header-1: value1")
+        config.add((b"http",), b"extraHeader", b"X-Header-2: value2")
+        config.add((b"http",), b"extraHeader", b"Authorization: Bearer token123")
+
+        c = HttpGitClient(url, config=config)
+        # Check that all headers were added to the pool manager
+        self.assertIn("X-Header-1", c.pool_manager.headers)
+        self.assertEqual(c.pool_manager.headers["X-Header-1"], "value1")
+        self.assertIn("X-Header-2", c.pool_manager.headers)
+        self.assertEqual(c.pool_manager.headers["X-Header-2"], "value2")
+        self.assertIn("Authorization", c.pool_manager.headers)
+        self.assertEqual(c.pool_manager.headers["Authorization"], "Bearer token123")
+
 
 class TCPGitClientTests(TestCase):
     def test_get_url(self) -> None: