24 — curl_cffi: keep proxy credentials on the tunnel, off the origin - #20
Open
MirjamOdile wants to merge 3 commits into
Open
24 — curl_cffi: keep proxy credentials on the tunnel, off the origin#20MirjamOdile wants to merge 3 commits into
MirjamOdile wants to merge 3 commits into
Conversation
CURL_CFFI_ENABLED plus an authenticating proxy could never work together: Scrapy's HttpProxyMiddleware strips the credentials out of meta['proxy'] into a Proxy-Authorization header, but curl_cffi authenticates from the URL only, so every request got 407. The same header was then forwarded to the origin server, leaking the proxy credentials to the site. proxies_from_request() now decodes that header back into the proxy URL when the URL has no credentials of its own, and the handler pops Proxy-Authorization from the outgoing request headers. Adds the request write-up (docs/requests/24).
Pins both halves of the fix: credentials are restored into the proxy URL from the Proxy-Authorization header (and a URL that already carries its own credentials wins), and the header is dropped from the outgoing request so it never reaches the origin server.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What was broken:
CURL_CFFI_ENABLED: trueand an authenticating proxy could never be used together — every single request failed with407 Proxy Authentication Required. Both settings are documented, both work on their own, and the combination has never worked. Worse, the proxy's username and password were being sent onward to every site we crawled. Observed in production on a site that blocks plain HTTP from the server IP and blocks curl_cffi without a proxy — so only the broken combination could have worked: the crawl enqueued 486 URLs and scraped 0 items, and even the robots.txt/llms.txt compliance witnesses failed.What it does now: the credentials are put back where curl_cffi looks for them, and removed from where they don't belong. Proxied curl_cffi crawls authenticate normally, and the crawled site never sees the proxy credentials.
Details
Three components hand the proxy along, and the credentials fell through the gap:
SmartProxyMiddlewaresetsrequest.meta['proxy']to the full credentialed URL.HttpProxyMiddlewarethen strips those credentials out ofmeta['proxy']and moves them into aProxy-Authorizationheader — the contract its own downloader honours.proxies_from_request()readmeta['proxy']only — now credential-free — and handed it to curl_cffi, which authenticates from the URL and ignores that header. The proxy answered 407.handlers/curl_cffi_handler.py,proxies_from_request(): whenmeta['proxy']carries no credentials but aProxy-Authorizationheader is present, decode the Basic payload and put the credentials back into the URL. Guarded on"@" not in proxy, so a proxy URL that still has its own credentials is left untouched.handlers/curl_cffi_handler.py,_fetch_sync(): dropProxy-Authorizationfrom the headers sent to the origin server. The handler built its outgoing headers fromrequest.headers, which still contained it — so the credentials went to every site on curl_cffi crawls. They belong to the CONNECT tunnel, not the target.docs/requests/24-curl-cffi-proxy-auth.md.Behavior changes
CURL_CFFI_ENABLED+ proxy crawls now work instead of failing 407 on every request. On the affected site: 407 count 0, robots.txt captured, items extracting, 403 rate 26% (was 42%).meta['proxy']absent still returnsNone, exactly as before.inspectwas never affected: it calls the transport directly with the credentialed URL and never enters the middleware chain. That asymmetry is what made this expensive to diagnose — the same site "works in inspect, fails in crawl".Verified
5 unit tests (
tests/unit/test_curl_cffi_proxy.py, 3 new): credentials restored from the header, a URL carrying its own credentials left alone,Proxy-Authorizationabsent from the outgoing request while other headers still go out, plus the two pre-existing meta-proxy cases. Full gate green againstmain(black, flake8, 473 unit tests).