pub trait ClassifyResponse {
type FailureClass;
type ClassifyEos: ClassifyEos<FailureClass = Self::FailureClass>;
// Required methods
fn classify_response<B>(
self,
res: &Response<B>,
) -> ClassifiedResponse<Self::FailureClass, Self::ClassifyEos>;
fn classify_error<E>(self, error: &E) -> Self::FailureClass
where E: Display + 'static;
// Provided method
fn map_failure_class<F, NewClass>(self, f: F) -> MapFailureClass<Self, F>
where Self: Sized,
F: FnOnce(Self::FailureClass) -> NewClass { ... }
}
Expand description
Trait for classifying responses as either success or failure. Designed to support both unary requests (single request for a single response) as well as streaming responses.
Response classifiers are used in cases where middleware needs to determine whether a response completed successfully or failed. For example, they may be used by logging or metrics middleware to record failures differently from successes.
Furthermore, when a response fails, a response classifier may provide additional information about the failure. This can, for example, be used to build retry policies by indicating whether or not a particular failure is retryable.
Required Associated Types§
sourcetype FailureClass
type FailureClass
The type returned when a response is classified as a failure.
Depending on the classifier, this may simply indicate that the request failed, or it may contain additional information about the failure, such as whether or not it is retryable.
sourcetype ClassifyEos: ClassifyEos<FailureClass = Self::FailureClass>
type ClassifyEos: ClassifyEos<FailureClass = Self::FailureClass>
The type used to classify the response end of stream (EOS).
Required Methods§
sourcefn classify_response<B>(
self,
res: &Response<B>,
) -> ClassifiedResponse<Self::FailureClass, Self::ClassifyEos>
fn classify_response<B>( self, res: &Response<B>, ) -> ClassifiedResponse<Self::FailureClass, Self::ClassifyEos>
Attempt to classify the beginning of a response.
In some cases, the response can be classified immediately, without waiting for a body to complete. This may include:
- When the response has an error status code.
- When a successful response does not have a streaming body.
- When the classifier does not care about streaming bodies.
When the response can be classified immediately, classify_response
returns a ClassifiedResponse::Ready
which indicates whether the
response succeeded or failed.
In other cases, however, the classifier may need to wait until the
response body stream completes before it can classify the response.
For example, gRPC indicates RPC failures using the grpc-status
trailer. In this case, classify_response
returns a
ClassifiedResponse::RequiresEos
containing a type which will
be used to classify the response when the body stream ends.
sourcefn classify_error<E>(self, error: &E) -> Self::FailureClasswhere
E: Display + 'static,
fn classify_error<E>(self, error: &E) -> Self::FailureClasswhere
E: Display + 'static,
Classify an error.
Errors are always errors (doh) but sometimes it might be useful to have multiple classes of errors. A retry policy might allow retrying some errors and not others.
Provided Methods§
sourcefn map_failure_class<F, NewClass>(self, f: F) -> MapFailureClass<Self, F>
fn map_failure_class<F, NewClass>(self, f: F) -> MapFailureClass<Self, F>
Transform the failure classification using a function.
§Example
use tower_http::classify::{
ServerErrorsAsFailures, ServerErrorsFailureClass,
ClassifyResponse, ClassifiedResponse
};
use http::{Response, StatusCode};
use http_body_util::Empty;
use bytes::Bytes;
fn transform_failure_class(class: ServerErrorsFailureClass) -> NewFailureClass {
match class {
// Convert status codes into u16
ServerErrorsFailureClass::StatusCode(status) => {
NewFailureClass::Status(status.as_u16())
}
// Don't change errors.
ServerErrorsFailureClass::Error(error) => {
NewFailureClass::Error(error)
}
}
}
enum NewFailureClass {
Status(u16),
Error(String),
}
// Create a classifier who's failure class will be transformed by `transform_failure_class`
let classifier = ServerErrorsAsFailures::new().map_failure_class(transform_failure_class);
let response = Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.body(Empty::<Bytes>::new())
.unwrap();
let classification = classifier.classify_response(&response);
assert!(matches!(
classification,
ClassifiedResponse::Ready(Err(NewFailureClass::Status(500)))
));