|
| 1 | +;; This example module is written in WebAssembly Text Format to show the |
| 2 | +;; how a handler works when the guest compiler doesn't support function |
| 3 | +;; exports, such as GOOS=wasip1 in Go 1.21. |
| 4 | +(module $log_once |
| 5 | + |
| 6 | + ;; log_enabled returns 1 if the $level is enabled. This value may be cached |
| 7 | + ;; at request granularity. |
| 8 | + (import "http_handler" "log_enabled" (func $log_enabled |
| 9 | + (param $level i32) |
| 10 | + (result (; 0 or enabled(1) ;) i32))) |
| 11 | + |
| 12 | + ;; logs a message to the host's logs at the given $level. |
| 13 | + (import "http_handler" "log" (func $log |
| 14 | + (param $level i32) |
| 15 | + (param $buf i32) (param $buf_limit i32))) |
| 16 | + |
| 17 | +(; begin adapter logic |
| 18 | +
|
| 19 | + Below is generic and can convert any normal handler to a single synchronous |
| 20 | + call, provided $handle_request and $handle_response are not exported. ;) |
| 21 | + |
| 22 | + ;; import $await_response, which blocks until the response is ready. |
| 23 | + (import "http_handler" "await_response" (func $await_response |
| 24 | + (param $ctx_next i64) |
| 25 | + (result (; is_error ;) i32))) |
| 26 | + |
| 27 | + ;; define a start function that performs a request-response without exports. |
| 28 | + ;; note: this logic is generic and can convert any exported $handle_request/ |
| 29 | + ;; $handle_response pair to a synchronous call without exports. |
| 30 | + (func $start |
| 31 | + (local $ctx_next i64) |
| 32 | + (local $is_error i32) |
| 33 | + (local $ctx i32) |
| 34 | + |
| 35 | + ;; ctxNext := handleRequest() |
| 36 | + (local.set $ctx_next (call $handle_request)) |
| 37 | + |
| 38 | + ;; isError := awaitResponse(ctxNext()) |
| 39 | + (local.set $is_error (call $await_response (local.get $ctx_next))) |
| 40 | + |
| 41 | + ;; expected_count = uint32(result >> 32) |
| 42 | + (local.set $ctx |
| 43 | + (i32.wrap_i64 (i64.shr_u (local.get $ctx_next) (i64.const 32)))) |
| 44 | + |
| 45 | + (call $handle_response (local.get $ctx) (local.get $is_error)) |
| 46 | + ) |
| 47 | + |
| 48 | +(; end adapter logic ;) |
| 49 | + |
| 50 | + (memory (export "memory") 1 1 (; 1 page==64KB ;)) |
| 51 | + (global $message i32 (i32.const 0)) |
| 52 | + (data (i32.const 0) "hello world") |
| 53 | + (global $message_len i32 (i32.const 11)) |
| 54 | + |
| 55 | + (func $handle_request (result (; ctx_next ;) i64) |
| 56 | + ;; We expect debug logging to be disabled. Panic otherwise! |
| 57 | + (if (i32.eq |
| 58 | + (call $log_enabled (i32.const -1)) ;; log_level_debug |
| 59 | + (i32.const 1)) ;; true |
| 60 | + (then unreachable)) |
| 61 | + |
| 62 | + (call $log |
| 63 | + (i32.const 0) ;; log_level_info |
| 64 | + (global.get $message) |
| 65 | + (global.get $message_len)) |
| 66 | + |
| 67 | + ;; uint32(ctx_next) == 1 means proceed to the next handler on the host. |
| 68 | + (return (i64.const 1))) |
| 69 | + |
| 70 | + ;; handle_response is no-op as this is a request-only handler. |
| 71 | + (func $handle_response (param $reqCtx i32) (param $is_error i32)) |
| 72 | +) |
0 commit comments