Skip to content
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

Add CatchPanic #214

Merged
merged 6 commits into from Feb 22, 2022
Merged

Add CatchPanic #214

merged 6 commits into from Feb 22, 2022

Conversation

davidpdrsn
Copy link
Member

@davidpdrsn davidpdrsn commented Jan 26, 2022

This adds a CatchPanic middleware that catches panics and converts them into 500 responses.

TODO

  • Module docs with examples
  • Support supplying closure to generate response in case users wanna return a fancy JSON response or something like that.

@davidpdrsn davidpdrsn added the A-new-middleware Area: new middleware proposals label Jan 26, 2022
Copy link

@kosta kosta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, that was quick :) Thank you!

tower-http/src/catch_panic.rs Outdated Show resolved Hide resolved
tower-http/src/catch_panic.rs Show resolved Hide resolved
tower-http/src/catch_panic.rs Outdated Show resolved Hide resolved

#[inline]
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.inner.poll_ready(cx)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, but should this also catch panics? 🤔

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm so thats a good question actually. I'm actually thinking no, panics from poll_ready shouldn't be handled for a few reasons:

  • We cannot return a response from poll_ready so we'd have to return an error. That would require changing the error type to BoxError which means a service that previously returned Infallible would now return BoxError. This makes it more annoying to use with axum.
  • If poll_ready returns an error the Service contract dictates that the service must be discarded and recreated. Hyper handles that and does the same thing regardless if poll_ready errors or panics. So since we cannot return a response it kinda doesn't matter what we do 🤷
  • In practice its rare for services to actually care about poll_ready so panics from here should be very rare. I would guess they're much more common from call.

@hawkw What do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I don't think we should catch panics here. Those reasons track for me.

@hawkw
Copy link
Member

hawkw commented Jan 27, 2022

Hmm, I kind of wonder if it makes sense to have a general-purpose CatchPanic middleware in tower itself, and then a middleware in tower-http that turns panic errors into 500s? not a blocker.

@davidpdrsn
Copy link
Member Author

@hawkw yep that's definitely something I want to explore as well before merging this!

I would like tower-http to not have a public dependency on tower (just service and layer) but I'll see what I can come up with 😊

@davidpdrsn davidpdrsn marked this pull request as ready for review January 30, 2022 17:15
@davidpdrsn davidpdrsn changed the title WIP: Add CatchPanic Add CatchPanic Jan 30, 2022
@davidpdrsn
Copy link
Member Author

Hmm, I kind of wonder if it makes sense to have a general-purpose CatchPanic middleware in tower itself, and then a middleware in tower-http that turns panic errors into 500s? not a blocker.

I've opted not to add anything to tower since I guess such a middleware would convert panics to errors. So to make this middleware easier to use with axum I'd prefer keeping the error type and instead changing the response.

@hawkw let me know if you had something else in mind!

@davidpdrsn
Copy link
Member Author

Note to self: Read actix/actix-web#1501

@davidpdrsn
Copy link
Member Author

I think we should make a decision about this soon.

From talking to people the main criticism I hear is "don't use panics for error handling", which I agree with, but sadly you sometimes have dependencies that behave badly and have to guard against that. I'll add a note about that to the docs.

It sounds to me like there isn't much reason not to provide a middleware like this.

Thoughts @LucioFranco @olix0r @hawkw?

Comment on lines +182 to +186
ResBody: Body<Data = Bytes> + Send + 'static,
ResBody::Error: Into<BoxError>,
T: ResponseForPanic + Clone,
T::ResponseBody: Body<Data = Bytes> + Send + 'static,
<T::ResponseBody as Body>::Error: Into<BoxError>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we actually need to include these send bounds?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. They're required because we call http_body::Body::boxed_unsync which requires the body to be Send. We call that on the body from inner service and from the callback that creates the panic response.

Copy link
Member

@LucioFranco LucioFranco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM jiust a few questions not blocking

@davidpdrsn davidpdrsn merged commit 0f365a1 into master Feb 22, 2022
@davidpdrsn davidpdrsn deleted the add-catch-panic branch February 22, 2022 19:15
davidpdrsn added a commit that referenced this pull request Mar 5, 2022
* Add `CatchPanic`

* support custom panic handler

* docs

* fix feature

* Add note about using panics for error handling
davidpdrsn added a commit that referenced this pull request Mar 5, 2022
- Added `CatchPanic` middleware which catches panics and converts them
  into `500 Internal Server` responses ([#214])

[#214]: #214
@davidpdrsn davidpdrsn mentioned this pull request Mar 5, 2022
davidpdrsn added a commit that referenced this pull request Mar 7, 2022
* Release 0.2.4

- Added `CatchPanic` middleware which catches panics and converts them
  into `500 Internal Server` responses ([#214])

[#214]: #214

* Fix parsing of `Accept-Encoding` request header (#220)

* Fix parsing of Accept-Encoding request header

* Add unit tests to content_encoding

* Represent quality values (qvalues) by a separate type

* Parse encodings case-insensitively

* Parse qvalues as specified in RFC 7231 section 5.3.1

Refs: #215

* Do not use or-pattern syntax

This syntax is not supported in rust 1.51 (the minimum toolchain
version).

* Add comments to QValue::parse

* Remove redundant SupportedEncodingsAll::new function

* Add unit tests for all content-encodings (gzip, deflate, br)

* Update changelog

* add changelog groups

Co-authored-by: Martin Dickopp <martin@zero-based.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-new-middleware Area: new middleware proposals
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants