Skip to content

Commit

Permalink
Allow fragments to be generated synthetically (no backend request)
Browse files Browse the repository at this point in the history
  • Loading branch information
kailan committed Oct 11, 2024
1 parent 0e4ce7e commit 51b8bfd
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 24 deletions.
8 changes: 4 additions & 4 deletions esi/src/document.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::VecDeque;

use crate::Result;
use fastly::{http::request::PendingRequest, Request};
use crate::{PendingFragmentContent, Result};
use fastly::Request;
use quick_xml::Writer;

pub struct Fragment {
Expand All @@ -11,8 +11,8 @@ pub struct Fragment {
pub(crate) alt: Option<Result<Request>>,
// Whether to continue on error
pub(crate) continue_on_error: bool,
// The pending request, which can be polled to retrieve the response
pub(crate) pending_request: PendingRequest,
// The pending fragment response, which can be polled to retrieve the content
pub(crate) pending_content: PendingFragmentContent,
}

/// `Task` is combining raw data and an include fragment for both `attempt` and `except` arms
Expand Down
53 changes: 36 additions & 17 deletions esi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,39 @@ pub use crate::error::ExecutionError;
// re-export quick_xml Reader and Writer
pub use quick_xml::{Reader, Writer};

type FragmentRequestDispatcher = dyn Fn(Request) -> Result<Option<PendingRequest>>;
type FragmentRequestDispatcher = dyn Fn(Request) -> Result<PendingFragmentContent>;

type FragmentResponseProcessor = dyn Fn(&mut Request, Response) -> Result<Response>;

/// Representation of a fragment that is either being fetched, has already been fetched (or generated synthetically), or skipped.
pub enum PendingFragmentContent {
PendingRequest(PendingRequest),
CompletedRequest(Response),
NoContent,
}

impl From<PendingRequest> for PendingFragmentContent {
fn from(value: PendingRequest) -> Self {
Self::PendingRequest(value)
}
}

impl From<Response> for PendingFragmentContent {
fn from(value: Response) -> Self {
Self::CompletedRequest(value)
}
}

impl PendingFragmentContent {
fn wait_for_content(self) -> Result<Response> {
Ok(match self {
PendingFragmentContent::PendingRequest(pending_request) => pending_request.wait()?,
PendingFragmentContent::CompletedRequest(response) => response,
PendingFragmentContent::NoContent => Response::from_status(StatusCode::NO_CONTENT),
})
}
}

/// An instance of the ESI processor with a given configuration.
pub struct Processor {
// The original client request metadata, if any.
Expand Down Expand Up @@ -100,7 +129,7 @@ impl Processor {
.unwrap_or_else(|| panic!("no host in request: {}", req.get_url()))
.to_string();
let pending_req = req.send_async(backend)?;
Ok(Some(pending_req))
Ok(pending_req.into())
}
});

Expand Down Expand Up @@ -220,13 +249,13 @@ fn process_include(
mut request,
alt,
continue_on_error,
pending_request,
pending_content,
} = fragment;

// wait for `<esi:include>` request to complete
let resp = match pending_request.wait() {
let resp = match pending_content.wait_for_content() {
Ok(r) => r,
Err(err) => return Err(ExecutionError::RequestError(err)),
Err(err) => return Err(err),
};

let processed_resp = if let Some(process_response) = process_fragment_response {
Expand Down Expand Up @@ -505,23 +534,13 @@ fn send_fragment_request(

let request = req.clone_without_body();

let pending_request = match dispatch_request(req) {
Ok(Some(req)) => req,
Ok(None) => {
debug!("No pending request returned, skipping");
return Ok(None);
}
Err(err) => {
error!("Failed to dispatch request: {:?}", err);
return Err(err);
}
};
let pending_content: PendingFragmentContent = dispatch_request(req)?;

Ok(Some(Fragment {
request,
alt,
continue_on_error,
pending_request,
pending_content,
}))
}

Expand Down
2 changes: 1 addition & 1 deletion examples/esi_example_advanced_error_handling/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ fn main() {
&mut xml_writer,
Some(&|req| {
info!("Sending request {} {}", req.get_method(), req.get_path());
Ok(Some(req.with_ttl(120).send_async("mock-s3")?))
Ok(req.with_ttl(120).send_async("mock-s3")?.into())
}),
Some(&|req, resp| {
info!(
Expand Down
2 changes: 1 addition & 1 deletion examples/esi_example_minimal/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ fn handle_request(req: Request) -> Result<(), Error> {
None,
Some(&|req| {
info!("Sending request {} {}", req.get_method(), req.get_path());
Ok(Some(req.with_ttl(120).send_async("mock-s3")?))
Ok(req.with_ttl(120).send_async("mock-s3")?.into())
}),
Some(&|req, mut resp| {
info!(
Expand Down
2 changes: 1 addition & 1 deletion examples/esi_try_example/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ fn handle_request(req: Request) -> Result<(), Error> {
None,
Some(&|req| {
info!("Sending request {} {}", req.get_method(), req.get_path());
Ok(Some(req.with_ttl(120).send_async("mock-s3")?))
Ok(req.with_ttl(120).send_async("mock-s3")?.into())
}),
Some(&|req, resp| {
info!(
Expand Down

0 comments on commit 51b8bfd

Please sign in to comment.