Commit 3c7092c
authored
feat: side-channel body passing via host functions (#49)
* fix: use binary bodies (Vec<u8>) in plugin SDK instead of String
Change Request/Response body from Option<String> to Option<Vec<u8>>
with base64 JSON encoding, fixing data loss for binary payloads like
multipart/form-data file uploads. Updates all plugins and the WASM
runtime to use the new binary-safe body type.
* fix: update remaining plugins and macro to use binary body type
Fix #[barbacane_dispatcher] macro error responses and update http-log,
oidc-auth, oauth2-auth, opa-authz HttpRequest structs to use
Option<Vec<u8>> with base64 encoding, matching the host-side expectation.
Also fix http-upstream test assertions to use from_slice.
* test: add comprehensive binary body coverage across SDK, WASM, and integration
SDK unit tests (20 new):
- Response base64 roundtrip (text, binary, none)
- Empty body vs None distinction
- Helper methods: body_string, set_body_text, Response::text
- Null bytes and all-256-byte-values roundtrip
- Middleware short-circuit with binary body
- Request body → Response body dispatcher roundtrip
WASM chain tests (2 new):
- parse_middleware_output with base64-encoded binary body (Continue)
- parse_middleware_output with binary body (ShortCircuit)
WASM cache tests (3 new):
- Binary body cache storage/retrieval
- CacheEntry JSON roundtrip with binary body
- CacheEntry JSON roundtrip with None body
Integration tests (3 new):
- Binary body through auth middleware to upstream (wiremock)
- Binary body direct dispatch without middleware (wiremock)
- Binary response body from upstream to client (wiremock)
* docs: update body type references from Option<String> to Option<Vec<u8>>
- docs/contributing/plugins.md: update SDK type signatures and add
helper method docs, base64 encoding note
- adr/0023-wasm-plugin-streaming.md: fix Response type reference
- tests/fixture-plugins/streaming-echo: update HttpRequest body field
to use base64_body serde encoding
* Fix write_to_memory OOM: write at __data_end instead of top of memory
The old approach wrote host data at mem_size - data.len() (top of linear
memory), which is exactly where dlmalloc's heap lives. This caused OOM
crashes in plugins that use host_http_call (e.g. oidc-auth) because the
heap allocation would overwrite the input data.
Now reads the __data_end WASM global at instantiation and writes host
data there — between static data and the stack. This is safe because
write_to_memory is only called before the WASM function executes (stack
is empty at that point).
* Add __heap_base bounds check to write_to_memory
Read both __data_end and __heap_base WASM globals at instantiation.
Input data is now bounded to the [__data_end..__heap_base] region,
preventing oversized payloads from silently corrupting the heap.
* fix: resolve WASM OOM by allocating input buffers via plugin's dlmalloc
The previous write_to_memory approaches (writing at top of memory, then
at __data_end, then via Memory::grow) all placed data in regions that
dlmalloc considered its heap, causing corruption during deserialization.
The fix exports alloc/dealloc from each WASM plugin (via the proc
macros) so the host allocates input buffers through the plugin's own
allocator. This ensures dlmalloc tracks the region and won't reuse it.
Additional optimizations to reduce peak memory:
- Free input buffer after deserialization (dealloc in on_request/
on_response/dispatch before output serialization)
- Replace serde_json::json!() intermediate Value tree with direct
ActionOutput struct serialization
- Scale WASM fuel with payload size for large body processing
Also adds 3 integration tests covering 500KB and 2MB body payloads
through middleware + dispatcher chains, and fixes a pre-existing
apikey-auth config format bug in the streaming test.
* feat: add body_access capability to strip request body from middleware that doesn't need it
Middleware plugins that only inspect headers (auth, rate-limit, etc.) no longer
receive the base64-encoded request body, avoiding unnecessary copies of large
payloads into each WASM instance.
- Add `body_access` bool to plugin manifest capabilities
- Compiler reads `body_access` from plugin.toml, carries it through artifact format
- Engine/pool propagate the flag per compiled module
- Data plane strips body (sets to null) before calling middleware without body_access,
re-attaches it after; middleware with body_access can read and modify the body
- Mark request-transformer, cel, request-size-limit as body_access = true
- Add SPEC-008 design document
* docs: update changelog for binary body support and body_access capability
* perf(http-upstream): reduce peak WASM memory via move-not-clone and manual serialization
Destructure Request to avoid cloning the body, pre-encode to base64
before building JSON output, and use manual SerializeMap to control
allocation. Peak memory drops from ~body×3.7 to ~body×2.7, allowing
3MB uploads to fit within the 16MB WASM instance budget.
Add integration test for 3MB body through middleware + dispatch.
* refactor: extract BodyAccessControl with split-once pattern and 19 unit tests
Replace per-middleware JSON parse/strip/reattach cycles with a single
upfront body extraction. Non-body middlewares get the pre-built body-less
JSON directly; body-access middlewares get one inject/extract cycle.
- New `BodyAccessControl` struct in barbacane-wasm with split/request_for/
update_after_middleware/finalize API
- 19 unit tests covering split, inject, update, finalize, full chain
scenarios (mixed, all-no-access, all-access), and edge cases
- Simplify execute_middleware_on_request to 3 lines per middleware
- Document body_access capability in CLAUDE.md
* fix: add base64_body serde to host HttpRequest/HttpResponse and all plugin HttpResponse structs
The host-side HttpRequest/HttpResponse in http_client.rs was missing
#[serde(with = "base64_body")], causing body encoding mismatch with
WASM plugins after the Vec<u8> body migration. Plugins would receive
a base64 string but try to deserialize it as a byte array (or vice
versa), causing silent corruption or deserialization failures.
Also scale WASM memory to max(16MB, max_body_size * 4) so dispatchers
have headroom for large file uploads.
Affected plugins: http-upstream, lambda, ai-proxy, s3, opa-authz,
oauth2-auth, oidc-auth.
Add 5 unit tests for host↔plugin base64 body serde compatibility.
* fix: strip response body for non-body-access middleware (prevents WASM OOM)
Mirror SPEC-008 body_access stripping for the on_response path. Middleware
without body_access = true now receives responses with body: null, preventing
large upstream responses (e.g. file downloads) from being base64-encoded
into every middleware's WASM linear memory.
Also strips response body in the streaming on_response path (observability-only,
modifications are discarded anyway).
Adds body_access = true to response-transformer plugin manifest since it
modifies response bodies and needs access to them.
* test: add workload integration tests and serde contract tests
Add body-echo fixture plugin (dispatcher that echoes request body/metadata),
14 workload integration tests covering body integrity through middleware
chains, large payloads, and response body passthrough, plus 10 serde
compatibility tests verifying wire format between host and plugin types.
These tests would have caught the base64_body serde mismatch, body
corruption through middleware chains, and response body OOM issues
proactively.
* docs: update test count to 1421
* feat: side-channel body passing via host functions (eliminates WASM OOM)
Bodies now travel as raw bytes via dedicated host functions instead of
base64-encoded inside JSON. This eliminates the ~3.65x memory overhead
per boundary crossing, allowing 10MB+ bodies within the 16MB default
WASM memory limit.
New host functions: host_body_len, host_body_read, host_body_set,
host_body_clear, host_http_response_body_len, host_http_response_body_read,
host_http_request_body_set.
Request/Response.body is now #[serde(skip)] — proc macros handle the
side-channel protocol transparently. base64_body module retained for
host-side HTTP types and cache entries.
All 27 plugins migrated. WASM memory formula: max(16MB, body + 4MB).
* docs: update changelog and plugin guide for side-channel body passing
- Changelog: document side-channel host functions, body_access fix, WASM
memory formula change, and plugin migration
- Plugin guide: update body docs from base64 to side-channel, update
HTTP call example, update WASM memory limit table
* docs: update test count to 1388
* docs: update ADR-0023 and SPEC-008 for side-channel body passing
- ADR-0023: remove outdated "base64-encoded in JSON" reference
- SPEC-008: mark as Implemented, update problem statement, pseudocode,
examples, and performance table to reflect side-channel protocol1 parent 287a6df commit 3c7092c
99 files changed
Lines changed: 5090 additions & 957 deletions
File tree
- adr
- crates
- barbacane-compiler/src
- barbacane-control/src/compiler
- barbacane-plugin-macros/src
- barbacane-plugin-sdk
- src
- barbacane-test
- src
- tests
- barbacane-wasm
- benches
- src
- barbacane/src
- docs/contributing
- plugins
- acl
- src
- ai-proxy
- src
- apikey-auth
- src
- basic-auth
- src
- bot-detection
- src
- cache
- src
- cel
- src
- correlation-id
- cors
- src
- http-log
- src
- http-upstream
- src
- ip-restriction
- src
- jwt-auth
- src
- kafka
- src
- lambda
- src
- mock
- src
- nats
- src
- oauth2-auth
- src
- observability
- src
- oidc-auth
- src
- opa-authz
- src
- rate-limit
- src
- request-size-limit
- src
- request-transformer
- src
- response-transformer
- src
- s3
- src
- ws-upstream
- src
- specs
- tests/fixture-plugins
- body-echo
- src
- streaming-echo
- src
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
10 | 29 | | |
11 | 30 | | |
12 | 31 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
105 | 105 | | |
106 | 106 | | |
107 | 107 | | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
108 | 111 | | |
109 | 112 | | |
110 | 113 | | |
| |||
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
13 | | - | |
14 | | - | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
8 | | - | |
| 8 | + | |
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
113 | 113 | | |
114 | 114 | | |
115 | 115 | | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
116 | 137 | | |
117 | 138 | | |
118 | 139 | | |
| |||
222 | 243 | | |
223 | 244 | | |
224 | 245 | | |
| 246 | + | |
225 | 247 | | |
226 | 248 | | |
227 | 249 | | |
| |||
302 | 324 | | |
303 | 325 | | |
304 | 326 | | |
305 | | - | |
306 | | - | |
307 | | - | |
308 | | - | |
| 327 | + | |
| 328 | + | |
309 | 329 | | |
310 | 330 | | |
311 | 331 | | |
| |||
315 | 335 | | |
316 | 336 | | |
317 | 337 | | |
318 | | - | |
319 | | - | |
| 338 | + | |
| 339 | + | |
320 | 340 | | |
321 | 341 | | |
322 | | - | |
| 342 | + | |
323 | 343 | | |
324 | 344 | | |
325 | 345 | | |
326 | 346 | | |
327 | 347 | | |
328 | 348 | | |
329 | | - | |
| 349 | + | |
330 | 350 | | |
331 | 351 | | |
332 | | - | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
333 | 360 | | |
334 | 361 | | |
335 | 362 | | |
| |||
346 | 373 | | |
347 | 374 | | |
348 | 375 | | |
| 376 | + | |
| 377 | + | |
349 | 378 | | |
350 | 379 | | |
351 | 380 | | |
| |||
583 | 612 | | |
584 | 613 | | |
585 | 614 | | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
586 | 618 | | |
587 | 619 | | |
588 | 620 | | |
| |||
1280 | 1312 | | |
1281 | 1313 | | |
1282 | 1314 | | |
| 1315 | + | |
1283 | 1316 | | |
1284 | 1317 | | |
1285 | 1318 | | |
| |||
1302 | 1335 | | |
1303 | 1336 | | |
1304 | 1337 | | |
1305 | | - | |
1306 | | - | |
1307 | | - | |
| 1338 | + | |
| 1339 | + | |
| 1340 | + | |
1308 | 1341 | | |
1309 | 1342 | | |
1310 | 1343 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
13 | | - | |
14 | | - | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
15 | 16 | | |
16 | 17 | | |
17 | 18 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| 18 | + | |
| 19 | + | |
18 | 20 | | |
19 | 21 | | |
20 | 22 | | |
| |||
24 | 26 | | |
25 | 27 | | |
26 | 28 | | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
27 | 42 | | |
28 | | - | |
| 43 | + | |
29 | 44 | | |
30 | 45 | | |
31 | 46 | | |
32 | | - | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
33 | 52 | | |
34 | 53 | | |
35 | 54 | | |
| |||
79 | 98 | | |
80 | 99 | | |
81 | 100 | | |
82 | | - | |
| 101 | + | |
83 | 102 | | |
84 | 103 | | |
85 | 104 | | |
86 | | - | |
87 | | - | |
88 | 105 | | |
89 | | - | |
| 106 | + | |
90 | 107 | | |
91 | 108 | | |
92 | 109 | | |
93 | 110 | | |
94 | 111 | | |
95 | 112 | | |
96 | | - | |
97 | | - | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
98 | 116 | | |
99 | 117 | | |
100 | 118 | | |
| |||
155 | 173 | | |
156 | 174 | | |
157 | 175 | | |
| 176 | + | |
| 177 | + | |
158 | 178 | | |
159 | 179 | | |
160 | 180 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
262 | 262 | | |
263 | 263 | | |
264 | 264 | | |
| 265 | + | |
| 266 | + | |
265 | 267 | | |
266 | 268 | | |
267 | 269 | | |
| |||
0 commit comments