66 lines
2.1 KiB
PHP
66 lines
2.1 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use Illuminate\Http\Client\Response;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Illuminate\Support\Facades\Log;
|
|
use InvalidArgumentException;
|
|
|
|
final class IndexNowService
|
|
{
|
|
/** @param array<int, string> $urls */
|
|
public function submit(array $urls): ?Response
|
|
{
|
|
if (! config('indexnow.enabled')) {
|
|
Log::info('IndexNow submission skipped: disabled.');
|
|
return null;
|
|
}
|
|
|
|
$key = trim((string) config('indexnow.key'));
|
|
if ($key === '') {
|
|
throw new InvalidArgumentException('INDEXNOW_KEY is not configured.');
|
|
}
|
|
|
|
$urls = collect($urls)
|
|
->filter(fn ($url) => is_string($url) && filter_var($url, FILTER_VALIDATE_URL))
|
|
->unique()
|
|
->values()
|
|
->all();
|
|
|
|
if ($urls === []) {
|
|
throw new InvalidArgumentException('No valid URLs were supplied to IndexNow.');
|
|
}
|
|
|
|
$host = parse_url($urls[0], PHP_URL_HOST);
|
|
if (! is_string($host) || $host === '') {
|
|
throw new InvalidArgumentException('Could not determine the IndexNow host.');
|
|
}
|
|
|
|
foreach ($urls as $url) {
|
|
if (parse_url($url, PHP_URL_HOST) !== $host) {
|
|
throw new InvalidArgumentException('All IndexNow URLs must use the same host.');
|
|
}
|
|
}
|
|
|
|
$response = Http::asJson()
|
|
->acceptJson()
|
|
->timeout(10)
|
|
->retry(2, 500)
|
|
->post((string) config('indexnow.endpoint'), [
|
|
'host' => $host,
|
|
'key' => $key,
|
|
'keyLocation' => 'https://'.$host.'/'.$key.'.txt',
|
|
'urlList' => $urls,
|
|
]);
|
|
|
|
if ($response->successful()) {
|
|
Log::info('IndexNow URLs submitted.', ['host' => $host, 'count' => count($urls), 'status' => $response->status()]);
|
|
} else {
|
|
Log::warning('IndexNow submission failed.', ['host' => $host, 'count' => count($urls), 'status' => $response->status(), 'body' => $response->body()]);
|
|
}
|
|
|
|
return $response;
|
|
}
|
|
}
|