Problem/Motivation
Ideally, Drupal core could enable persistent transport sharing for HTTP client requests. This allows requests to share connections, DNS, and TLS sessions across multiple PHP executions. For example, batch operations could continue a series of HTTP client requests to the same host without a DNS lookup, reconnecting and renegotiating TLS.
Steps to reproduce
Time the HTTP client requests in e.g. Update Status module, and notice that each time you click "Check manually," ~100ms or so of extra time is spent on the first request. Much of that extra time can be saved if connections are reused across multiple PHP executions.
Proposed resolution
Since guzzle doesn't automatically enable transport sharing when a HandlerStack is built, core could introduce its own HandlerStack factory method to configure this automatically via ['transport_sharing' => \GuzzleHttp\TransportSharing::PERSISTENT_PREFER]
Remaining tasks
Review MR.
User interface changes
Introduced terminology
API changes
Data model changes
Release notes snippet
Issue fork drupal-3618392
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
mfbComment #4
mfbComment #5
catchThis looks good, I can't see anything to complain about.
Should help translation downloads during the multilingual installer too.
Comment #7
quietone commentedChecking that the core gates are passed.
I read the MR and made two changes, one to a comment and one to add
declare(strict_types=1);. The latter is now policy for new code.Other than that everything is in order here. The changes I made are straightforward and policy so I am leaving at RTBC
Comment #8
mfb@quietone's tweaks look good, rebased since tests were failing, leaving at RTBC
Comment #9
dries commentedThis looks good to me as well.
The only non-blocking question I have is: why doesn't Guzzle make this the default? It has a fallback system. Maybe the feature is still too new?
Comment #10
mfbhttps://github.com/guzzle/guzzle/blob/8.3/docs/handlers.md#transport-sha... doesn't clearly say why it's not the default, but I would guess it's because of the philosophical question of whether or not you want to share connections with other code running in the same PHP process - which could be different paying customers in the case of shared hosting. There shouldn't be much in the way of practical impacts since guard rails are in place - for example cookies are not shared. Assuming your environment has correctly patched CVE-2026-8932, which e.g. an up-to-date debian curl package has, TLS sessions using client certificates are also not shared.
Comment #11
catchThe main thing they mention is that curl shares this across applications on the same host, where each of those applications is asking for transport sharing - e.g. it triggers behaviour in the curl binary rather than just PHP.
Drupal core does relatively few outgoing http requests - there is update status, translation download, oembed fetching in core - will be some contrib and custom Guzzle implementations.
I think this would benefit oembed as well, especially if there are multiple embeds from the same provider on the same page. See also #3621396: Use a queue and permanent cache for Drupal\media\OEmbed\ResourceFetcher::fetchResource().
I can't really think of a problem that would actually arise from this in practice, and it seems like a very good performance improvement that we can't otherwise get, but tagging for security/framework manager review to get an extra opinion.