From 51b8bfd2dfa62a95d00aa7de6d4cb37820c87c3e Mon Sep 17 00:00:00 2001 From: Kailan Blanks Date: Fri, 11 Oct 2024 00:03:36 -0400 Subject: [PATCH 1/3] Allow fragments to be generated synthetically (no backend request) --- esi/src/document.rs | 8 +-- esi/src/lib.rs | 53 +++++++++++++------ .../src/main.rs | 2 +- examples/esi_example_minimal/src/main.rs | 2 +- examples/esi_try_example/src/main.rs | 2 +- 5 files changed, 43 insertions(+), 24 deletions(-) diff --git a/esi/src/document.rs b/esi/src/document.rs index 41999c3..1189b8e 100644 --- a/esi/src/document.rs +++ b/esi/src/document.rs @@ -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 { @@ -11,8 +11,8 @@ pub struct Fragment { pub(crate) alt: Option>, // 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 diff --git a/esi/src/lib.rs b/esi/src/lib.rs index 13b176a..5739fda 100644 --- a/esi/src/lib.rs +++ b/esi/src/lib.rs @@ -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>; +type FragmentRequestDispatcher = dyn Fn(Request) -> Result; type FragmentResponseProcessor = dyn Fn(&mut Request, Response) -> Result; +/// 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 for PendingFragmentContent { + fn from(value: PendingRequest) -> Self { + Self::PendingRequest(value) + } +} + +impl From for PendingFragmentContent { + fn from(value: Response) -> Self { + Self::CompletedRequest(value) + } +} + +impl PendingFragmentContent { + fn wait_for_content(self) -> Result { + 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. @@ -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()) } }); @@ -220,13 +249,13 @@ fn process_include( mut request, alt, continue_on_error, - pending_request, + pending_content, } = fragment; // wait for `` 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 { @@ -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, })) } diff --git a/examples/esi_example_advanced_error_handling/src/main.rs b/examples/esi_example_advanced_error_handling/src/main.rs index 3443900..5e93cce 100644 --- a/examples/esi_example_advanced_error_handling/src/main.rs +++ b/examples/esi_example_advanced_error_handling/src/main.rs @@ -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!( diff --git a/examples/esi_example_minimal/src/main.rs b/examples/esi_example_minimal/src/main.rs index b3d0ba5..a6f29be 100644 --- a/examples/esi_example_minimal/src/main.rs +++ b/examples/esi_example_minimal/src/main.rs @@ -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!( diff --git a/examples/esi_try_example/src/main.rs b/examples/esi_try_example/src/main.rs index a283ffc..289d3bc 100644 --- a/examples/esi_try_example/src/main.rs +++ b/examples/esi_try_example/src/main.rs @@ -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!( From 047c08a606aa49662fef930bf2967df74bb313fd Mon Sep 17 00:00:00 2001 From: Kailan Blanks Date: Fri, 11 Oct 2024 17:05:13 +0100 Subject: [PATCH 2/3] Reference `Self` in enum impl rather than full name Co-authored-by: Vadim Getmanshchuk --- esi/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esi/src/lib.rs b/esi/src/lib.rs index 5739fda..1862cfa 100644 --- a/esi/src/lib.rs +++ b/esi/src/lib.rs @@ -49,9 +49,9 @@ impl From for PendingFragmentContent { impl PendingFragmentContent { fn wait_for_content(self) -> Result { Ok(match self { - PendingFragmentContent::PendingRequest(pending_request) => pending_request.wait()?, - PendingFragmentContent::CompletedRequest(response) => response, - PendingFragmentContent::NoContent => Response::from_status(StatusCode::NO_CONTENT), + Self::PendingRequest(pending_request) => pending_request.wait()?, + Self::CompletedRequest(response) => response, + Self::NoContent => Response::from_status(StatusCode::NO_CONTENT), }) } } From 69e005269494ecfb45297cb071e79d378269b947 Mon Sep 17 00:00:00 2001 From: Vadim Getmanshchuk Date: Fri, 11 Oct 2024 14:16:53 -0500 Subject: [PATCH 3/3] Increment `fastly` crate version --- esi/Cargo.toml | 2 +- examples/esi_example_advanced_error_handling/Cargo.toml | 2 +- examples/esi_example_minimal/Cargo.toml | 2 +- examples/esi_try_example/Cargo.toml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esi/Cargo.toml b/esi/Cargo.toml index 9857afe..6649f2a 100644 --- a/esi/Cargo.toml +++ b/esi/Cargo.toml @@ -11,7 +11,7 @@ readme = "./README.md" [dependencies] quick-xml = "0.36.0" thiserror = "^1.0" -fastly = "^0.10" +fastly = "^0.11" log = "^0.4" [dev-dependencies] diff --git a/examples/esi_example_advanced_error_handling/Cargo.toml b/examples/esi_example_advanced_error_handling/Cargo.toml index e8907a7..6886b4c 100644 --- a/examples/esi_example_advanced_error_handling/Cargo.toml +++ b/examples/esi_example_advanced_error_handling/Cargo.toml @@ -7,7 +7,7 @@ edition.workspace = true publish = false [dependencies] -fastly = "^0.10" +fastly = "^0.11" esi = { path = "../../esi" } log = "^0.4" env_logger = "^0.11" diff --git a/examples/esi_example_minimal/Cargo.toml b/examples/esi_example_minimal/Cargo.toml index 54197f8..1d7f6ee 100644 --- a/examples/esi_example_minimal/Cargo.toml +++ b/examples/esi_example_minimal/Cargo.toml @@ -7,7 +7,7 @@ edition.workspace = true publish = false [dependencies] -fastly = "^0.10" +fastly = "^0.11" esi = { path = "../../esi" } log = "^0.4" env_logger = "^0.11" diff --git a/examples/esi_try_example/Cargo.toml b/examples/esi_try_example/Cargo.toml index 6e9cc74..935343e 100644 --- a/examples/esi_try_example/Cargo.toml +++ b/examples/esi_try_example/Cargo.toml @@ -10,7 +10,7 @@ publish = false debug = 1 [dependencies] -fastly = "0.10.1" +fastly = "0.11" esi = { path = "../../esi" } log = "^0.4" env_logger = "0.11.3"