Skip to main content

Processor

Struct Processor 

Source
pub struct Processor { /* private fields */ }
Expand description

A processor for handling ESI responses

The Processor maintains state and configuration for processing ESI directives in HTML/XML content. It handles fragment inclusion, variable substitution, and conditional processing according to the ESI specification.

§Fields

  • ctx - Evaluation context containing variables and request metadata
  • configuration - Configuration settings controlling ESI processing behavior

§Example

use esi::{Processor, Configuration};
use fastly::Request;

// Create a configuration (assuming Configuration implements Default)
let config = Configuration::default();

// Optionally, create a Request (assuming Request can be constructed or mocked)
let request = Request::get("http://example.com/");

// Initialize the Processor with optional request metadata
let processor = Processor::new(Some(request), config);

Implementations§

Source§

impl Processor

Implementation of the main Processor methods driving ESI processing

This impl block contains the core logic for processing ESI documents, including the main streaming loop, fragment dispatching, and queue management. The DocumentHandler implementation above delegates to these methods for the actual processing work, allowing the handler to focus on interfacing with the streaming architecture and the evaluation context.

Source

pub fn new( original_request_metadata: Option<Request>, configuration: Configuration, ) -> Self

Source

pub const fn context(&self) -> &EvalContext

Get the evaluation context (for testing)

Provides access to the processor’s internal state including variables, response headers, status code, and body overrides set by ESI functions.

Source

pub fn process_response( self, src_stream: &mut Response, client_response_metadata: Option<Response>, dispatch_fragment_request: Option<&dyn Fn(Request, Option<u32>) -> Result<PendingFragmentContent>>, process_fragment_response: Option<&dyn Fn(&mut Request, Response) -> Result<Response>>, ) -> Result<()>

Process a response body as an ESI document. Consumes the response body.

This method processes ESI directives in the response body while streaming the output to the client, minimizing memory usage for large responses. It handles ESI includes, conditionals, and variable substitution according to the ESI specification.

§Response Manipulation Functions

ESI functions can modify the response that gets sent to the client:

§$add_header(name, value)

Adds a custom header to the response:

<esi:vars>$add_header('X-Custom-Header', 'my-value')</esi:vars>
§$set_response_code(code [, body])

Sets the HTTP status code and optionally replaces the response body:

<esi:vars>$set_response_code(404, 'Page not found')</esi:vars>
§$set_redirect(url [, code])

Sets up an HTTP redirect (default 302):

<esi:vars>$set_redirect('https://example.com/new-page')</esi:vars>
<esi:vars>$set_redirect('https://example.com/moved', 301)</esi:vars>

Note: These functions modify the response metadata that process_response will use when sending the response to the client. The headers, status code, and body override are buffered during processing and applied when the response is sent.

§Arguments
  • src_stream - Source HTTP response containing ESI markup to process
  • client_response_metadata - Optional response metadata (headers, status) to send to client
  • dispatch_fragment_request - Optional callback for customizing fragment request handling
  • process_fragment_response - Optional callback for processing fragment responses
§Returns
  • Result<()> - Ok if processing completed successfully, Error if processing failed
§Example
use fastly::Response;
use esi::{Processor, Configuration};

// Create a processor
let processor = Processor::new(None, Configuration::default());

// Create a response with ESI markup
let mut response = Response::new();
response.set_body("<esi:include src='http://example.com/header.html'/>");

// Define a simple fragment dispatcher
fn default_fragment_dispatcher(req: fastly::Request, maxwait: Option<u32>) -> esi::Result<esi::PendingFragmentContent> {
    Ok(esi::PendingFragmentContent::CompletedRequest(
        Box::new(fastly::Response::from_body("Fragment content"))
    ))
}
// Process the response, streaming the resulting document directly to the client
processor.process_response(
    &mut response,
    None,
    Some(&default_fragment_dispatcher),
    None
)?;
§Errors

Returns error if:

  • ESI processing fails
  • Stream writing fails
  • Fragment requests fail
Source

pub fn process_stream( &mut self, src_stream: impl BufRead, output_writer: &mut impl Write, dispatch_fragment_request: Option<&dyn Fn(Request, Option<u32>) -> Result<PendingFragmentContent>>, process_fragment_response: Option<&dyn Fn(&mut Request, Response) -> Result<Response>>, ) -> Result<()>

Process an ESI stream from any BufRead into a Write.

  • Reads in 8 KB chunks, buffering only what the parser needs
  • Parses incrementally; writes content as soon as it’s parsed
  • Dispatches includes immediately; waits for them later in document order
  • Uses select() to harvest in-flight includes while preserving output order

For Fastly Response bodies, prefer [process_response], which wires up cache headers and response metadata for you.

§Arguments
  • src_stream - BufRead source containing ESI markup (streams in chunks)
  • output_writer - Writer to stream processed output to (writes immediately)
  • dispatch_fragment_request - Optional handler for fragment requests
  • process_fragment_response - Optional processor for fragment responses
§Returns
  • Result<()> - Ok if processing completed successfully
§Errors

Returns error if:

  • ESI markup parsing fails or document is malformed
  • Fragment requests fail (unless continue_on_error is set)
  • Input reading or output writing fails
  • Invalid UTF-8 encoding encountered

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<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> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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> 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 = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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