ソースを参照

Add support for http.extraHeader configuration

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 4 ヶ月 前
コミット
d913031178
3 ファイル変更53 行追加0 行削除
  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: