#[non_exhaustive]pub enum NonUtf8HeaderHandling {
Reject,
Skip,
}Expand description
What to do when a response header value bound to a modeled member is not valid UTF-8
An HTTP header value may contain any octet in 0x80..=0xFF (obs-text, RFC 7230), and an
arbitrary sequence of those is not necessarily valid UTF-8, so a service may send a value that
cannot be represented as a Rust String. Headers stores
such a value as received, but the modeled member it is bound to is a String, so something has
to give when the member is deserialized.
The default is Reject. To choose otherwise, put this in the config bag from an
interceptor that runs before deserialization. Skip does not remove the header, so
the same interceptor can read the octets from any hook that sees the response, using
Headers::get_bytes or
iter_bytes:
#[derive(Clone, Debug, Default)]
struct SkipNonUtf8Headers {
seen: Arc<Mutex<Vec<(String, Vec<u8>)>>>,
}
impl Intercept for SkipNonUtf8Headers {
fn name(&self) -> &'static str {
"SkipNonUtf8Headers"
}
fn read_before_execution(
&self,
_context: &BeforeSerializationInterceptorContextRef<'_>,
cfg: &mut ConfigBag,
) -> Result<(), BoxError> {
cfg.interceptor_state()
.store_put(NonUtf8HeaderHandling::Skip);
Ok(())
}
fn read_before_deserialization(
&self,
context: &BeforeDeserializationInterceptorContextRef<'_>,
_runtime_components: &RuntimeComponents,
_cfg: &mut ConfigBag,
) -> Result<(), BoxError> {
// Runs once per attempt, so overwrite rather than append.
*self.seen.lock().unwrap() = context
.response()
.headers()
.iter_bytes()
.filter(|(_, value)| std::str::from_utf8(value).is_err())
.map(|(name, value)| (name.to_owned(), value.to_vec()))
.collect();
Ok(())
}
}This applies only to values bound to a modeled member. A header bound to nothing is never an error regardless of encoding.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Reject
Fail the operation, reporting the member and header that could not be parsed.
This is the default: a value the service sent is not silently discarded.
Skip
Deserialize the member as if the header were absent.
The header itself is left in place, so the octets stay readable through
Headers::get_bytes.
Note this drops the whole member, not just the offending value: for a member bound to a
list-valued header, one unreadable value makes the entire member None.
Trait Implementations§
Source§impl Clone for NonUtf8HeaderHandling
impl Clone for NonUtf8HeaderHandling
Source§impl Debug for NonUtf8HeaderHandling
impl Debug for NonUtf8HeaderHandling
Source§impl Default for NonUtf8HeaderHandling
impl Default for NonUtf8HeaderHandling
impl Eq for NonUtf8HeaderHandling
Source§impl PartialEq for NonUtf8HeaderHandling
impl PartialEq for NonUtf8HeaderHandling
Source§impl Storable for NonUtf8HeaderHandling
impl Storable for NonUtf8HeaderHandling
Source§type Storer = StoreReplace<NonUtf8HeaderHandling>
type Storer = StoreReplace<NonUtf8HeaderHandling>
StoreReplace and StoreAppendimpl StructuralPartialEq for NonUtf8HeaderHandling
Auto Trait Implementations§
impl Freeze for NonUtf8HeaderHandling
impl RefUnwindSafe for NonUtf8HeaderHandling
impl Send for NonUtf8HeaderHandling
impl Sync for NonUtf8HeaderHandling
impl Unpin for NonUtf8HeaderHandling
impl UnsafeUnpin for NonUtf8HeaderHandling
impl UnwindSafe for NonUtf8HeaderHandling
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more