Trait pingora_proxy::ProxyHttp

source ·
pub trait ProxyHttp {
    type CTX;

Show 25 methods // Required methods fn new_ctx(&self) -> Self::CTX; fn upstream_peer<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, session: &'life1 mut Session, ctx: &'life2 mut Self::CTX ) -> Pin<Box<dyn Future<Output = Result<Box<HttpPeer>>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait; // Provided methods fn request_filter<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, _session: &'life1 mut Session, _ctx: &'life2 mut Self::CTX ) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>> where Self::CTX: Send + Sync, Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait { ... } fn request_cache_filter( &self, _session: &mut Session, _ctx: &mut Self::CTX ) -> Result<()> { ... } fn cache_key_callback( &self, session: &Session, _ctx: &mut Self::CTX ) -> Result<CacheKey> { ... } fn cache_miss(&self, session: &mut Session, _ctx: &mut Self::CTX) { ... } fn cache_hit_filter<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, _meta: &'life1 CacheMeta, _ctx: &'life2 mut Self::CTX, _req: &'life3 RequestHeader ) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>> where Self::CTX: Send + Sync, Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait { ... } fn proxy_upstream_filter<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, _session: &'life1 mut Session, _ctx: &'life2 mut Self::CTX ) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>> where Self::CTX: Send + Sync, Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait { ... } fn response_cache_filter( &self, _session: &Session, _resp: &ResponseHeader, _ctx: &mut Self::CTX ) -> Result<RespCacheable> { ... } fn cache_vary_filter( &self, _meta: &CacheMeta, _ctx: &mut Self::CTX, _req: &RequestHeader ) -> Option<HashBinary> { ... } fn upstream_request_filter<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, _session: &'life1 mut Session, _upstream_request: &'life2 mut RequestHeader, _ctx: &'life3 mut Self::CTX ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>> where Self::CTX: Send + Sync, Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait { ... } fn upstream_response_filter( &self, _session: &mut Session, _upstream_response: &mut ResponseHeader, _ctx: &mut Self::CTX ) { ... } fn response_filter<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, _session: &'life1 mut Session, _upstream_response: &'life2 mut ResponseHeader, _ctx: &'life3 mut Self::CTX ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>> where Self::CTX: Send + Sync, Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait { ... } fn upstream_response_body_filter( &self, _session: &mut Session, _body: &mut Option<Bytes>, _end_of_stream: bool, _ctx: &mut Self::CTX ) { ... } fn response_body_filter( &self, _session: &mut Session, _body: &mut Option<Bytes>, _end_of_stream: bool, _ctx: &mut Self::CTX ) -> Result<Option<Duration>> where Self::CTX: Send + Sync { ... } fn response_trailer_filter<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, _session: &'life1 mut Session, _upstream_trailers: &'life2 mut HeaderMap, _ctx: &'life3 mut Self::CTX ) -> Pin<Box<dyn Future<Output = Result<Option<Bytes>>> + Send + 'async_trait>> where Self::CTX: Send + Sync, Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait { ... } fn logging<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, _session: &'life1 mut Session, _e: Option<&'life2 Error>, _ctx: &'life3 mut Self::CTX ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>> where Self::CTX: Send + Sync, Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait { ... } fn suppress_error_log( &self, _session: &Session, _ctx: &Self::CTX, _error: &Error ) -> bool { ... } fn error_while_proxy( &self, peer: &HttpPeer, session: &mut Session, e: Box<Error>, _ctx: &mut Self::CTX, client_reused: bool ) -> Box<Error> { ... } fn fail_to_connect( &self, _session: &mut Session, _peer: &HttpPeer, _ctx: &mut Self::CTX, e: Box<Error> ) -> Box<Error> { ... } fn fail_to_proxy<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, session: &'life1 mut Session, e: &'life2 Error, _ctx: &'life3 mut Self::CTX ) -> Pin<Box<dyn Future<Output = u16> + Send + 'async_trait>> where Self::CTX: Send + Sync, Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait { ... } fn should_serve_stale( &self, _session: &mut Session, _ctx: &mut Self::CTX, error: Option<&Error> ) -> bool { ... } fn connected_to_upstream<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>( &'life0 self, _session: &'life1 mut Session, _reused: bool, _peer: &'life2 HttpPeer, _fd: RawFd, _digest: Option<&'life3 Digest>, _ctx: &'life4 mut Self::CTX ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>> where Self::CTX: Send + Sync, Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, 'life4: 'async_trait { ... } fn request_summary(&self, session: &Session, _ctx: &Self::CTX) -> String { ... } fn is_purge(&self, _session: &Session, _ctx: &Self::CTX) -> bool { ... }
}
Expand description

The interface to control the HTTP proxy

The methods in ProxyHttp are filters/callbacks which will be performed on all requests at their particular stage (if applicable).

If any of the filters returns Result::Err, the request will fail, and the error will be logged.

Required Associated Types§

source

type CTX

The per request object to share state across the different filters

Required Methods§

source

fn new_ctx(&self) -> Self::CTX

Define how the ctx should be created.

source

fn upstream_peer<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, session: &'life1 mut Session, ctx: &'life2 mut Self::CTX ) -> Pin<Box<dyn Future<Output = Result<Box<HttpPeer>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Define where the proxy should send the request to.

The returned HttpPeer contains the information regarding where and how this request should be forwarded to.

Provided Methods§

source

fn request_filter<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, _session: &'life1 mut Session, _ctx: &'life2 mut Self::CTX ) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>
where Self::CTX: Send + Sync, Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Handle the incoming request.

In this phase, users can parse, validate, rate limit, perform access control and/or return a response for this request.

If the user already sent a response to this request, an Ok(true) should be returned so that the proxy would exit. The proxy continues to the next phases when Ok(false) is returned.

By default this filter does nothing and returns Ok(false).

source

fn request_cache_filter( &self, _session: &mut Session, _ctx: &mut Self::CTX ) -> Result<()>

This filter decides if the request is cacheable and what cache backend to use

The caller can interact with Session.cache to enable caching.

By default this filter does nothing which effectively disables caching.

source

fn cache_key_callback( &self, session: &Session, _ctx: &mut Self::CTX ) -> Result<CacheKey>

This callback generates the cache key

This callback is called only when cache is enabled for this request

By default this callback returns a default cache key generated from the request.

source

fn cache_miss(&self, session: &mut Session, _ctx: &mut Self::CTX)

This callback is invoked when a cacheable response is ready to be admitted to cache

source

fn cache_hit_filter<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, _meta: &'life1 CacheMeta, _ctx: &'life2 mut Self::CTX, _req: &'life3 RequestHeader ) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>
where Self::CTX: Send + Sync, Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

This filter is called after a successful cache lookup and before the cache asset is ready to be used.

This filter allow the user to log or force expire the asset.

source

fn proxy_upstream_filter<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, _session: &'life1 mut Session, _ctx: &'life2 mut Self::CTX ) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>
where Self::CTX: Send + Sync, Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Decide if a request should continue to upstream after not being served from cache.

returns: Ok(true) if the request should continue, Ok(false) if a response was written by the callback and the session should be finished, or an error

This filter can be used for deferring checks like rate limiting or access control to when they actually needed after cache miss.

source

fn response_cache_filter( &self, _session: &Session, _resp: &ResponseHeader, _ctx: &mut Self::CTX ) -> Result<RespCacheable>

Decide if the response is cacheable

source

fn cache_vary_filter( &self, _meta: &CacheMeta, _ctx: &mut Self::CTX, _req: &RequestHeader ) -> Option<HashBinary>

Decide how to generate cache vary key from both request and response

None means no variance is needed.

source

fn upstream_request_filter<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, _session: &'life1 mut Session, _upstream_request: &'life2 mut RequestHeader, _ctx: &'life3 mut Self::CTX ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self::CTX: Send + Sync, Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Modify the request before it is sent to the upstream

Unlike Self::request_filter(), this filter allows to change the request headers to send to the upstream.

source

fn upstream_response_filter( &self, _session: &mut Session, _upstream_response: &mut ResponseHeader, _ctx: &mut Self::CTX )

Modify the response header from the upstream

The modification is before caching, so any change here will be stored in the cache if enabled.

Responses served from cache won’t trigger this filter. If the cache needed revalidation, only the 304 from upstream will trigger the filter (though it will be merged into the cached header, not served directly to downstream).

source

fn response_filter<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, _session: &'life1 mut Session, _upstream_response: &'life2 mut ResponseHeader, _ctx: &'life3 mut Self::CTX ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self::CTX: Send + Sync, Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Modify the response header before it is send to the downstream

The modification is after caching. This filter is called for all responses including responses served from cache.

source

fn upstream_response_body_filter( &self, _session: &mut Session, _body: &mut Option<Bytes>, _end_of_stream: bool, _ctx: &mut Self::CTX )

Similar to Self::upstream_response_filter() but for response body

This function will be called every time a piece of response body is received. The body is not the entire response body.

source

fn response_body_filter( &self, _session: &mut Session, _body: &mut Option<Bytes>, _end_of_stream: bool, _ctx: &mut Self::CTX ) -> Result<Option<Duration>>
where Self::CTX: Send + Sync,

Similar to Self::response_filter() but for response body chunks

source

fn response_trailer_filter<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, _session: &'life1 mut Session, _upstream_trailers: &'life2 mut HeaderMap, _ctx: &'life3 mut Self::CTX ) -> Pin<Box<dyn Future<Output = Result<Option<Bytes>>> + Send + 'async_trait>>
where Self::CTX: Send + Sync, Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

When a trailer is received.

source

fn logging<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, _session: &'life1 mut Session, _e: Option<&'life2 Error>, _ctx: &'life3 mut Self::CTX ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self::CTX: Send + Sync, Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

This filter is called when the entire response is sent to the downstream successfully or there is a fatal error that terminate the request.

An error log is already emitted if there is any error. This phase is used for collecting metrics and sending access logs.

source

fn suppress_error_log( &self, _session: &Session, _ctx: &Self::CTX, _error: &Error ) -> bool

A value of true means that the log message will be suppressed. The default value is false.

source

fn error_while_proxy( &self, peer: &HttpPeer, session: &mut Session, e: Box<Error>, _ctx: &mut Self::CTX, client_reused: bool ) -> Box<Error>

This filter is called when there is an error after a connection is established (or reused) to the upstream.

source

fn fail_to_connect( &self, _session: &mut Session, _peer: &HttpPeer, _ctx: &mut Self::CTX, e: Box<Error> ) -> Box<Error>

This filter is called when there is an error in the process of establishing a connection to the upstream.

In this filter the user can decide whether the error is retry-able by marking the error e.

If the error can be retried, Self::upstream_peer() will be called again so that the user can decide whether to send the request to the same upstream or another upstream that is possibly available.

source

fn fail_to_proxy<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, session: &'life1 mut Session, e: &'life2 Error, _ctx: &'life3 mut Self::CTX ) -> Pin<Box<dyn Future<Output = u16> + Send + 'async_trait>>
where Self::CTX: Send + Sync, Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

This filter is called when the request encounters a fatal error.

Users may write an error response to the downstream if the downstream is still writable.

The response status code of the error response maybe returned for logging purpose.

source

fn should_serve_stale( &self, _session: &mut Session, _ctx: &mut Self::CTX, error: Option<&Error> ) -> bool

Decide whether should serve stale when encountering an error or during revalidation

An implementation should follow https://datatracker.ietf.org/doc/html/rfc9111#section-4.2.4 https://www.rfc-editor.org/rfc/rfc5861#section-4

This filter is only called if cache is enabled.

source

fn connected_to_upstream<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>( &'life0 self, _session: &'life1 mut Session, _reused: bool, _peer: &'life2 HttpPeer, _fd: RawFd, _digest: Option<&'life3 Digest>, _ctx: &'life4 mut Self::CTX ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self::CTX: Send + Sync, Self: Sync + 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, 'life4: 'async_trait,

This filter is called when the request just established or reused a connection to the upstream

This filter allows user to log timing and connection related info.

source

fn request_summary(&self, session: &Session, _ctx: &Self::CTX) -> String

This callback is invoked every time request related error log needs to be generated

Users can define what is important to be written about this request via the returned string.

source

fn is_purge(&self, _session: &Session, _ctx: &Self::CTX) -> bool

Whether the request should be used to invalidate(delete) the HTTP cache

  • true: this request will be used to invalidate the cache.
  • false: this request is a treated as a normal request

Implementors§