Skip to content

Commit 0e6892e

Browse files
committed
feat: support custom error messages for manual HttpRequestFailed throw
1 parent 150b342 commit 0e6892e

File tree

5 files changed

+47
-10
lines changed

5 files changed

+47
-10
lines changed

packages/http/src/HttpRequestFailed.php

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,38 @@
44

55
use Exception;
66
use Tempest\Core\ProvidesContext;
7-
use Throwable;
87

98
/**
10-
* Represents an HTTP exception.
9+
* Stops the request's execution and return a response with the given status. Optionally, a message may be provided.
1110
*/
1211
final class HttpRequestFailed extends Exception implements ProvidesContext
1312
{
13+
/**
14+
* @param Status $status The HTTP status code to send as a response.
15+
* @param string|null $message An optional message that will be displayed to the client.
16+
* @param Response|null $cause The response that caused the failure, if any.
17+
* @param Request|null $request The request that failed, for debug purposes.
18+
*/
1419
public function __construct(
1520
private(set) readonly Status $status,
1621
?string $message = null,
1722
private(set) readonly ?Response $cause = null,
1823
private(set) readonly ?Request $request = null,
19-
?Throwable $previous = null,
2024
) {
2125
parent::__construct(
2226
message: $message ?: '',
2327
code: $status->value,
24-
previous: $previous,
2528
);
2629
}
2730

2831
public function context(): array
2932
{
30-
return [
33+
return array_filter([
3134
'request_uri' => $this->request?->uri,
3235
'request_method' => $this->request?->method->value,
33-
'status' => $this->status->value,
34-
'message' => $this->message,
35-
'cause' => $this->cause,
36-
'previous' => $this->getPrevious()?->getMessage(),
37-
];
36+
'status_code' => $this->status->value,
37+
'message' => $this->message !== '' ? $this->message : null,
38+
'original_response' => $this->cause ? $this->cause::class : null,
39+
]);
3840
}
3941
}

packages/router/src/Exceptions/HtmlExceptionRenderer.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ public function render(Throwable $throwable): Response
6969

7070
private function renderHttpRequestFailed(HttpRequestFailed $exception): Response
7171
{
72+
if ($exception->getMessage() !== '') {
73+
return $this->renderErrorResponse($exception->status, message: $exception->getMessage());
74+
}
75+
7276
if ($exception->cause && is_string($exception->cause->body)) {
7377
return $this->renderErrorResponse($exception->status, message: $exception->cause->body);
7478
}

packages/router/src/Exceptions/JsonExceptionRenderer.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ public function render(Throwable $throwable): Response
4848

4949
private function renderHttpRequestFailed(HttpRequestFailed $exception): Response
5050
{
51+
if ($exception->getMessage() !== '') {
52+
return $this->renderErrorResponse($exception->status, message: $exception->getMessage());
53+
}
54+
5155
if ($exception->cause && is_string($exception->cause->body)) {
5256
return $this->renderErrorResponse($exception->status, message: $exception->cause->body);
5357
}

tests/Integration/Http/Exceptions/HtmlExceptionRendererTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,4 +188,18 @@ public function uses_translations(): void
188188
$this->assertInstanceOf(View::class, $response->body);
189189
$this->assertSame('I am a teapot.', $response->body->data['message']);
190190
}
191+
192+
#[Test]
193+
public function http_request_failed_with_custom_message(): void
194+
{
195+
$response = $this->renderer->render(new HttpRequestFailed(
196+
status: Status::BAD_REQUEST,
197+
message: 'Custom error message',
198+
));
199+
200+
$this->assertSame(Status::BAD_REQUEST, $response->status);
201+
$this->assertInstanceOf(GenericResponse::class, $response);
202+
$this->assertInstanceOf(GenericView::class, $response->body);
203+
$this->assertSame('Custom error message', $response->body->data['message']);
204+
}
191205
}

tests/Integration/Http/Exceptions/JsonExceptionRendererTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,4 +177,17 @@ public function uses_status_description(): void
177177

178178
$this->assertSame("I'm a teapot", $response->body['message']);
179179
}
180+
181+
#[Test]
182+
public function http_request_failed_with_custom_message(): void
183+
{
184+
$response = $this->renderer->render(new HttpRequestFailed(
185+
status: Status::BAD_REQUEST,
186+
message: 'Custom error message',
187+
));
188+
189+
$this->assertInstanceOf(Json::class, $response);
190+
$this->assertSame(Status::BAD_REQUEST, $response->status);
191+
$this->assertSame('Custom error message', $response->body['message']);
192+
}
180193
}

0 commit comments

Comments
 (0)