refactor(request): propagate validation failures as exceptions

This commit is contained in:
kj
2026-09-07 17:20:19 -03:00
parent 65380f37c6
commit a534613d26

View File

@@ -2,6 +2,8 @@
namespace Libs; namespace Libs;
use Exception;
/** /**
* Request - DuckBrain * Request - DuckBrain
* *
@@ -59,17 +61,20 @@ class Request extends Neuron
} }
// Run configured validations // Run configured validations
if (!$this->validate()) { $this->validate();
exit();
}
} }
/** /**
* Starts the configured validation. * Starts the configured validation.
* *
* @return bool * On failure the single error message is built with Validator::message()
* and handed to onInvalid(), which throws by default: failures travel up
* as exceptions instead of answering HTTP here.
*
* @return void
* @throws Exception When a configured rule fails.
*/ */
public function validate(): bool public function validate(): void
{ {
$actual = match ($_SERVER['REQUEST_METHOD']) { $actual = match ($_SERVER['REQUEST_METHOD']) {
'POST', 'PUT', 'PATCH', 'DELETE' => $this->{strtolower($_SERVER['REQUEST_METHOD'])}, 'POST', 'PUT', 'PATCH', 'DELETE' => $this->{strtolower($_SERVER['REQUEST_METHOD'])},
@@ -88,7 +93,7 @@ class Request extends Neuron
Validator::validateList(static::getRules(), $this->get) && Validator::validateList(static::getRules(), $this->get) &&
Validator::validateList(static::rules(), $body) Validator::validateList(static::rules(), $body)
) { ) {
return true; return;
} }
$error = Validator::message( $error = Validator::message(
@@ -98,7 +103,6 @@ class Request extends Neuron
); );
static::onInvalid($error); static::onInvalid($error);
return false;
} }
/** /**
@@ -157,27 +161,20 @@ class Request extends Neuron
/** /**
* Function to execute when an invalid value has been detected. * Function to execute when an invalid value has been detected.
* *
* Always answers with a single error and HTTP 422. The representation is * The default implementation always throws a generic \Exception carrying
* negotiated from the request's Accept header: JSON when the client asks * the single error message and HTTP 422 as its code; the framework's
* for application/json, plain text otherwise. * exception boundary (Router::apply) renders the response. Override it to
* throw a more specific exception type instead. The never return type is
* the contract: an override that returned would let the request continue
* with invalid data, so PHP rejects such an override at compile time.
* *
* @param string $error * @param string $error
* *
* @return void * @return never
* @throws Exception
*/ */
public function onInvalid(string $error): void public function onInvalid(string $error): never
{ {
http_response_code(422); throw new Exception($error, 422);
$accept = $_SERVER['HTTP_ACCEPT'] ?? '';
if (str_contains($accept, 'application/json')) {
header('Content-Type: application/json');
print(json_encode(['error' => $error]));
return;
}
print($error);
} }
} }