pub struct MessageHandler;Expand description
Message handler for request/response manipulation.
Implementations§
Source§impl MessageHandler
impl MessageHandler
Sourcepub fn upgrade_protocol(
request: &Request<BoxBody<Bytes, Error>>,
) -> Option<String>
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.
Sourcepub fn h2_connect_protocol(
request: &Request<BoxBody<Bytes, Error>>,
) -> Option<String>
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.
Sourcepub fn restore_upgrade_headers(
request: &mut Request<BoxBody<Bytes, Error>>,
protocol: &str,
)
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.
Sourcepub fn upgrade_allowed(protocol: &str, allowed: &[String]) -> bool
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.
Sourcepub fn unsafe_path_reason(path: &str) -> Option<&'static str>
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;parameterafter 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.
Sourcepub fn strip_hop_by_hop_headers(request: &mut Request<BoxBody<Bytes, Error>>)
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.
Sourcepub fn add_forwarding_headers(
request: &mut Request<BoxBody<Bytes, Error>>,
client_addr: SocketAddr,
proto: &str,
trust_client: bool,
)
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.
Sourcepub fn rewrite_host_header(
request: &mut Request<BoxBody<Bytes, Error>>,
upstream_host: &str,
)
pub fn rewrite_host_header( request: &mut Request<BoxBody<Bytes, Error>>, upstream_host: &str, )
Rewrite the Host header for upstream.
Sourcepub fn strip_path_prefix(
request: &mut Request<BoxBody<Bytes, Error>>,
prefix: &str,
)
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.
Sourcepub fn apply_route_headers(
request: &mut Request<BoxBody<Bytes, Error>>,
route: &Route,
)
pub fn apply_route_headers( request: &mut Request<BoxBody<Bytes, Error>>, route: &Route, )
Apply route-specific header modifications.
Sourcepub fn error_response(
status: StatusCode,
message: &str,
) -> Response<BoxBody<Bytes, Error>>
pub fn error_response( status: StatusCode, message: &str, ) -> Response<BoxBody<Bytes, Error>>
Create a synthetic error response.
Sourcepub fn bad_request(message: &str) -> Response<BoxBody<Bytes, Error>>
pub fn bad_request(message: &str) -> Response<BoxBody<Bytes, Error>>
Create a 400 Bad Request response.
Sourcepub fn bad_gateway(message: &str) -> Response<BoxBody<Bytes, Error>>
pub fn bad_gateway(message: &str) -> Response<BoxBody<Bytes, Error>>
Create a 502 Bad Gateway response.
Create a 503 Service Unavailable response.
Sourcepub fn request_host(request: &Request<impl Body>) -> String
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.
Sourcepub fn gateway_timeout(message: &str) -> Response<BoxBody<Bytes, Error>>
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.
Auto Trait Implementations§
impl Freeze for MessageHandler
impl RefUnwindSafe for MessageHandler
impl Send for MessageHandler
impl Sync for MessageHandler
impl Unpin for MessageHandler
impl UnsafeUnpin for MessageHandler
impl UnwindSafe for MessageHandler
Blanket Implementations§
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
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> 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