Issue #3586446: Add per-provider HTTP handler configuration
Description
Adds per-provider HTTP client handler configuration so sites can fix streaming failures (e.g. OpenAI + CKEditor AI under php-fpm/Docker) without site-wide $settings['http_client_config'].
Previously, AiProviderClientBase::create() accepted http_client_options on plugin construction, but nothing set it. This MR introduces AiProviderHttpClientOptionsBuilder, which merges:
- Exported config (
ai.settings:provider_http_clients) settings.php($settings['ai_provider_http_clients'])- Explicit
http_client_optionsoncreateInstance()(highest priority) Handler presets: | Preset | Effect | |--------|--------| |default| No override — current Drupal HTTP client behaviour | |curl|HandlerStack::create(new CurlHandler())for that provider only | UI: Advanced settings » Provider HTTP clients — one select per installed provider. Docs:docs/developers/provider_http_client.mdTests:tests/src/Unit/Service/AiProviderHttpClientOptionsBuilderTest.php; kernel schema coverage updated. Closes #3586446
Testing instructions
- Enable AI and an OpenAI provider module; configure a valid API key.
- Go to
/admin/config/ai/settings→ Advanced settings → Provider HTTP clients. - Confirm each provider shows Default (Drupal HTTP client) by default; save —
provider_http_clientsshould stay empty. - Set OpenAI to cURL handler, save, and confirm
ai.settings:provider_http_clients.openai.handleriscurl. - On an environment where streamed CKEditor AI failed with default handler, confirm streaming works with OpenAI set to cURL handler (no site-wide
http_client_configchange). - Optional: in
settings.php, set$settings['ai_provider_http_clients']['openai'] = ['handler' => 'curl'];— confirm the UI field is disabled and the override applies. - Run unit tests:
cd web/core ../vendor/bin/phpunit -c phpunit.xml.dist \ ../modules/contrib/ai/tests/src/Unit/Service/AiProviderHttpClientOptionsBuilderTest.php
Checklist
- I have linked the related issue in the MR title or description
- I have performed a self-review of my own code
- I have added or updated tests, or explained in the description why this change is not covered by tests
- I have updated documentation for any new or changed functionality
- I have written testing instructions and verified them locally
- I have noted any required post-merge steps (config imports, cache rebuilds, manual changes)
- This MR contains no breaking API or hook changes, or they are explicitly documented in the description
AI Compliance
Note
Check the one that best describes your usage, or leave all unchecked if AI was not significantly used.
-
AI Assisted Code
Mainly written by a human; AI used for autocomplete or partial generation under full human supervision. -
AI Generated Code
Mainly generated by AI, reviewed and approved by a human before this MR was created. -
Vibe Coded
Generated by AI and only functionally reviewed before this MR was created.
Closes #3586446