labrodev / laravel-domain-keeper
Domain registrar-expiry reader for Laravel — RDAP first with a port-43 WHOIS fallback.
Requires
- php: ^8.4
- guzzlehttp/guzzle: ^7.8
- illuminate/http: ^13.0
- illuminate/support: ^13.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- driftingly/rector-laravel: ^2.5
- larastan/larastan: ^3.0
- laravel/pint: ^1.0
- orchestra/testbench: ^11.0
- pestphp/pest: ^4.0
README
Domain registrar-expiry reader for Laravel — RDAP first with a port-43 WHOIS fallback. Ask it for a domain and it returns the registrar expiry date as a Carbon instance; the package stores nothing and keeps no state between lookups.
Installation
composer require labrodev/laravel-domain-keeper
Publish the config file:
php artisan vendor:publish --tag=domain-keeper-config
All environment variables are optional — the defaults work out of the box:
DOMAIN_KEEPER_RDAP_URL=https://rdap.org/domain/ DOMAIN_KEEPER_WHOIS_SERVER=whois.iana.org DOMAIN_KEEPER_TIMEOUT=10
Reading a domain's expiry date
Type-hint the RegistrarExpiryReader contract — the service provider binds it to the RDAP-first implementation:
use Labrodev\DomainKeeper\Contracts\RegistrarExpiryReader; use Labrodev\DomainKeeper\Exceptions\RegistrarExpiryNotFound; class DomainExpiryCheckController { public function __invoke(RegistrarExpiryReader $registrarExpiryReader) { try { $expiry = $registrarExpiryReader->expiryDate('example.com'); } catch (RegistrarExpiryNotFound $registrarExpiryNotFound) { // Neither RDAP nor WHOIS produced a date; the message names the domain. } return $expiry->toDateString(); } }
How it resolves
- RDAP — an HTTPS GET to
{rdap_url}{domain}(defaulthttps://rdap.org/domain/, which redirects to the authoritative registry RDAP server). The reader picks theexpirationevent out of the RDAPeventsarray. Plain HTTPS, so it works inside containers with no raw-socket access. - IANA WHOIS referral — when RDAP yields nothing, the domain is queried against the bootstrap WHOIS server (
whois.iana.orgby default) and thewhois:referral line names the TLD's authoritative WHOIS server. - Registrar WHOIS — the referral server is queried for the domain and the expiry line is parsed (
Registry Expiry Date,Registrar Registration Expiration Date,Expiration Date,Expiry Date, orpaid-till).
Every failure along the way falls through silently to the next step; only when all three sources come up empty does the reader throw RegistrarExpiryNotFound.
Testing your own code
The raw port-43 socket lives in Labrodev\DomainKeeper\Services\WhoisClient, which the reader receives via constructor injection — swap it through the container to keep your suite off the network:
use Labrodev\DomainKeeper\Services\WhoisClient; app()->instance(WhoisClient::class, new readonly class extends WhoisClient { public function query(string $server, string $domain): ?string { return "Registry Expiry Date: 2030-01-01T00:00:00Z\n"; } });
Testing
composer test # pest composer phpstan # larastan, level 7 composer pint # laravel preset composer check # all of the above
License
MIT. See LICENSE.md.