Build a :class:`~urllib.request.Request`, attaching auth when config matches. Uses the first matching entry from ``auth.json`` whose token resolves. Returns a plain request when no entry matches or the file doesn't exist.
(url: str, extra_headers: dict[str, str] | None = None)
| 96 | |
| 97 | |
| 98 | def build_request(url: str, extra_headers: dict[str, str] | None = None) -> urllib.request.Request: |
| 99 | """Build a :class:`~urllib.request.Request`, attaching auth when config matches. |
| 100 | |
| 101 | Uses the first matching entry from ``auth.json`` whose token resolves. |
| 102 | Returns a plain request when no entry matches or the file doesn't exist. |
| 103 | """ |
| 104 | headers: dict[str, str] = {} |
| 105 | if extra_headers: |
| 106 | # Strip Authorization from extra_headers to prevent bypass |
| 107 | headers.update({k: v for k, v in extra_headers.items() if k.lower() != "authorization"}) |
| 108 | # Auth headers applied last — cannot be overridden by extra_headers |
| 109 | entries = find_entries_for_url(url, _load_config()) |
| 110 | for entry in entries: |
| 111 | provider = get_provider(entry.provider) |
| 112 | if provider is None: |
| 113 | continue |
| 114 | token = provider.resolve_token(entry) |
| 115 | if token: |
| 116 | headers.update(provider.auth_headers(token, entry.auth)) |
| 117 | break |
| 118 | return urllib.request.Request(url, headers=headers) |
| 119 | |
| 120 | |
| 121 | def github_provider_hosts() -> tuple[str, ...]: |