- UpdateDnsRecords Action: controller method now one-liner, all DNS logic in Action with activity logging and edit lock. - Prometheus metrics at /v1/metrics: chain_height, alias_count, claims_pending, dns_tickets, gateways_live. Grafana-ready. - ValidateJsonRequest middleware: enforces application/json on POST, 64KB body size limit. Applied to all /v1/* API routes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
71 lines
2.1 KiB
PHP
71 lines
2.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Website\Api;
|
|
|
|
use Core\Events\DomainResolving;
|
|
use Core\Events\WebRoutesRegistering;
|
|
use Illuminate\Foundation\Http\Middleware\ValidateCsrfToken;
|
|
use Illuminate\Support\Facades\Event;
|
|
use Illuminate\Support\Facades\Route;
|
|
use Illuminate\Support\ServiceProvider;
|
|
|
|
/**
|
|
* api.lthn.io — REST API.
|
|
*
|
|
* Registers all /v1/* API routes. In production, Traefik routes
|
|
* api.lthn.io traffic here. The honeypot null-routes API payloads
|
|
* sent to the web domain, so these routes MUST NOT be on lthn.io.
|
|
*
|
|
* DomainResolving handles the homepage (/) — only on api.lthn.io.
|
|
* API routes register unconditionally since Blesta connects via
|
|
* host.docker.internal in homelab.
|
|
*/
|
|
class Boot extends ServiceProvider
|
|
{
|
|
public static array $domains = [
|
|
'/^api\.lthn\.io$/',
|
|
'/^api\.lthn\.sh$/',
|
|
'/^api\.(test|localhost)$/',
|
|
];
|
|
|
|
public static array $listens = [
|
|
DomainResolving::class => 'onDomain',
|
|
WebRoutesRegistering::class => 'onWebRoutes',
|
|
];
|
|
|
|
public function register(): void {}
|
|
|
|
public function boot(): void
|
|
{
|
|
$this->loadViewsFrom(__DIR__ . '/Views', 'api');
|
|
|
|
foreach (static::$listens as $event => $method) {
|
|
Event::listen($event, [$this, $method]);
|
|
}
|
|
}
|
|
|
|
public function onDomain(DomainResolving $event): void
|
|
{
|
|
foreach (static::$domains as $pattern) {
|
|
if (preg_match($pattern, $event->domain)) {
|
|
$event->resolve($this);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
public function onWebRoutes(WebRoutesRegistering $event): void
|
|
{
|
|
// API routes — no CSRF, no session needed
|
|
$event->routes(fn () => Route::prefix('v1')
|
|
->withoutMiddleware(ValidateCsrfToken::class)
|
|
->middleware('json.validate')
|
|
->group(__DIR__ . '/Routes/api.php'));
|
|
|
|
// Homepage scoped to API domain via middleware
|
|
$event->routes(fn () => Route::middleware('domain:api.lthn.io,api.lthn.sh')
|
|
->group(__DIR__ . '/Routes/home.php'));
|
|
}
|
|
}
|