Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: http-wasm/http-wasm-host-go
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: main
Choose a base ref
...
head repository: http-wasm/http-wasm-host-go
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: await-response
Choose a head ref
Can’t automatically merge. Don’t worry, you can still create the pull request.
  • 4 commits
  • 57 files changed
  • 1 contributor

Commits on Aug 8, 2023

  1. Adds once mechanism for Go 1.21 GOOS=js

    This adds an alternative to pooling called once. Specifically, this uses
    a module once per request, and in doing so supports guests who cannot
    export functions. The implementation adds `await_response` with adapter
    glue which the host side implements with Go channels.
    
    As you can see below, this is far less performant than using the pool
    model. However, this allows use of Go 1.21 GOOS=wasip1, which does not
    support pooling because it cannot export host functions.
    ```
    Benchmark/example_log_once
    Benchmark/example_log_once/example_log_once
    Benchmark/example_log_once/example_log_once-12                                 	   52648	     23117 ns/op
    Benchmark/example_log
    Benchmark/example_log/example_log
    Benchmark/example_log/example_log-12                                           	 2100068	       550.4 ns/op
    ```
    
    See golang/go#42372
    
    Signed-off-by: Adrian Cole <adrian@tetrate.io>
    Adrian Cole committed Aug 8, 2023
    Copy the full SHA
    d13ec52 View commit details
  2. polish

    Signed-off-by: Adrian Cole <adrian@tetrate.io>
    Adrian Cole committed Aug 8, 2023
    Copy the full SHA
    68d438a View commit details
  3. polish

    Signed-off-by: Adrian Cole <adrian@tetrate.io>
    Adrian Cole committed Aug 8, 2023
    Copy the full SHA
    6a82e7d View commit details
  4. wasm

    Signed-off-by: Adrian Cole <adrian@tetrate.io>
    Adrian Cole committed Aug 8, 2023
    Copy the full SHA
    c430399 View commit details
Showing with 567 additions and 201 deletions.
  1. +3 −0 api/handler/wasm.go
  2. BIN examples/log_once.wasm
  3. +73 −0 examples/log_once.wat
  4. +100 −138 handler/middleware.go
  5. +2 −2 handler/middleware_test.go
  6. +9 −6 handler/nethttp/benchmark_test.go
  7. +33 −13 handler/nethttp/middleware_test.go
  8. +108 −0 handler/once.go
  9. +135 −0 handler/pool.go
  10. +0 −13 handler/state.go
  11. +7 −0 internal/test/testdata.go
  12. BIN internal/test/testdata/bench/add_header_value.wasm
  13. +1 −1 internal/test/testdata/bench/add_header_value.wat
  14. BIN internal/test/testdata/bench/get_header_names.wasm
  15. +1 −1 internal/test/testdata/bench/get_header_names.wat
  16. BIN internal/test/testdata/bench/get_header_values.wasm
  17. +1 −1 internal/test/testdata/bench/get_header_values.wat
  18. BIN internal/test/testdata/bench/get_uri.wasm
  19. +1 −1 internal/test/testdata/bench/get_uri.wat
  20. BIN internal/test/testdata/bench/log.wasm
  21. +1 −1 internal/test/testdata/bench/log.wat
  22. BIN internal/test/testdata/bench/read_body.wasm
  23. +1 −1 internal/test/testdata/bench/read_body.wat
  24. BIN internal/test/testdata/bench/read_body_stream.wasm
  25. +1 −1 internal/test/testdata/bench/read_body_stream.wat
  26. BIN internal/test/testdata/bench/remove_header.wasm
  27. +1 −1 internal/test/testdata/bench/remove_header.wat
  28. BIN internal/test/testdata/bench/set_header_value.wasm
  29. +1 −1 internal/test/testdata/bench/set_header_value.wat
  30. BIN internal/test/testdata/bench/set_status_code.wasm
  31. +1 −1 internal/test/testdata/bench/set_status_code.wat
  32. BIN internal/test/testdata/bench/set_uri.wasm
  33. +1 −1 internal/test/testdata/bench/set_uri.wat
  34. BIN internal/test/testdata/bench/write_body.wasm
  35. +1 −1 internal/test/testdata/bench/write_body.wat
  36. BIN internal/test/testdata/e2e/await_response.wasm
  37. +68 −0 internal/test/testdata/e2e/await_response.wat
  38. BIN internal/test/testdata/e2e/handle_response.wasm
  39. +8 −8 internal/test/testdata/e2e/handle_response.wat
  40. BIN internal/test/testdata/e2e/header_names.wasm
  41. +1 −1 internal/test/testdata/e2e/header_names.wat
  42. BIN internal/test/testdata/e2e/header_value.wasm
  43. +1 −1 internal/test/testdata/e2e/header_value.wat
  44. BIN internal/test/testdata/e2e/method.wasm
  45. +1 −1 internal/test/testdata/e2e/method.wat
  46. BIN internal/test/testdata/e2e/protocol_version.wasm
  47. +1 −1 internal/test/testdata/e2e/protocol_version.wat
  48. BIN internal/test/testdata/e2e/uri.wasm
  49. +1 −1 internal/test/testdata/e2e/uri.wat
  50. BIN internal/test/testdata/error/panic_on_handle_request.wasm
  51. +1 −1 internal/test/testdata/error/panic_on_handle_request.wat
  52. BIN internal/test/testdata/error/panic_on_handle_response.wasm
  53. +1 −1 internal/test/testdata/error/panic_on_handle_response.wat
  54. BIN internal/test/testdata/error/panic_on_start.wasm
  55. +1 −1 internal/test/testdata/error/panic_on_start.wat
  56. BIN internal/test/testdata/error/set_request_header_after_next.wasm
  57. +1 −1 internal/test/testdata/error/set_request_header_after_next.wat
3 changes: 3 additions & 0 deletions api/handler/wasm.go
Original file line number Diff line number Diff line change
@@ -300,6 +300,9 @@ const (
// TODO: document on http-wasm-abi
FuncWriteBody = "write_body"

// FuncAwaitResponse TODO
FuncAwaitResponse = "await_response"

// FuncGetStatusCode returns the status code produced by FuncNext. This
// requires FeatureBufferResponse.
//
Binary file added examples/log_once.wasm
Binary file not shown.
73 changes: 73 additions & 0 deletions examples/log_once.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
;; This example module is written in WebAssembly Text Format to show the
;; how a handler works when the guest compiler doesn't support function
;; exports, such as GOOS=wasip1 in Go 1.21.
(module $log_once

;; log_enabled returns 1 if the $level is enabled. This value may be cached
;; at request granularity.
(import "http_handler" "log_enabled" (func $log_enabled
(param $level i32)
(result (; 0 or enabled(1) ;) i32)))

;; logs a message to the host's logs at the given $level.
(import "http_handler" "log" (func $log
(param $level i32)
(param $buf i32) (param $buf_limit i32)))

(; begin adapter logic
Below is generic and can convert any normal handler to a single synchronous
call, provided $handle_request and $handle_response are not exported. ;)

;; import $await_response, which blocks until the response is ready.
(import "http_handler" "await_response" (func $await_response
(param $ctx_next i64)
(result (; is_error ;) i32)))

;; define a start function that performs a request-response without exports.
;; note: this logic is generic and can convert any exported $handle_request/
;; $handle_response pair to a synchronous call without exports.
(func $start
(local $ctx_next i64)
(local $is_error i32)
(local $ctx i32)

;; ctxNext := handleRequest()
(local.set $ctx_next (call $handle_request))

;; isError := awaitResponse(ctxNext)
(local.set $is_error (call $await_response (local.get $ctx_next)))

;; ctx := uint32(ctxNext >> 32)
(local.set $ctx
(i32.wrap_i64 (i64.shr_u (local.get $ctx_next) (i64.const 32))))

;; handleResponse(ctx, isError)
(call $handle_response (local.get $ctx) (local.get $is_error))
)

(; end adapter logic ;)

(memory (export "memory") 1 1 (; 1 page==64KB ;))
(global $message i32 (i32.const 0))
(data (i32.const 0) "hello world")
(global $message_len i32 (i32.const 11))

(func $handle_request (result (; ctx_next ;) i64)
;; We expect debug logging to be disabled. Panic otherwise!
(if (i32.eq
(call $log_enabled (i32.const -1)) ;; log_level_debug
(i32.const 1)) ;; true
(then unreachable))

(call $log
(i32.const 0) ;; log_level_info
(global.get $message)
(global.get $message_len))

;; uint32(ctx_next) == 1 means proceed to the next handler on the host.
(return (i64.const 1)))

;; handle_response is no-op as this is a request-only handler.
(func $handle_response (param $reqCtx i32) (param $is_error i32))
)
Loading