Snakeway v0.15.0
Highlights
WASM devices
Snakeway now supports extending the proxy with WASM devices: custom traffic logic written in any language that compiles to a WebAssembly component.
Devices run in a sandboxed Wasmtime runtime (component model, snakeway:device@0.4.0) with access to request and
response context, a host API for logging and metrics, and a typed configuration map.
A bug in a device cannot crash the proxy, and each device runs in a memory-limited sandbox.
Devices are declared in a device file under device.d/:
wasm_devices = [
{
name = "my-device"
enable = true
path = "/etc/snakeway/devices/my_device.wasm"
fail_policy = "open" # "open" or "closed" on trap, timeout, or load error
timeout_ms = 5 # per-hook epoch deadline
body_buffer_max = 0 # 0 = streaming; > 0 buffers up to N bytes
hooks = ["on_request"]
config = {
api_key = "secret-value"
}
}
]
Hooks can inspect and modify request and response headers and bodies.
A reference JWT auth device ships alongside the runtime as a worked example, and it models
secure identity handling for anyone adapting it.
It rejects tokens that are missing required claims or signed with a secret that is too short,
and it returns a generic error rather than revealing which check failed.
It also strips client-supplied identity headers such as x-user-id and x-tenant-id before a
request is forwarded, so a caller cannot spoof identity, including on public paths that bypass
authentication.
The WIT interface (snakeway:device@0.4.0) may change in future releases.
Engine-wide resource limits for the shared WASM runtime are set with the optional wasm block in
server.
max_concurrent_executions caps how many device hooks run at once, and max_memory_bytes caps the
memory a single execution may use.
Both default to Snakeway's previous built-in values, so existing configurations are unaffected.
See the Server block for the field reference.
See Authoring WASM Devices for the full guide.
HTTP/2 server tuning
Listeners with enable_http2 = true accept an optional http2 block that tunes the HTTP/2
server parameters advertised to clients. Every field is optional and falls back to its default
when unset.
bind = {
interface = "0.0.0.0"
port = 443
enable_http2 = true
http2 = {
max_concurrent_streams = 100
max_header_list_size = 65536
initial_window_size = 65535
initial_connection_window_size = 1048576
}
}
See HTTP/2 settings for the field reference.
Upstream connection tuning and reuse fix
This release remediates an upstream connection reuse issue and adds explicit control over
upstream connection behavior through the new upstream block (see Breaking Changes
for the relocation of existing fields).
Two new timeout settings are available:
connection_timeout_secondsbounds how long a connect (TCP plus the TLS handshake) may take before failing.read_timeout_secondsbounds a stalled or wedged origin without breaking slow-but-progressing or streaming responses; the timer resets on every read and is not applied to websocket upgrades.
Both are optional and disabled when omitted, preserving v0.14.0 behavior.
upstream {
connection_pool_size = 256
connection_timeout_seconds = 10
read_timeout_seconds = 60
}
See the Server block for the full field reference.
Inspecting effective configuration
snakeway config dump gained a populated-spec representation.
Run snakeway config dump --repr populated-spec to print your configuration with every optional
block and field filled in with its default value.
This shows the effective settings the proxy will apply without starting it, which is useful for
confirming what a partial config actually resolves to.
The output format is selectable with --format hcl, --format json, or --format yaml.
snakeway config dump --repr populated-spec --format hcl
Breaking Changes
Upstream tuning consolidated into a single upstream block
Upstream connection settings are now grouped under one upstream block inside server.
Two settings that lived elsewhere in v0.14.0 have moved into it:
- The top-level
upstream_source_addressesblock is nowupstream.source_addresses. - The
performance.upstream_connection_pool_sizefield is nowupstream.connection_pool_size.
The upstream block also introduces connection_timeout_seconds and read_timeout_seconds,
which did not exist in v0.14.0.
Before (v0.14.0):
server {
performance {
work_stealing = true
upstream_connection_pool_size = 128
}
upstream_source_addresses {
ipv4 = ["10.0.1.5"]
ipv6 = ["fd00::1"]
}
}
After (v0.15.0):
server {
performance {
work_stealing = true
}
upstream {
connection_pool_size = 128
connection_timeout_seconds = 10 # new, omit to disable, but you probably want this
read_timeout_seconds = 60 # new, omit to disable, but you probably want this
source_addresses {
ipv4 = ["10.0.1.5"]
ipv6 = ["fd00::1"]
}
}
}
A config that still uses upstream_source_addresses or performance.upstream_connection_pool_size
is rejected at load time, and the proxy refuses to start until it is updated.
What to do: move upstream_connection_pool_size out of performance into the new upstream
block as connection_pool_size, and move the upstream_source_addresses block under upstream
as source_addresses. No values need to change.
Upgrade Notes
Run snakeway config check before upgrading.
If your v0.14.0 config sets upstream_source_addresses or performance.upstream_connection_pool_size,
relocate them into the new upstream block as described above.
The new upstream.connection_timeout_seconds and upstream.read_timeout_seconds fields are optional.
Omit them to preserve the previous behavior of no upstream timeouts.
Internals / Developer
These changes do not affect configuration or runtime behavior. They are noted for contributors and anyone tracking the project internals.
confval matured into a standalone library
Reusable validation and conversion logic moved out of the application crates and into the
confval configuration library.
- A new
keywordpipeline module addsKeywordSetfor validating keyword fields, now used across the device and ingress specifications. - A new
narrowpipeline module centralizes numeric and duration conversions that were previously scattered helper functions. - The derive macro gained support for
#[confval(nested, default)]on non-optional nested fields. The attribute is now rejected on optional fields, enforced by a compile-fail test. - New reuse helpers
parse_cidr_listandrequire_existing_file(the latter with remediation help) replace duplicated validation across CIDR and filesystem checks.
confval and confval-derive also received READMEs, TOML and HCL usage examples, and an
enhanced prelude.
The crates were published as confval 0.3.1 and confval-derive 0.1.1.
A just doc task was added for building API documentation.