You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
-`<esi:text>` (raw passthrough — content is emitted verbatim, no ESI processing)
17
+
18
+
**Note:** The following tags support nested ESI tags: `<esi:try>`, `<esi:attempt>`, `<esi:except>`, `<esi:choose>`, `<esi:when>`, `<esi:otherwise>`, `<esi:foreach>`, `<esi:function>`, and `<esi:assign>` (long form only).
19
+
20
+
**Dynamic Content Assembly (DCA)**: Both `<esi:include>` and `<esi:eval>` support the `dca` attribute:
21
+
22
+
-`dca="none"` (default): For `include`, inserts raw content without ESI processing. For `eval`, fragment executes in parent's context (variables shared).
23
+
-`dca="esi"`: Two-phase processing: fragment is first processed in an isolated context, then the output is processed in parent's context (variables from phase 1 don't leak, but output can contain ESI tags).
24
+
25
+
**Include vs Eval**:
26
+
27
+
-`<esi:include>`: Fetches content from origin
28
+
-`dca="none"`: Inserts content verbatim (no ESI processing)
29
+
-`dca="esi"`: Parses and evaluates content as ESI before insertion
30
+
-`<esi:eval>`: Fetches content and **always** parses it as ESI (blocking operation)
31
+
-`dca="none"`: Evaluates in parent's namespace (variables from fragment affect parent)
32
+
-`dca="esi"`: **Two-phase**: Phase 1 processes fragment in isolated context (variables set here stay isolated), then Phase 2 processes the output in parent's context (output can contain ESI that accesses parent variables)
33
+
34
+
### Include/Eval Attributes
35
+
36
+
Both `<esi:include>` and `<esi:eval>` support the following attributes:
37
+
38
+
**Required:**
39
+
40
+
-`src="url"` - Source URL to fetch (supports ESI expressions)
-`$ping()` - Returns the string `"pong"` (useful for testing)
179
+
180
+
**Note:** Response manipulation functions are buffered during ESI processing and applied when `process_response()` sends the final response to the client.
181
+
182
+
### User-Defined Functions
183
+
184
+
You can define reusable functions with `<esi:function>` and return values with `<esi:return>`:
-`<esi:function name="...">` defines a function; the body can contain any ESI tags.
196
+
-`<esi:return value="..."/>` returns a value from the function.
197
+
- Inside a function body, `$(ARGS)` is a list of the positional arguments passed to the call, and individual arguments can be accessed with `$(ARGS{0})`, `$(ARGS{1})`, etc.
198
+
- Functions support recursion up to the configured depth (default: 5, see [Configuration](#configuration)).
199
+
- User-defined functions take priority over built-in functions of the same name.
200
+
201
+
### Built-in Variables
202
+
203
+
The following variables are available in ESI expressions:
204
+
205
+
**Request metadata:**
206
+
207
+
-`$(REQUEST_METHOD)` - HTTP method of the original client request (e.g. `GET`)
208
+
-`$(REQUEST_PATH)` - Path component of the request URL
209
+
-`$(QUERY_STRING)` - Raw query string from the request URL
210
+
-`$(REMOTE_ADDR)` - Client IP address
211
+
212
+
**HTTP headers:**
213
+
214
+
-`$(HTTP_<HEADER>)` - Value of the named request header (e.g. `$(HTTP_HOST)`, `$(HTTP_ACCEPT)`)
215
+
-`$(HTTP_COOKIE{'name'})` - Value of a specific cookie from the `Cookie` header
216
+
217
+
**Regex captures:**
218
+
219
+
-`$(MATCHES{0})`, `$(MATCHES{1})`, … - Capture groups from the last `matches` / `matches_i` operator or `<esi:when matchname="...">` test
220
+
221
+
### Configuration
222
+
223
+
`Configuration` controls the processor's runtime behaviour. All fields have sensible defaults and can be customised with builder methods:
224
+
225
+
```rust,no_run
226
+
let config = esi::Configuration::default()
227
+
.with_escaped(true) // unescape HTML entities in URLs (default: true)
228
+
.with_chunk_size(32768) // streaming read buffer, in bytes (default: 16384)
229
+
.with_function_recursion_depth(10) // max depth for user-defined function calls (default: 10)
230
+
.with_caching(esi::CacheConfig {
231
+
is_rendered_cacheable: true,
232
+
rendered_cache_control: true,
233
+
rendered_ttl: Some(600),
234
+
is_includes_cacheable: true,
235
+
includes_default_ttl: Some(300),
236
+
includes_force_ttl: None,
237
+
});
238
+
```
239
+
240
+
| Field | Builder method | Default | Description |
|`is_escaped_content`|`with_escaped(bool)`|`true`| Unescape HTML entities in URLs. Set to `false` for non-HTML templates (e.g. JSON). |
243
+
|`chunk_size`|`with_chunk_size(usize)`|`16384`| Size (bytes) of the read buffer used when streaming ESI input. Larger values may improve throughput; smaller values reduce memory. |
244
+
|`function_recursion_depth`|`max_function_recursion_depth(usize)`|`5`| Maximum call-stack depth for user-defined ESI functions. |
245
+
|`cache`|`with_caching(CacheConfig)`| see below | Cache settings for rendered output and included fragments. |
For advanced use cases, you can process any `BufRead` source and write to any `Write` destination:
329
+
330
+
```rust,no_run
331
+
use std::io::{BufReader, Write};
332
+
use esi::{Processor, Configuration};
333
+
334
+
fn process_custom_stream(
335
+
input: impl std::io::Read,
336
+
output: &mut impl Write,
337
+
) -> Result<(), esi::ESIError> {
338
+
let mut processor = Processor::new(None, Configuration::default());
339
+
340
+
// Process from any readable source
341
+
let reader = BufReader::new(input);
342
+
343
+
processor.process_stream(
344
+
reader,
345
+
output,
346
+
Some(&|req, _maxwait| {
347
+
// Custom fragment dispatcher
348
+
Ok(req.send_async("backend")?.into())
349
+
}),
350
+
None,
351
+
)?;
352
+
353
+
Ok(())
354
+
}
355
+
```
356
+
85
357
See example applications in the [`examples`](./examples) subdirectory or read the hosted documentation at [docs.rs/esi](https://docs.rs/esi). Due to the fact that this processor streams fragments to the client as soon as they are available, it is not possible to return a relevant status code for later errors once we have started streaming the response to the client. For this reason, it is recommended that you refer to the [`esi_example_advanced_error_handling`](./examples/esi_example_advanced_error_handling) application, which allows you to handle errors gracefully by maintaining ownership of the output stream.
0 commit comments