From a4dc0ac277072e4fe546adf92e084f4976811eb4 Mon Sep 17 00:00:00 2001 From: Lann Martin Date: Mon, 6 Oct 2025 14:57:44 -0400 Subject: [PATCH 1/4] Rework 0.3 handlers and worlds - Add a `client` interface with a `send` function matching `handle` - Replace the `imports` world's `handler` import with `client` - Replace the `proxy` world with `service` - Add a `middleware` world --- wit-0.3.0-draft/client.wit | 13 +++++++++ wit-0.3.0-draft/handler.wit | 17 ++++-------- wit-0.3.0-draft/{proxy.wit => service.wit} | 32 +++++++++++++--------- 3 files changed, 38 insertions(+), 24 deletions(-) create mode 100644 wit-0.3.0-draft/client.wit rename wit-0.3.0-draft/{proxy.wit => service.wit} (60%) diff --git a/wit-0.3.0-draft/client.wit b/wit-0.3.0-draft/client.wit new file mode 100644 index 0000000..651d58c --- /dev/null +++ b/wit-0.3.0-draft/client.wit @@ -0,0 +1,13 @@ +/// This interface defines an HTTP client. It may be imported by components that +/// wish to send HTTP Requests or it may be composed with a `handler` to process +/// requests without any use of a network. In addition, it may be exported by +/// components to wrap another `client` as with "client interceptors". +interface client { + use types.{request, response, error-code}; + + /// This function may be used to either send an outgoing request over the + /// network or to forward it to another component. + send: async func( + request: request, + ) -> result; +} diff --git a/wit-0.3.0-draft/handler.wit b/wit-0.3.0-draft/handler.wit index e4446cb..e62981d 100644 --- a/wit-0.3.0-draft/handler.wit +++ b/wit-0.3.0-draft/handler.wit @@ -1,17 +1,12 @@ -/// This interface defines a handler of HTTP Requests. It may be imported by -/// components which wish to send HTTP Requests and also exported by components -/// which can respond to HTTP Requests. In addition, it may be used to pass -/// a request from one component to another without any use of a network. +/// This interface defines a handler of HTTP Requests. It may be exported by +/// components which can respond to HTTP Requests. In addition, it may be +/// imported by components to wrap another `handler` as with "middleware". interface handler { use types.{request, response, error-code}; - /// When exported, this function may be called with either an incoming - /// request read from the network or a request synthesized or forwarded by - /// another component. - /// - /// When imported, this function may be used to either send an outgoing - /// request over the network or pass it to another component. + /// This function may be called with either an incoming request read from the + /// network or a request synthesized or forwarded by another component. handle: async func( request: request, ) -> result; -} +} \ No newline at end of file diff --git a/wit-0.3.0-draft/proxy.wit b/wit-0.3.0-draft/service.wit similarity index 60% rename from wit-0.3.0-draft/proxy.wit rename to wit-0.3.0-draft/service.wit index 223083e..caf2730 100644 --- a/wit-0.3.0-draft/proxy.wit +++ b/wit-0.3.0-draft/service.wit @@ -1,13 +1,13 @@ package wasi:http@0.3.0-rc-2025-09-16; -/// The `wasi:http/imports` world imports all the APIs for HTTP proxies. +/// The `wasi:http/imports` world imports all the APIs for HTTP services. /// It is intended to be `include`d in other worlds. world imports { - /// HTTP proxies have access to time and randomness. + /// HTTP services have access to time and randomness. include wasi:clocks/imports@0.3.0-rc-2025-09-16; import wasi:random/random@0.3.0-rc-2025-09-16; - /// Proxies have standard output and error streams which are expected to + /// Services have standard output and error streams which are expected to /// terminate in a developer-facing console provided by the host. import wasi:cli/stdout@0.3.0-rc-2025-09-16; import wasi:cli/stderr@0.3.0-rc-2025-09-16; @@ -18,19 +18,15 @@ world imports { /// when this import is properly removed. import wasi:cli/stdin@0.3.0-rc-2025-09-16; - /// This is the default handler to use when user code simply wants to make an + /// This is the default `client` to use when user code simply wants to make an /// HTTP request (e.g., via `fetch()`). - /// - /// This may also be used to pass synthesized or forwarded requests to another - /// component. - import handler; + import client; } -/// The `wasi:http/proxy` world captures a widely-implementable intersection of -/// hosts that includes HTTP forward and reverse proxies. Components targeting -/// this world may concurrently stream in and out any number of incoming and -/// outgoing HTTP requests. -world proxy { +/// The `wasi:http/service` world captures a broad category of HTTP services +/// including web applications, API servers, and proxies. It may be `include`d +/// in more specific worlds such as `wasi:http/gateway`. +world service { include imports; /// The host delivers incoming HTTP requests to a component by calling the @@ -42,3 +38,13 @@ world proxy { /// another component. export handler; } + +/// The `wasi:http/middleware` world captures HTTP services that forward HTTP +/// Requests to another handler. Components may implement this world to allow +/// them to participate in handler "chains" where a Request flows through +/// handlers on its way to some "terminal" service and corresponding Responses +/// flow in the opposite direction. +world middleware { + include service; + import handler; +} \ No newline at end of file From 6ee48a561b85596543b5d643040dcf70e1dfd2de Mon Sep 17 00:00:00 2001 From: Lann Martin Date: Wed, 15 Oct 2025 10:28:41 -0400 Subject: [PATCH 2/4] Address PR feedback --- wit-0.3.0-draft/client.wit | 13 ------ wit-0.3.0-draft/handler.wit | 12 ------ wit-0.3.0-draft/service.wit | 50 ----------------------- wit-0.3.0-draft/worlds.wit | 81 +++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 75 deletions(-) delete mode 100644 wit-0.3.0-draft/client.wit delete mode 100644 wit-0.3.0-draft/handler.wit delete mode 100644 wit-0.3.0-draft/service.wit create mode 100644 wit-0.3.0-draft/worlds.wit diff --git a/wit-0.3.0-draft/client.wit b/wit-0.3.0-draft/client.wit deleted file mode 100644 index 651d58c..0000000 --- a/wit-0.3.0-draft/client.wit +++ /dev/null @@ -1,13 +0,0 @@ -/// This interface defines an HTTP client. It may be imported by components that -/// wish to send HTTP Requests or it may be composed with a `handler` to process -/// requests without any use of a network. In addition, it may be exported by -/// components to wrap another `client` as with "client interceptors". -interface client { - use types.{request, response, error-code}; - - /// This function may be used to either send an outgoing request over the - /// network or to forward it to another component. - send: async func( - request: request, - ) -> result; -} diff --git a/wit-0.3.0-draft/handler.wit b/wit-0.3.0-draft/handler.wit deleted file mode 100644 index e62981d..0000000 --- a/wit-0.3.0-draft/handler.wit +++ /dev/null @@ -1,12 +0,0 @@ -/// This interface defines a handler of HTTP Requests. It may be exported by -/// components which can respond to HTTP Requests. In addition, it may be -/// imported by components to wrap another `handler` as with "middleware". -interface handler { - use types.{request, response, error-code}; - - /// This function may be called with either an incoming request read from the - /// network or a request synthesized or forwarded by another component. - handle: async func( - request: request, - ) -> result; -} \ No newline at end of file diff --git a/wit-0.3.0-draft/service.wit b/wit-0.3.0-draft/service.wit deleted file mode 100644 index caf2730..0000000 --- a/wit-0.3.0-draft/service.wit +++ /dev/null @@ -1,50 +0,0 @@ -package wasi:http@0.3.0-rc-2025-09-16; - -/// The `wasi:http/imports` world imports all the APIs for HTTP services. -/// It is intended to be `include`d in other worlds. -world imports { - /// HTTP services have access to time and randomness. - include wasi:clocks/imports@0.3.0-rc-2025-09-16; - import wasi:random/random@0.3.0-rc-2025-09-16; - - /// Services have standard output and error streams which are expected to - /// terminate in a developer-facing console provided by the host. - import wasi:cli/stdout@0.3.0-rc-2025-09-16; - import wasi:cli/stderr@0.3.0-rc-2025-09-16; - - /// TODO: this is a temporary workaround until component tooling is able to - /// gracefully handle the absence of stdin. Hosts must return an eof stream - /// for this import, which is what wasi-libc + tooling will do automatically - /// when this import is properly removed. - import wasi:cli/stdin@0.3.0-rc-2025-09-16; - - /// This is the default `client` to use when user code simply wants to make an - /// HTTP request (e.g., via `fetch()`). - import client; -} - -/// The `wasi:http/service` world captures a broad category of HTTP services -/// including web applications, API servers, and proxies. It may be `include`d -/// in more specific worlds such as `wasi:http/gateway`. -world service { - include imports; - - /// The host delivers incoming HTTP requests to a component by calling the - /// `handle` function of this exported interface. A host may arbitrarily reuse - /// or not reuse component instance when delivering incoming HTTP requests and - /// thus a component must be able to handle 0..N calls to `handle`. - /// - /// This may also be used to receive synthesized or forwarded requests from - /// another component. - export handler; -} - -/// The `wasi:http/middleware` world captures HTTP services that forward HTTP -/// Requests to another handler. Components may implement this world to allow -/// them to participate in handler "chains" where a Request flows through -/// handlers on its way to some "terminal" service and corresponding Responses -/// flow in the opposite direction. -world middleware { - include service; - import handler; -} \ No newline at end of file diff --git a/wit-0.3.0-draft/worlds.wit b/wit-0.3.0-draft/worlds.wit new file mode 100644 index 0000000..777fcc6 --- /dev/null +++ b/wit-0.3.0-draft/worlds.wit @@ -0,0 +1,81 @@ +package wasi:http@0.3.0-rc-2025-09-16; + +/// The `wasi:http/service` world captures a broad category of HTTP services +/// including web applications, API servers, and proxies. It may be `include`d +/// in more specific worlds such as `wasi:http/middleware`. +world service { + /// HTTP services have access to time and randomness. + include wasi:clocks/imports@0.3.0-rc-2025-09-16; + import wasi:random/random@0.3.0-rc-2025-09-16; + + /// Services have standard output and error streams which are expected to + /// terminate in a developer-facing console provided by the host. + import wasi:cli/stdout@0.3.0-rc-2025-09-16; + import wasi:cli/stderr@0.3.0-rc-2025-09-16; + + /// TODO: this is a temporary workaround until component tooling is able to + /// gracefully handle the absence of stdin. Hosts must return an eof stream + /// for this import, which is what wasi-libc + tooling will do automatically + /// when this import is properly removed. + import wasi:cli/stdin@0.3.0-rc-2025-09-16; + + /// This is the default `client` to use when user code simply wants to make an + /// HTTP request (e.g., via `fetch()`). + import client; + + /// The host delivers incoming HTTP requests to a component by calling the + /// `handle` function of this exported interface. A host may arbitrarily reuse + /// or not reuse component instance when delivering incoming HTTP requests and + /// thus a component must be able to handle 0..N calls to `handle`. + /// + /// This may also be used to receive synthesized or forwarded requests from + /// another component. + export handler; +} + +/// The `wasi:http/middleware` world captures HTTP services that forward HTTP +/// Requests to another handler. +/// +/// Components may implement this world to allow them to participate in handler +/// "chains" where a Request flows through handlers on its way to some terminal +/// `service` and corresponding Responses flow in the opposite direction. +world middleware { + include service; + import handler; +} + +/// This interface defines a handler of HTTP Requests. +/// +/// In a `wasi:http/service` this interface is exported to respond to an +/// incoming HTTP Request with a Response. +/// +/// In `wasi:http/middleware` this interface is both exported and imported as +/// the "downstream" and "upstream" directions of the middleware chain. +interface handler { + use types.{request, response, error-code}; + + /// This function may be called with either an incoming request read from the + /// network or a request synthesized or forwarded by another component. + handle: async func( + request: request, + ) -> result; +} + +/// This interface defines an HTTP client for sending "outgoing" requests. +/// +/// Most components are expected to import this interface to provide the +/// capability to send HTTP requests to arbitrary destinations on a network. +/// +/// The type signature of `client.send` is the same as `handler.handle`. This +/// duplication is currently necessary because some Component Model tooling +/// (including WIT itself) is unable to represent a component importing two +/// instances of the same interface. +interface client { + use types.{request, response, error-code}; + + // This function may be used to either send an outgoing request over the + // network or to forward it to another component. + send: async func( + request: request, + ) -> result; +} \ No newline at end of file From 10a3d6360a2adc788a5ee8b6165824a8812f3e1f Mon Sep 17 00:00:00 2001 From: Lann Date: Thu, 16 Oct 2025 08:50:36 -0400 Subject: [PATCH 3/4] Adopt PR feedback Co-authored-by: Luke Wagner --- wit-0.3.0-draft/worlds.wit | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/wit-0.3.0-draft/worlds.wit b/wit-0.3.0-draft/worlds.wit index 777fcc6..946eaf4 100644 --- a/wit-0.3.0-draft/worlds.wit +++ b/wit-0.3.0-draft/worlds.wit @@ -35,20 +35,20 @@ world service { /// The `wasi:http/middleware` world captures HTTP services that forward HTTP /// Requests to another handler. -/// +/// /// Components may implement this world to allow them to participate in handler -/// "chains" where a Request flows through handlers on its way to some terminal -/// `service` and corresponding Responses flow in the opposite direction. +/// "chains" where a `request` flows through handlers on its way to some terminal +/// `service` and corresponding `response` flows in the opposite direction. world middleware { include service; import handler; } /// This interface defines a handler of HTTP Requests. -/// +/// /// In a `wasi:http/service` this interface is exported to respond to an /// incoming HTTP Request with a Response. -/// +/// /// In `wasi:http/middleware` this interface is both exported and imported as /// the "downstream" and "upstream" directions of the middleware chain. interface handler { @@ -62,10 +62,10 @@ interface handler { } /// This interface defines an HTTP client for sending "outgoing" requests. -/// +/// /// Most components are expected to import this interface to provide the /// capability to send HTTP requests to arbitrary destinations on a network. -/// +/// /// The type signature of `client.send` is the same as `handler.handle`. This /// duplication is currently necessary because some Component Model tooling /// (including WIT itself) is unable to represent a component importing two From 9df1865ed657e6383887a965ea8fa71bcbe5b726 Mon Sep 17 00:00:00 2001 From: Lann Martin Date: Thu, 16 Oct 2025 14:33:18 -0400 Subject: [PATCH 4/4] Add note about linking client to handler --- wit-0.3.0-draft/worlds.wit | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wit-0.3.0-draft/worlds.wit b/wit-0.3.0-draft/worlds.wit index 946eaf4..942c47e 100644 --- a/wit-0.3.0-draft/worlds.wit +++ b/wit-0.3.0-draft/worlds.wit @@ -69,7 +69,8 @@ interface handler { /// The type signature of `client.send` is the same as `handler.handle`. This /// duplication is currently necessary because some Component Model tooling /// (including WIT itself) is unable to represent a component importing two -/// instances of the same interface. +/// instances of the same interface. A `client.send` import may be linked +/// directly to a `handler.handle` export to bypass the network. interface client { use types.{request, response, error-code};