Skip to content

Allow injecting a PSR-18 HTTP client and PSR-16 cache - #6

Merged
ArrayIterator merged 1 commit into
ArrayAccess:mainfrom
tomsommer:psr-http-client
Oct 9, 2026
Merged

ArrayIterator merged 1 commit into
ArrayAccess:mainfrom
tomsommer:psr-http-client

Conversation

@tomsommer

Copy link
Copy Markdown

Implements the proposal from #5.

What it does

Client optionally accepts a PSR-18 HTTP client, a PSR-17 request factory and a PSR-16 cache:

$httpClient = new Psr18Client(HttpClient::create(['timeout' => 5]));
$client = new Client($httpClient, null, new Psr16Cache(new FilesystemAdapter()));
  • HTTP client: used for both the IANA bootstrap files and the RDAP queries, so timeouts, proxies, retries, logging and test mocking follow the application's own HTTP stack.
  • Request factory: can be omitted when the HTTP client also implements RequestFactoryInterface (e.g. Symfony's Psr18Client). An InvalidArgumentException is thrown if neither provides one.
  • Cache: stores the bootstrap files for AbstractRdapService::cacheExpirations() seconds. Content is only cached after it validates, and an invalid cache entry is deleted and fetched again.
  • Status codes: the response body is returned regardless of the HTTP status (matching ignore_errors => true in the stream context), so RDAP error payloads still become RdapResponseException. Transport failures, and error statuses with an empty body, become RdapRemoteRequestException with the HTTP status as the code.

Backwards compatibility

Without arguments, the existing file_get_contents() requests and the temporary-file bootstrap cache are unchanged. No existing interface signature changes:

  • The client is reached through a new optional RdapHttpClientAwareInterface that Client implements; RdapClientInterface is untouched.
  • AbstractRdapService gets a new fromJson(), which fromURL() now uses for validation. RdapServiceInterface::fromURL() keeps its signature.

The new requirements are the interface-only packages psr/http-client, psr/http-factory and psr/simple-cache (^1.0 || ^2.0 || ^3.0).

Testing

  • composer validate --strict, phpcs and phpstan (level 8, also with phpVersion: 80100) pass.
  • Smoke-tested against live RDAP servers: default path (1.1.1.1 via APNIC), Psr18Client + PSR-16 cache (IPv6 via RIPE, second client served the bootstrap file from cache), and a 404 from Verisign surfacing as RdapRemoteRequestException with code 404.

Closes #5

Client optionally accepts a PSR-18 client, a PSR-17 request factory
and a PSR-16 cache. When an HTTP client is given it is used for both
the IANA bootstrap files and the RDAP queries; the cache stores the
bootstrap files. Without arguments the existing file_get_contents()
and temporary file cache behaviour is unchanged.

Closes ArrayAccess#5
@ArrayIterator
ArrayIterator merged commit a2a74e5 into ArrayAccess:main Oct 9, 2026
4 checks passed
@tomsommer

Copy link
Copy Markdown
Author

Thanks for merging this so quickly!

Would you be able to tag a release so it can be installed through Composer? The latest tag is still 1.0.1, and since this adds a feature without breaking changes, 1.1.0 would fit.

I also opened a few small bug fixes found while working on this, in case you want to include them in the same release:

They are independent of each other. If you'd rather not review them now, tagging what's on main would already help a lot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support injecting a PSR-18 HTTP client (and PSR-16 cache for bootstrap files)

2 participants