-
Notifications
You must be signed in to change notification settings - Fork 11.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[8.x] Add throwWith to the HTTP client response #34558
Conversation
{ | ||
if ($this->serverError() || $this->clientError()) { | ||
$callback($this); | ||
|
||
throw new RequestException($this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if we do it as:
throw tap(new RequestException($this), function ($exception) use ($callback) {
$callback($this, $exception);
});
* | ||
* @throw \Illuminate\Http\Client\RequestException | ||
*/ | ||
public function throwWith($callback) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about beforeThrowing
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then it'd make sense to call beforeThrowing()->throw()
, which IMO is too bervose
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed on that being to verbose. I was hoping to find something that could express "When throwing, do this thing and then throw" rather than two methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
onError
also makes sense to me. throwWith
doesn't make sense to me because it has an indication of which parameters would be given to throw
(like the Cotnainer's makeWith
). Though I still prefer beforeThrowing
as it indicates what to do (callback) right before an exception is thrown. I guess whenThrowing
could also work (like Query Builder when()
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't disagree with your objections. As mentioned I didn't know if this was really a great method name.
Maybe there just isn't a nice "all-in-one" option, as whenThrowing
also makes me wonder if I need to call throw
or not.
Maybe it is just an onError
callback (as you and others suggested on Twitter).
return $client->withHeaders($headers)
->post($url, $payload)
->onError(fn ($response) =>
Log::error('Twitter API failed posting Tweet', [
'url' => $url,
'payload' => $payload,
'headers' => $headers,
'response' => $response->body(),
])
)->throw()->json();
Or maybe I just need to wrap up the more verbose middleware as @sebdesign pointed out in my own app 🤷♂️
I just liked how the error callback and throw was on the other side of the post
call, as it felt nicer to me being in sequential order, but that is just an opinion that might not be shared.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally I prefer the onError
callback instead of the Middleware::mapResponse
stuff. It feels nicer and you get to work with the Laravel\Http\Client\Response
instead of the Guzzle response.
I think the same can be achieved by using middleware. Example: return $client->withHeaders($headers)
->withMiddleware(Middleware::mapResponse(function ($response) {
if ($response->getStatusCode() >= 400) {
Log::error('Twitter API failed posting Tweet', [
'url' => $url,
'payload' => $payload,
'headers' => $headers,
'response' => (string) $response->getBody(),
]);
}
return $response;
}))->post($url, $payload)->throw()->json(); |
Because: - There is a repeated pattern where you want to perform a particular action if the response has failed, such as logging the error. ```php // before... $response = $client->withHeaders($headers)->post($url, $payload); if ($response->failed()) { Log::error('Twitter API failed posting Tweet', [ 'url' => $url, 'payload' => $payload, 'headers' => $headers, 'response' => $response->body(), ]); $response->throw(); } return $response->json(); // after... return $client->withHeaders($headers) ->post($url, $payload) ->throwWith(fn ($response) => Log::error('Twitter API failed posting Tweet', [ 'url' => $url, 'payload' => $payload, 'headers' => $headers, 'response' => $response->body(), ]) )->json(); ``` This commit: - Adds the `throwWith` method to the response. - Updates the `throw` method to utilise the new `throwWith` method, just with an empty closure. Notes: - I'm not convinced this is the best name for this method. - I'm also wondering if the method should be a `tap` method of some kind. `tapWhenThrowing` or something along those lines.
Although it isn't as nice as I had hoped, I've moved to an New implementation example: Before... $response = $client->withHeaders($headers)->post($url, $payload);
if ($response->failed()) {
Log::error('Twitter API failed posting Tweet', [
'url' => $url,
'payload' => $payload,
'headers' => $headers,
'response' => $response->body(),
]);
$response->throw();
}
return $response->json(); After... return $client->withHeaders($headers)
->post($url, $payload)
->onError(fn ($response) =>
Log::error('Twitter API failed posting Tweet', [
'url' => $url,
'payload' => $payload,
'headers' => $headers,
'response' => $response->body(),
])
)->throw()->json(); As @sebdesign pointed out, using the method instead of the suggested middleware approach above you get to use the Illuminate response instead of the Guzzle response in the callback. See: #34558 (comment) I also think it feels nicer as it is expressed in sequential order. |
Because: - There wasn't a great name that really expressed what was happening under the hood, i.e. running the closure and throwing the exception This commit: - Reverts the `throw` method and implements a stand-alone `onError` method
@@ -216,6 +216,21 @@ public function throw() | |||
return $this; | |||
} | |||
|
|||
/** | |||
* Execute the callback and throw an exception if a server of client error occurred. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess the comment should be changed as an exception is not thrown anymore
I think there's one last option for this that technically has to be split into 2 PRs: PR 1 (8.x)
PR 2 (9.x)
Usage:
|
I like that, but I fear the name |
@m1guelpf I don't see that as a problem, but rather as a feature.
|
So I kept the |
Nice! Thanks for the collab everyone. Really dig where this landed with everyone’s input. Best of all worlds! ❤️ |
Implementation updated: #34558 (comment)
Because:
Before...
After...
This commit:
throwWith
method to the response.throw
method to utilise the newthrowWith
method, just with an empty closure.Notes:
tap
method of some kind.tapWhenThrowing
or something along those lines.