Skip to content

Commit

Permalink
Short form esi:vars processing works. Added an example for testing.
Browse files Browse the repository at this point in the history
  • Loading branch information
tyler committed Dec 4, 2024
1 parent 96dfe51 commit b04ea81
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 3 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ members = [
"examples/esi_example_minimal",
"examples/esi_example_advanced_error_handling",
"examples/esi_try_example",
"examples/esi_vars_example",
]

[workspace.package]
Expand Down
22 changes: 19 additions & 3 deletions esi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use fastly::http::request::PendingRequest;
use fastly::http::{header, Method, StatusCode, Url};
use fastly::{mime, Body, Request, Response};
use log::{debug, error, trace};
use std::collections::VecDeque;
use std::collections::{HashMap, VecDeque};
use std::io::{BufRead, Write};

pub use crate::document::{Element, Fragment};
Expand Down Expand Up @@ -142,6 +142,9 @@ impl Processor {
// `root_task` is the root task that will be used to fetch tags in recursive manner
let root_task = &mut Task::new();

// variables
let mut variables = HashMap::new();

let is_escaped = self.configuration.is_escaped_content;
// Call the library to parse fn `parse_tags` which will call the callback function
// on each tag / event it finds in the document.
Expand All @@ -156,6 +159,7 @@ impl Processor {
is_escaped,
&original_request_metadata,
dispatch_fragment_request,
&mut variables,
)
},
)?;
Expand Down Expand Up @@ -393,6 +397,7 @@ fn event_receiver(
is_escaped: bool,
original_request_metadata: &Request,
dispatch_fragment_request: &FragmentRequestDispatcher,
variables: &mut HashMap<String, String>,
) -> Result<()> {
debug!("got {:?}", event);

Expand Down Expand Up @@ -430,12 +435,14 @@ fn event_receiver(
is_escaped,
original_request_metadata,
dispatch_fragment_request,
variables,
)?;
let except_task = task_handler(
except_events,
is_escaped,
original_request_metadata,
dispatch_fragment_request,
variables,
)?;

trace!(
Expand All @@ -450,10 +457,17 @@ fn event_receiver(
});
}
Event::ESI(Tag::Assign { name, value }) => {
// process assignment
variables.insert(name, value);
}
Event::ESI(Tag::Vars { name }) => {
// process vars
if let Some(name) = name {
if let Some(value) = variables.get(&name) {
let value = value.to_owned();
queue.push_back(Element::Raw(value.into_bytes()));
}
} else {
// TODO: long form
}
}
Event::XML(event) => {
debug!("pushing content to buffer, len: {}", queue.len());
Expand All @@ -473,6 +487,7 @@ fn task_handler(
is_escaped: bool,
original_request_metadata: &Request,
dispatch_fragment_request: &FragmentRequestDispatcher,
variables: &mut HashMap<String, String>,
) -> Result<Task> {
let mut task = Task::new();
for event in events {
Expand All @@ -482,6 +497,7 @@ fn task_handler(
is_escaped,
original_request_metadata,
dispatch_fragment_request,
variables,
)?;
}
Ok(task)
Expand Down
6 changes: 6 additions & 0 deletions examples/esi_vars_example/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[target.wasm32-wasi]
rustflags = ["-C", "debuginfo=2"]
runner = "viceroy run -C fastly.toml -- "

[build]
target = "wasm32-wasi"
13 changes: 13 additions & 0 deletions examples/esi_vars_example/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "esi_vars_example"
version.workspace = true
authors.workspace = true
license.workspace = true
edition.workspace = true
publish = false

[dependencies]
fastly = "^0.11"
esi = { path = "../../esi" }
log = "^0.4"
env_logger = "^0.11"
28 changes: 28 additions & 0 deletions examples/esi_vars_example/fastly.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# This file describes a Fastly Compute package. To learn more visit:
# https://developer.fastly.com/reference/fastly-toml/

authors = ["[email protected]"]
description = ""
language = "rust"
manifest_version = 2
name = "esi_example_minimal"
service_id = ""

[local_server]

[local_server.backends]

[local_server.backends.mock-s3]
url = "https://mock-s3.edgecompute.app"
override_host = "mock-s3.edgecompute.app"

[scripts]
build = "cargo build --bin esi_example_minimal --release --target wasm32-wasi --color always"

[setup]

[setup.backends]

[setup.backends.mock-s3]
address = "mock-s3.edgecompute.app"
port = 443
22 changes: 22 additions & 0 deletions examples/esi_vars_example/src/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<title>My Variable Website</title>
</head>
<body>
<header style="background: #f1f1f1; padding: 16px">
<h1>My Variable Website</h1>
</header>
<div class="layout" style="display: flex">
Assigning "YES" to variable...<br>
<esi:assign name="test" value="YES" />
Check (short form): YES=<esi:vars name="test" /><br>
Check (long form): YES=<esi:vars>$(test)</esi:vars><br>

Updating variable to "PERHAPS"...<br>
<esi:assign name="test" value="PERHAPS" />
Check (short form): PERHAPS=<esi:vars name="test" /><br>
Check (long form): PERHAPS=<esi:vars>$(test)</esi:vars><br>
</div>
</body>
</html>
62 changes: 62 additions & 0 deletions examples/esi_vars_example/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use fastly::{http::StatusCode, mime, Error, Request, Response};
use log::info;

fn main() {
env_logger::builder()
.filter(None, log::LevelFilter::Trace)
.init();

if let Err(err) = handle_request(Request::from_client()) {
println!("returning error response");

Response::from_status(StatusCode::INTERNAL_SERVER_ERROR)
.with_body(err.to_string())
.send_to_client();
}
}

fn handle_request(req: Request) -> Result<(), Error> {
if req.get_path() != "/" {
Response::from_status(StatusCode::NOT_FOUND).send_to_client();
return Ok(());
}

// Generate synthetic test response from "index.html" file.
// You probably want replace this with a backend call, e.g. `req.clone_without_body().send("origin_0")`
let mut beresp =
Response::from_body(include_str!("index.html")).with_content_type(mime::TEXT_HTML);

// If the response is HTML, we can parse it for ESI tags.
if beresp
.get_content_type()
.is_some_and(|c| c.subtype() == mime::HTML)
{
let processor = esi::Processor::new(Some(req), esi::Configuration::default());

processor.process_response(
&mut beresp,
None,
Some(&|req| {
info!("Sending request {} {}", req.get_method(), req.get_path());
Ok(req.with_ttl(120).send_async("mock-s3")?.into())
}),
Some(&|req, mut resp| {
info!(
"Received response for {} {}",
req.get_method(),
req.get_path()
);
if !resp.get_status().is_success() {
// Override status so we still insert errors.
resp.set_status(StatusCode::OK);
}
Ok(resp)
}),
)?;
} else {
// Otherwise, we can just return the response.
beresp.send_to_client();
}

Ok(())
}

0 comments on commit b04ea81

Please sign in to comment.