Skip to content

Refine HttpClient factory lifecycle and request helper API after #534 #563

Closed

Description

@armanist

Follow-up to #534. The adapter extraction introduced CurlAdapter and MultiCurlAdapter, but the public creation/lifecycle model is still unclear.

Current issues:

  • HttpClientFactory::get() returns a cached mutable HttpClient.
  • HttpClient stores request-specific state: method, data, request headers, responses, and errors.
  • Reusing a cached HttpClient can leak state between requests unless every create*Request() call resets state.
  • HttpClientType exists but is not currently used.
  • HttpClient directly constructs CurlAdapter / MultiCurlAdapter.
  • Public usage is unclear: new HttpClient(), HttpClientFactory::get(), and future helper usage are not aligned.
  • Core packages currently instantiate or inject HttpClient directly and call createRequest(), so removing those methods immediately is not safe.

Goal

Define and implement a coherent request-context creation model for HttpClient, while preserving backward compatibility with existing consumers.

Proposed Direction

Treat HTTP requests as fresh request contexts, closer to PaginatorFactory::create(...) than cached service factories like Cache/Mailer.

Add factory methods that return fresh configured clients:

HttpClientFactory::createRequest(string $url, ?Curl $client = null): HttpClient
HttpClientFactory::createMultiRequest(?MultiCurl $client = null): HttpClient
HttpClientFactory::createAsyncMultiRequest(callable $success, callable $error, ?MultiCurl $client = null): HttpClient

Add helper functions:

httpRequest(string $url, ?Curl $client = null): HttpClient
httpMultiRequest(?MultiCurl $client = null): HttpClient
httpAsyncMultiRequest(callable $success, callable $error, ?MultiCurl $client = null): HttpClient

Keep existing instance methods for compatibility:

HttpClient::createRequest()
HttpClient::createMultiRequest()
HttpClient::createAsyncMultiRequest()

Do not promote cached HttpClientFactory::get() for request usage. Either remove it if safe, or deprecate it if it may already be used externally.

Tasks

  1. Audit current core usages of HttpClient.
  2. Add fresh request-context factory methods.
  3. Add helper functions for single, multi, and async multi requests.
  4. Decide whether HttpClientFactory::get() should be removed or deprecated.
  5. Decide whether HttpClientType should be removed or used internally.
  6. Keep backward-compatible HttpClient::create*Request() methods unless a breaking change is explicitly accepted.
  7. Add tests proving each factory/helper call returns a fresh request context.
  8. Add tests for no stale state between sequential requests.
  9. Update core package usages where appropriate:
    • Captcha
    • Lang
    • Storage
    • Mailer
  10. Update documentation/changelog with recommended usage.

Acceptance Criteria

  • httpRequest($url) creates a fresh single-request HttpClient.
  • httpMultiRequest() creates a fresh multi-request HttpClient.
  • httpAsyncMultiRequest($success, $error) creates a fresh async multi-request HttpClient.
  • Factory request-creation methods return fresh instances.
  • No request state leaks between factory/helper-created requests.
  • Existing direct usage with new HttpClient()->createRequest() still works.
  • Existing core package tests pass.
  • Downstream save_remote_image() works using the new helper/factory style.
  • HttpClientType is either used meaningfully or removed.
  • HttpClientFactory::get() is removed or clearly deprecated to avoid cached mutable-request misuse.

Validation

Run:

vendor/bin/phpunit tests/Unit/HttpClient
vendor/bin/phpunit tests/Unit/Captcha tests/Unit/Lang tests/Unit/Storage tests/Unit/Mailer
composer cs:check
composer phpstan

Also perform downstream smoke test in quantum-php-project:

  • point quantum/framework to local core path repository;
  • update save_remote_image() to use the new helper/factory style;
  • verify a real HTTP image download saves the expected file body.

Activity

  1. self-assigned this
    on Jul 18, 2026
  2. added
    bugSomething isn't working
    enhancementNew feature or request
    httpHTTP transport, redirects, and request/response behavior
    on Jul 18, 2026
  3. added theissue type on Jul 18, 2026
  4. added this to the 3.1.0 milestone on Jul 18, 2026
  5. armanist commented on Jul 18, 2026

    @armanist
    CollaboratorAuthor

    Updated implementation direction after design review:

    • HttpClientFactory::get() should be removed.
    • HttpClientFactory should expose only fresh request-context creation methods:
    HttpClientFactory::createRequest(string $url): HttpClient
    HttpClientFactory::createMultiRequest(): HttpClient
    HttpClientFactory::createAsyncMultiRequest(callable $success, callable $error): HttpClient
    • Factory methods should not expose vendor Curl / MultiCurl parameters. Vendor injection remains only on the existing HttpClient::create*Request() compatibility methods for tests/internal compatibility.
    • Add helpers with these exact names:
    httpRequest(string $url): HttpClient
    httpMultiRequest(): HttpClient
    httpAsyncMultiRequest(callable $success, callable $error): HttpClient
    • Keep existing HttpClient::createRequest(), HttpClient::createMultiRequest(), and HttpClient::createAsyncMultiRequest() for backward compatibility.
    • Remove HttpClientType; no generic create(string $type, array $params) API is planned for this ticket.
    • Do not add resetRequestState() in this ticket because the new factory/helper APIs return fresh HttpClient instances and the existing instance methods are kept only for compatibility.

    This narrows the ticket to a fresh request-context factory/helper API and avoids exposing vendor classes through the new public helper/factory surface.

  6. added 2 commits that reference this issue on Jul 18, 2026
  7. added 3 commits that reference this issue on Jul 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingenhancementNew feature or requesthttpHTTP transport, redirects, and request/response behavior

Type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions