From c032c336514dcb251d256431f2ec54ca67ef1ca7 Mon Sep 17 00:00:00 2001 From: Brendan Burns Date: Fri, 17 Feb 2023 19:55:31 +0000 Subject: [PATCH] Initial documentation. --- README.md | 102 ++++++++++++++++++++++++++++++++++++++++++++++- wasi-http.wit | 58 +++++++++++++++++++++++++++ wasi-http.wit.md | 90 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 248 insertions(+), 2 deletions(-) create mode 100644 wasi-http.wit create mode 100644 wasi-http.wit.md diff --git a/README.md b/README.md index 2d9e040..2c1e23c 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,101 @@ -# WASI HTTP +# `wasi-http` -(This is a placeholder so there can be a PR to fill in the contents.) +A proposed [WebAssembly System Interface](https://github.com/WebAssembly/WASI) +API to add native http client support. + +### Current Phase + +Phase 1 + +### Champions + +- [Brendan Burns](https://github.com/brendandburns) + +### Phase 4 Advancement Criteria + +_TODO before entering Phase 2._ + +## Table of Contents + +- [Introduction](#introduction) +- [Goals](#goals) +- [Non-goals](#non-goals) +- [API walk-through](#api-walk-through) + - [Use case: support various languages](#use-case-support-various-languages) +- [Detailed design discussion](#detailed-design-discussion) +- [Considered alternatives](#considered-alternatives) + - [Alternative: sockets](#alternative-sockets) +- [Stakeholder Interest & Feedback](#stakeholder-interest--feedback) +- [References & acknowledgements](#references--acknowledgements) + +### Introduction +This proposal looks to provide a standard API for http clients. This proposal +intends to add an HTTP API in addition to a Socket API so that there can +be a sandbox boundary around the L7 application layer protocol which +allows more rich controls than an L4 based sandbox. + +### Goals +- __Http Client support__: the goal of this proposal is to add the missing + functions that are required to make core HTTP requests from WebAssembly + programs. + +- __browser polyfills__: for browsers, we aim to provide a way to polyfill this + API using Web Workers providing similar functionality to what exists in + browsers today. + + + +### Non-goals +- __Streaming HTTP__: this API will not be compatible (for now) with WebSockets + or http/2 streaming. + +- __HTTP Serving__: this API is currently only concerned with HTTP client + requests, not building an HTTP server. + + + +### API walk-through + +The API consists of a single function. In pseudo-code: + +```C +void req(request_t *req, response_error_tuple_t *ret); +``` + +This will execute a single web request and return either an error or a response from the server. + +#### Use case: support various languages + +Using this API, it should be possible to implement idiomatic http clients in languages like: +- __C__, (e.g. libcurl) +- __Dotnet__, (e.g. HttpClient class) +- __Golang__, (e.g. Http) + + +### Detailed design discussion + +### Considered alternatives + +#### Alternative: Sockets + +There is a proposal to add Berkely Socket support to WASI. We believe that this effort is complimentary. +While it is feasible to implement standard HTTP clients in terms of sockets, there is not much value +in doing this in WASI/WebAssembly. There are many existing, sophisticated HTTP clients, and implementing +yet another client doesn't add much to the ecosystem. Additionally, there is nothing in this proposal +the precludes someone choosing to implement an HTTP client in WebAssembly over sockets. This proposal +enables us to support a common use case easily and securely using a host implementation that uses +existing, production-grade HTTP clients. + +### Stakeholder Interest & Feedback + +TODO before entering Phase 3. + + + + +### References & acknowledgements + +There have been various previous efforts in this space: +* https://github.com/deislabs/wasi-experimental-http +* https://github.com/deislabs/spiderlightning \ No newline at end of file diff --git a/wasi-http.wit b/wasi-http.wit new file mode 100644 index 0000000..c4ce8f6 --- /dev/null +++ b/wasi-http.wit @@ -0,0 +1,58 @@ +interface http-types { + /// The HTTP status code. + type http-status = u16 + + /// The HTTP body. + type body = list + + /// The HTTP headers represented as a list of (name, value) pairs. + type headers = list>> + + /// The HTTP parameter queries, represented as a list of (name, value) pairs. + type params = list> + + /// The HTTP URI of the current request. + type uri = string + + /// The HTTP method. + enum method { + get, + post, + put, + delete, + patch, + head, + options, + } + + /// An HTTP request. + record request { + method: method, + uri: uri, + headers: headers, + params: params, + body: option, + } + + /// An HTTP response. + record response { + status: http-status, + headers: option, + body: option, + } + + /// HTTP errors returned by the runtime. + variant http-error { + invalid-url(string), + timeout-error(string), + protocol-error(string), + status-error(u16), + unexpected-error(string) + } + + req: func(req: request) -> tuple +} + +default world wasi-http { + export exports: self.http-types +} \ No newline at end of file diff --git a/wasi-http.wit.md b/wasi-http.wit.md new file mode 100644 index 0000000..08a3284 --- /dev/null +++ b/wasi-http.wit.md @@ -0,0 +1,90 @@ +# World wasi-http + + + - Exports: + - interface `exports` + +## Export interface exports + +---- + +### Types + +#### `type uri` +`string` +

The HTTP URI of the current request. + +#### `type params` +[`params`](#params) +

The HTTP parameter queries, represented as a list of (name, value) pairs. + +#### `enum method` + +The HTTP method. + +##### Enum Cases + +- `get` +- `post` +- `put` +- `delete` +- `patch` +- `head` +- `options` +#### `type http-status` +`u16` +

The HTTP status code. + +#### `variant http-error` + +HTTP errors returned by the runtime. + +##### Variant Cases + +- `invalid-url`: `string` +- `timeout-error`: `string` +- `protocol-error`: `string` +- `status-error`: `u16` +- `unexpected-error`: `string` +#### `type headers` +[`headers`](#headers) +

The HTTP headers represented as a list of (name, value) pairs. + +#### `type body` +[`body`](#body) +

The HTTP body. + +#### `record response` + +An HTTP response. + +##### Record Fields + +- `status`: [`http-status`](#http_status) +- `headers`: option<[`headers`](#headers)> +- `body`: option<[`body`](#body)> +#### `record request` + +An HTTP request. + +##### Record Fields + +- `method`: [`method`](#method) +- `uri`: [`uri`](#uri) +- `headers`: [`headers`](#headers) +- `params`: [`params`](#params) +- `body`: option<[`body`](#body)> +---- + +### Functions + +#### `req: func` + + +##### Params + +- `req`: [`request`](#request) + +##### Return values + +- ([`response`](#response), [`http-error`](#http_error))