Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add incoming and outgoing handlers for HTTP/2 #129

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions wit/http2-handler.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/// This interface defines a handler of incoming HTTP/2 Requests. It should
/// be exported by components which can respond to HTTP/2 Requests.
///
/// Note: This interface specifically enforces use of HTTP/2, and must not be
/// provided in environments that aren't able to provide an HTTP/2 connection
/// or otherwise implement the full semantics of an HTTP/2 connection.
@since(version = 0.2.2)
interface http2-incoming-handler {
@since(version = 0.2.2)
use types.{incoming-request, response-outparam};

/// This function is invoked with an incoming HTTP Request, and a resource
/// `response-outparam` which provides the capability to reply with an HTTP
/// Response. The response is sent by calling the `response-outparam.set`
/// method, which allows execution to continue after the response has been
/// sent. This enables both streaming to the response body, and performing other
/// work.
///
/// The implementor of this function must write a response to the
/// `response-outparam` before returning, or else the caller will respond
/// with an error on its behalf.
@since(version = 0.2.2)
Copy link
Member

@yoshuawuyts yoshuawuyts Sep 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR implements an interface which has not yet gone through a WASI SG vote, and until it has it can't be included as part of a WASI release. Can you please change the @since gates to @unstable gates instead?:

Suggested change
@since(version = 0.2.2)
@unstable(feature = "http-http2")

Once this PR lands, please also file a PR on the WASI proposal tracker so we can track this extension as part of the WASI phase process. Full details on the process for adding interfaces to existing WASI proposals can be found here. Thanks!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh of course yes: I'll make sure to change this before this lands—if it ever does. Thank you!

handle: func(
request: incoming-request,
response-out: response-outparam
);
}

/// This interface defines a handler of outgoing HTTP/2 Requests. It should be
/// imported by components which wish to make HTTP/2 Requests.
///
/// Note: This interface specifically enforces use of HTTP/2, and must not be
/// provided in environments that aren't able to provide an HTTP/2 connection
/// or otherwise implement the full semantics of an HTTP/2 connection.
@since(version = 0.2.2)
interface http2-outgoing-handler {
@since(version = 0.2.2)
use types.{
outgoing-request, request-options, future-incoming-response, error-code
};

/// This function is invoked with an outgoing HTTP Request, and it returns
/// a resource `future-incoming-response` which represents an HTTP Response
/// which may arrive in the future.
///
/// The `options` argument accepts optional parameters for the HTTP
/// protocol's transport layer.
///
/// This function may return an error if the `outgoing-request` is invalid
/// or not allowed to be made. Otherwise, protocol errors are reported
/// through the `future-incoming-response`.
@since(version = 0.2.2)
handle: func(
request: outgoing-request,
options: option<request-options>
) -> result<future-incoming-response, error-code>;
}
45 changes: 41 additions & 4 deletions wit/proxy.wit
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package wasi:http@0.2.1;
package wasi:http@0.2.2;

/// The `wasi:http/imports` world imports all the APIs for HTTP proxies.
/// The `wasi:http/imports-no-handler` world imports all the APIs for HTTP proxies
/// except for the `outgoing-handler`.
/// It is intended to be `include`d in other worlds.
@since(version = 0.2.0)
world imports {
@since(version = 0.2.2)
world imports-no-handler {
/// HTTP proxies have access to time and randomness.
@since(version = 0.2.0)
import wasi:clocks/monotonic-clock@0.2.1;
Expand All @@ -25,6 +26,14 @@ world imports {
/// when this import is properly removed.
@since(version = 0.2.0)
import wasi:cli/stdin@0.2.1;
}

/// The `wasi:http/imports` world imports all the APIs for HTTP proxies.
/// It is intended to be `include`d in other worlds.
@since(version = 0.2.0)
world imports {
@since(version = 0.2.0)
include imports-no-handler;

/// This is the default handler to use when user code simply wants to make an
/// HTTP request (e.g., via `fetch()`).
Expand All @@ -36,6 +45,8 @@ world imports {
/// 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.
/// `wasi:http/proxy` doesn't specify the HTTP version to be used, leaving that
/// decision to the host.
@since(version = 0.2.0)
world proxy {
@since(version = 0.2.0)
Expand All @@ -48,3 +59,29 @@ world proxy {
@since(version = 0.2.0)
export incoming-handler;
}

/// The `wasi:http/http2-proxy` world captures a widely-implementable intersection of
/// hosts that includes HTTP/2 forward and reverse proxies. Components targeting
/// this world may concurrently stream in and out any number of incoming and
/// outgoing HTTP requests.
/// In difference to `wasi:http/proxy`, `wasi:http/http2-proxy` specifies that exactly
/// HTTP/2 must be used, making it usable for scenarios that require HTTP/2.
/// In particular, gRPC must use HTTP/2 as the transport, so gRPC clients and servers
/// should target this world.
@since(version = 0.2.2)
world http2-proxy {
@since(version = 0.2.2)
include imports-no-handler;

/// This is the default handler to use when user code simply wants to make an
/// HTTP request (e.g., via `fetch()`).
@since(version = 0.2.2)
import http2-outgoing-handler;

/// 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`.
@since(version = 0.2.2)
export http2-incoming-handler;
}
22 changes: 20 additions & 2 deletions wit/types.wit
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ interface types {
HTTPS,
other(string)
}
}

/// This type corresponds to HTTP protocol versions.
@since(version = 0.2.2)
variant http-version {
HTTP11,
HTTP2,
HTTP3
other(string)
Copy link

@pavelsavara pavelsavara Sep 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding HTTP4 to the enum would be API breaking change.

There is similar discussion about TSL version, with regards to future compatibility.
WebAssembly/wasi-sockets#104 (comment)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I saw that. My intuition is that HTTP versions are introduced rarely enough that we'll have solved this by the time HTTP/4 comes around, but I'm happy to change it if people feel that that's not right.

}

/// These cases are inspired by the IANA HTTP Proxy Error Types:
/// https://www.iana.org/assignments/http-proxy-status/http-proxy-status.xhtml#table-http-proxy-error-types
Expand Down Expand Up @@ -149,9 +159,9 @@ interface types {
///
/// Field keys should always be treated as case insensitive by the `fields`
/// resource for the purposes of equality checking.
///
///
/// # Deprecation
///
///
/// This type has been deprecated in favor of the `field-name` type.
@since(version = 0.2.0)
@deprecated(version = 0.2.2)
Expand Down Expand Up @@ -273,6 +283,10 @@ interface types {
@since(version = 0.2.0)
resource incoming-request {

/// Returns the HTTP version of the incoming request.
@since(version = 0.2.2)
http-version: func() -> http-version;

/// Returns the method of the incoming request.
@since(version = 0.2.0)
method: func() -> method;
Expand Down Expand Up @@ -460,6 +474,10 @@ interface types {
@since(version = 0.2.0)
resource incoming-response {

/// Returns the HTTP version of the incoming request.
@since(version = 0.2.2)
http-version: func() -> http-version;

/// Returns the status code from the incoming response.
@since(version = 0.2.0)
status: func() -> status-code;
Expand Down
Loading