Skip to main content

MessageHandler

Struct MessageHandler 

Source
pub struct MessageHandler;
Expand description

Message handler for request/response manipulation.

Implementations§

Source§

impl MessageHandler

Source

pub fn upgrade_protocol( request: &Request<BoxBody<Bytes, Error>>, ) -> Option<String>

The protocol a request is asking to upgrade to, if it is a valid upgrade request.

Requires both Upgrade: <proto> and an upgrade token in Connection, per RFC 9110 section 7.8 – Upgrade alone is not a request to switch. HTTP/2 is excluded deliberately: it carries no Upgrade header and negotiates extended CONNECT instead (RFC 8441), which is not implemented.

Source

pub fn h2_connect_protocol( request: &Request<BoxBody<Bytes, Error>>, ) -> Option<String>

The protocol an HTTP/2 extended CONNECT is asking for (RFC 8441).

HTTP/2 has no Upgrade; a WebSocket is opened with :method = CONNECT plus a :protocol pseudo-header, which hyper surfaces as a hyper::ext::Protocol extension. This is only ever offered when the listener advertised SETTINGS_ENABLE_CONNECT_PROTOCOL.

Source

pub fn restore_upgrade_headers( request: &mut Request<BoxBody<Bytes, Error>>, protocol: &str, )

Re-apply the upgrade headers that Self::strip_hop_by_hop_headers took.

An upgrade is the one case where these headers legitimately travel to the next hop. Only a normalised Connection: upgrade and the requested protocol go back – not whatever token list the client sent – so the carve-out cannot be used to smuggle other headers through.

Source

pub fn upgrade_allowed(protocol: &str, allowed: &[String]) -> bool

Whether protocol, as returned by Self::upgrade_protocol or Self::h2_connect_protocol, is one the proxy may tunnel.

An exact, case-insensitive match against allowed – so a request for several protocols at once (Upgrade: websocket, h2c) is not a match for any of them, and is declined.

Source

pub fn unsafe_path_reason(path: &str) -> Option<&'static str>

Why a request path cannot be routed safely, if it cannot.

Routes match the path as sent, and a backend resolves it after decoding and normalising – so any path the two would read differently is a way past a route’s path rules. /public/../admin matched the /public route and was forwarded verbatim, to a backend that served /admin. Refused:

  • dot-segments (. and ..), literal or percent-encoded in any case, and with a ;parameter after them, which Tomcat-style servers strip before resolving;
  • an encoded slash or backslash (%2f, %5c), which a backend may decode into a separator the route never saw;
  • a literal backslash, which some servers treat as a separator.

Refusing rather than normalising: a client that sends these is either probing or broken, and normalising would mean the proxy and the backend each have to agree with a third reading of the path.

Source

pub fn strip_hop_by_hop_headers(request: &mut Request<BoxBody<Bytes, Error>>)

Remove hop-by-hop headers before forwarding, per RFC 9110 section 7.6.1.

Two sets go: the standard hop-by-hop headers, and every header named as a token in the incoming Connection field. Call this before Self::add_forwarding_headers – a client that names x-forwarded-for in Connection then strips only its own inbound value, and we set a fresh one afterwards, rather than being able to suppress ours.

Source

pub fn add_forwarding_headers( request: &mut Request<BoxBody<Bytes, Error>>, client_addr: SocketAddr, proto: &str, trust_client: bool, )

Add X-Forwarded-* headers to a request.

A backend uses these to decide who the client is – for its logs, its own rate limits, its IP allow-lists – so a value the client wrote is a value the client chose. Unless trust_client is set (server.trust_forwarded_headers), everything the client sent is replaced with what the proxy saw: X-Forwarded-For and X-Real-IP become the socket’s peer address, and Forwarded is removed. It used to be appended to, set only if absent, and passed through, which let any client claim any address.

With trust_client, the client is another proxy: its chain is kept and this hop appended to X-Forwarded-For and Forwarded, and the X-Forwarded-Proto and X-Forwarded-Host it set are left as they are, since they describe the original request better than this hop can. X-Real-IP is still the peer address: it names one address, and the one this proxy saw is the one it can vouch for.

Source

pub fn rewrite_host_header( request: &mut Request<BoxBody<Bytes, Error>>, upstream_host: &str, )

Rewrite the Host header for upstream.

Source

pub fn strip_path_prefix( request: &mut Request<BoxBody<Bytes, Error>>, prefix: &str, )

Strip path prefix from request URI.

Only on a segment boundary, by the same rule routes match with (crate::config::path_has_prefix): /api comes off /api/users but not off /apis.

Source

pub fn apply_route_headers( request: &mut Request<BoxBody<Bytes, Error>>, route: &Route, )

Apply route-specific header modifications.

Source

pub fn error_response( status: StatusCode, message: &str, ) -> Response<BoxBody<Bytes, Error>>

Create a synthetic error response.

Source

pub fn bad_request(message: &str) -> Response<BoxBody<Bytes, Error>>

Create a 400 Bad Request response.

Source

pub fn bad_gateway(message: &str) -> Response<BoxBody<Bytes, Error>>

Create a 502 Bad Gateway response.

Source

pub fn service_unavailable(message: &str) -> Response<BoxBody<Bytes, Error>>

Create a 503 Service Unavailable response.

Source

pub fn request_host(request: &Request<impl Body>) -> String

The host a request is for, without its port.

Not just the Host header. HTTP/2 has no Host: RFC 9113 section 8.3.1 replaces it with the :authority pseudo-header, which reaches us on the URI. Reading only the header therefore yields an empty host for every h2 and h2c request, and a route with a match.host matches nothing – confirmed against a running proxy, where the same host-matched route answered 200 over HTTP/1.1 and 404 over HTTP/2.

add_forwarding_headers already had this fallback for x-forwarded-host; route selection did not.

Source

pub fn gateway_timeout(message: &str) -> Response<BoxBody<Bytes, Error>>

Create a 504 Gateway Timeout response.

Takes a message so the body can say how long the request waited. A bare “Gateway Timeout” leaves the caller unable to tell a route configured with one second from an upstream that is genuinely wedged.

Source

pub fn too_many_requests() -> Response<BoxBody<Bytes, Error>>

Create a 429 Too Many Requests response.

Source

pub fn not_found() -> Response<BoxBody<Bytes, Error>>

Create a 404 Not Found response.

Source

pub fn not_implemented(message: &str) -> Response<BoxBody<Bytes, Error>>

Create a 501 Not Implemented response.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

Source§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

Source§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

Source§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more