pingora_proxy

Trait ProxyHttp

Source
pub trait ProxyHttp {
    type CTX;

Show 31 methods // Required methods fn new_ctx(&self) -> Self::CTX; async fn upstream_peer( &self, session: &mut Session, ctx: &mut Self::CTX, ) -> Result<Box<HttpPeer>>; // Provided methods fn init_downstream_modules(&self, modules: &mut HttpModules) { ... } async fn request_filter( &self, _session: &mut Session, _ctx: &mut Self::CTX, ) -> Result<bool> where Self::CTX: Send + Sync { ... } async fn early_request_filter( &self, _session: &mut Session, _ctx: &mut Self::CTX, ) -> Result<()> where Self::CTX: Send + Sync { ... } async fn request_body_filter( &self, _session: &mut Session, _body: &mut Option<Bytes>, _end_of_stream: bool, _ctx: &mut Self::CTX, ) -> Result<()> where Self::CTX: Send + Sync { ... } 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) { ... } async fn cache_hit_filter( &self, _session: &Session, _meta: &CacheMeta, _ctx: &mut Self::CTX, ) -> Result<bool> where Self::CTX: Send + Sync { ... } async fn proxy_upstream_filter( &self, _session: &mut Session, _ctx: &mut Self::CTX, ) -> Result<bool> where Self::CTX: Send + Sync { ... } 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 cache_not_modified_filter( &self, session: &Session, resp: &ResponseHeader, _ctx: &mut Self::CTX, ) -> Result<bool> { ... } async fn upstream_request_filter( &self, _session: &mut Session, _upstream_request: &mut RequestHeader, _ctx: &mut Self::CTX, ) -> Result<()> where Self::CTX: Send + Sync { ... } fn upstream_response_filter( &self, _session: &mut Session, _upstream_response: &mut ResponseHeader, _ctx: &mut Self::CTX, ) { ... } async fn response_filter( &self, _session: &mut Session, _upstream_response: &mut ResponseHeader, _ctx: &mut Self::CTX, ) -> Result<()> where Self::CTX: Send + Sync { ... } fn upstream_response_body_filter( &self, _session: &mut Session, _body: &mut Option<Bytes>, _end_of_stream: bool, _ctx: &mut Self::CTX, ) { ... } fn upstream_response_trailer_filter( &self, _session: &mut Session, _upstream_trailers: &mut HeaderMap, _ctx: &mut Self::CTX, ) -> Result<()> { ... } 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 { ... } async fn response_trailer_filter( &self, _session: &mut Session, _upstream_trailers: &mut HeaderMap, _ctx: &mut Self::CTX, ) -> Result<Option<Bytes>> where Self::CTX: Send + Sync { ... } async fn logging( &self, _session: &mut Session, _e: Option<&Error>, _ctx: &mut Self::CTX, ) where Self::CTX: Send + Sync { ... } 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> { ... } async fn fail_to_proxy( &self, session: &mut Session, e: &Error, _ctx: &mut Self::CTX, ) -> u16 where Self::CTX: Send + Sync { ... } fn should_serve_stale( &self, _session: &mut Session, _ctx: &mut Self::CTX, error: Option<&Error>, ) -> bool { ... } async fn connected_to_upstream( &self, _session: &mut Session, _reused: bool, _peer: &HttpPeer, _fd: RawFd, _digest: Option<&Digest>, _ctx: &mut Self::CTX, ) -> Result<()> where Self::CTX: Send + Sync { ... } fn request_summary(&self, session: &Session, _ctx: &Self::CTX) -> String { ... } fn is_purge(&self, _session: &Session, _ctx: &Self::CTX) -> bool { ... } fn purge_response_filter( &self, _session: &Session, _ctx: &mut Self::CTX, _purge_status: PurgeStatus, _purge_response: &mut Cow<'static, ResponseHeader>, ) -> Result<()> { ... }
}
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

async fn upstream_peer( &self, session: &mut Session, ctx: &mut Self::CTX, ) -> Result<Box<HttpPeer>>

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 init_downstream_modules(&self, modules: &mut HttpModules)

Set up downstream modules.

In this phase, users can add or configure HttpModules before the server starts up.

In the default implementation of this method, ResponseCompressionBuilder is added and disabled.

Source

async fn request_filter( &self, _session: &mut Session, _ctx: &mut Self::CTX, ) -> Result<bool>
where Self::CTX: Send + Sync,

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

async fn early_request_filter( &self, _session: &mut Session, _ctx: &mut Self::CTX, ) -> Result<()>
where Self::CTX: Send + Sync,

Handle the incoming request before any downstream module is executed.

This function is similar to Self::request_filter() but executes before any other logic, including downstream module logic. The main purpose of this function is to provide finer grained control of the behavior of the modules.

Note that because this function is executed before any module that might provide access control or rate limiting, logic should stay in request_filter() if it can in order to be protected by said modules.

Source

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

Handle the incoming request body.

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

The async nature of this function allows to throttle the upload speed and/or executing heavy computation logic such as WAF rules on offloaded threads without blocking the threads who process the requests themselves.

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

async fn cache_hit_filter( &self, _session: &Session, _meta: &CacheMeta, _ctx: &mut Self::CTX, ) -> Result<bool>
where Self::CTX: Send + Sync,

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

async fn proxy_upstream_filter( &self, _session: &mut Session, _ctx: &mut Self::CTX, ) -> Result<bool>
where Self::CTX: Send + Sync,

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 cache_not_modified_filter( &self, session: &Session, resp: &ResponseHeader, _ctx: &mut Self::CTX, ) -> Result<bool>

Decide if the incoming request’s condition fails against the cached response.

Returning Ok(true) means that the response does not match against the condition, and that the proxy can return 304 Not Modified downstream.

An example is a conditional GET request with If-None-Match: "foobar". If the cached response contains the ETag: "foobar", then the condition fails, and 304 Not Modified should be returned. Else, the condition passes which means the full 200 OK response must be sent.

Source

async fn upstream_request_filter( &self, _session: &mut Session, _upstream_request: &mut RequestHeader, _ctx: &mut Self::CTX, ) -> Result<()>
where Self::CTX: Send + Sync,

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

async fn response_filter( &self, _session: &mut Session, _upstream_response: &mut ResponseHeader, _ctx: &mut Self::CTX, ) -> Result<()>
where Self::CTX: Send + Sync,

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 upstream_response_trailer_filter( &self, _session: &mut Session, _upstream_trailers: &mut HeaderMap, _ctx: &mut Self::CTX, ) -> Result<()>

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

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

async fn response_trailer_filter( &self, _session: &mut Session, _upstream_trailers: &mut HeaderMap, _ctx: &mut Self::CTX, ) -> Result<Option<Bytes>>
where Self::CTX: Send + Sync,

Similar to Self::response_filter() but for response trailers. Note, returning an Ok(Some(Bytes)) will result in the downstream response trailers being written to the response body.

TODO: make this interface more intuitive

Source

async fn logging( &self, _session: &mut Session, _e: Option<&Error>, _ctx: &mut Self::CTX, )
where Self::CTX: Send + Sync,

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

async fn fail_to_proxy( &self, session: &mut Session, e: &Error, _ctx: &mut Self::CTX, ) -> u16
where Self::CTX: Send + Sync,

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

async fn connected_to_upstream( &self, _session: &mut Session, _reused: bool, _peer: &HttpPeer, _fd: RawFd, _digest: Option<&Digest>, _ctx: &mut Self::CTX, ) -> Result<()>
where Self::CTX: Send + Sync,

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
Source

fn purge_response_filter( &self, _session: &Session, _ctx: &mut Self::CTX, _purge_status: PurgeStatus, _purge_response: &mut Cow<'static, ResponseHeader>, ) -> Result<()>

This filter is called after the proxy cache generates the downstream response to the purge request (to invalidate or delete from the HTTP cache), based on the purge status, which indicates whether the request succeeded or failed.

The filter allows the user to modify or replace the generated downstream response. If the filter returns Err, the proxy will instead send a 500 response.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§