Skip to content
This repository was archived by the owner on Nov 25, 2025. It is now read-only.
Closed
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
102 changes: 100 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -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.

<!-- [This should include a list of implementers who have expressed interest in
implementing the proposal] -->


### References & acknowledgements

There have been various previous efforts in this space:
* https://github.com/deislabs/wasi-experimental-http
* https://github.com/deislabs/spiderlightning
58 changes: 58 additions & 0 deletions wasi-http.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
interface http-types {
/// The HTTP status code.
type http-status = u16

/// The HTTP body.
type body = list<u8>

/// The HTTP headers represented as a list of (name, value) pairs.
type headers = list<tuple<string, list<string>>>

/// The HTTP parameter queries, represented as a list of (name, value) pairs.
type params = list<tuple<string, string>>

/// 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<body>,
}

/// An HTTP response.
record response {
status: http-status,
headers: option<headers>,
body: option<body>,
}

/// 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<response, http-error>
}

default world wasi-http {
export exports: self.http-types
}
90 changes: 90 additions & 0 deletions wasi-http.wit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# <a name="wasi_http">World wasi-http</a>


- Exports:
- interface `exports`

## <a name="exports">Export interface exports</a>

----

### Types

#### <a name="uri">`type uri`</a>
`string`
<p>The HTTP URI of the current request.

#### <a name="params">`type params`</a>
[`params`](#params)
<p>The HTTP parameter queries, represented as a list of (name, value) pairs.

#### <a name="method">`enum method`</a>

The HTTP method.

##### Enum Cases

- <a name="method.get">`get`</a>
- <a name="method.post">`post`</a>
- <a name="method.put">`put`</a>
- <a name="method.delete">`delete`</a>
- <a name="method.patch">`patch`</a>
- <a name="method.head">`head`</a>
- <a name="method.options">`options`</a>
#### <a name="http_status">`type http-status`</a>
`u16`
<p>The HTTP status code.

#### <a name="http_error">`variant http-error`</a>

HTTP errors returned by the runtime.

##### Variant Cases

- <a name="http_error.invalid_url">`invalid-url`</a>: `string`
- <a name="http_error.timeout_error">`timeout-error`</a>: `string`
- <a name="http_error.protocol_error">`protocol-error`</a>: `string`
- <a name="http_error.status_error">`status-error`</a>: `u16`
- <a name="http_error.unexpected_error">`unexpected-error`</a>: `string`
#### <a name="headers">`type headers`</a>
[`headers`](#headers)
<p>The HTTP headers represented as a list of (name, value) pairs.

#### <a name="body">`type body`</a>
[`body`](#body)
<p>The HTTP body.

#### <a name="response">`record response`</a>

An HTTP response.

##### Record Fields

- <a name="response.status">`status`</a>: [`http-status`](#http_status)
- <a name="response.headers">`headers`</a>: option<[`headers`](#headers)>
- <a name="response.body">`body`</a>: option<[`body`](#body)>
#### <a name="request">`record request`</a>

An HTTP request.

##### Record Fields

- <a name="request.method">`method`</a>: [`method`](#method)
- <a name="request.uri">`uri`</a>: [`uri`](#uri)
- <a name="request.headers">`headers`</a>: [`headers`](#headers)
- <a name="request.params">`params`</a>: [`params`](#params)
- <a name="request.body">`body`</a>: option<[`body`](#body)>
----

### Functions

#### <a name="req">`req: func`</a>


##### Params

- <a name="req.req">`req`</a>: [`request`](#request)

##### Return values

- <a name="req.0"></a> ([`response`](#response), [`http-error`](#http_error))