This interface defines all of the types and methods for implementing HTTP Requests and Responses, both incoming and outgoing, as well as their headers, trailers, and bodies.
Types
use type durationsince 0.2.0
from wasi:clocks/monotonic-clock@0.2.6
A duration of time, in nanoseconds.
u64
use resource input-streamsince 0.2.0
An input bytestream.
input-streams are non-blocking to the extent practical on underlying
platforms. I/O operations always return promptly; if fewer bytes are
promptly available than requested, they return the number of bytes promptly
available, which could even be zero. To wait for data to be available,
use the subscribe function to obtain a pollable which can be polled
for using wasi:io/poll.
read: func(len: u64) -> result<list<u8>, stream-error>since 0.2.0Perform a non-blocking read from the stream.
When the source of a
readis binary data, the bytes from the source are returned verbatim. When the source of areadis known to the implementation to be text, bytes containing the UTF-8 encoding of the text are returned.This function returns a list of bytes containing the read data, when successful. The returned list will contain up to
lenbytes; it may return fewer than requested, but not more. The list is empty when no bytes are available for reading at this time. The pollable given bysubscribewill be ready when more bytes are available.This function fails with a
stream-errorwhen the operation encounters an error, givinglast-operation-failed, or when the stream is closed, givingclosed.When the caller gives a
lenof 0, it represents a request to read 0 bytes. If the stream is still open, this call should succeed and return an empty list, or otherwise fail withclosed.The
lenparameter is au64, which could represent a list of u8 which is not possible to allocate in wasm32, or not desirable to allocate as as a return value by the callee. The callee may return a list of bytes less thanlenin size while more bytes are available for reading.blocking-read: func(len: u64) -> result<list<u8>, stream-error>since 0.2.0Read bytes from a stream, after blocking until at least one byte can be read. Except for blocking, behavior is identical to
read.skip: func(len: u64) -> result<u64, stream-error>since 0.2.0Skip bytes from a stream. Returns number of bytes skipped.
Behaves identical to
read, except instead of returning a list of bytes, returns the number of bytes consumed from the stream.blocking-skip: func(len: u64) -> result<u64, stream-error>since 0.2.0Skip bytes from a stream, after blocking until at least one byte can be skipped. Except for blocking behavior, identical to
skip.subscribe: func() -> pollablesince 0.2.0Create a
pollablewhich will resolve once either the specified stream has bytes available to read or the other end of the stream has been closed. The createdpollableis a child resource of theinput-stream. Implementations may trap if theinput-streamis dropped before all derivedpollables created with this function are dropped.
use resource output-streamsince 0.2.0
An output bytestream.
output-streams are non-blocking to the extent practical on
underlying platforms. Except where specified otherwise, I/O operations also
always return promptly, after the number of bytes that can be written
promptly, which could even be zero. To wait for the stream to be ready to
accept data, the subscribe function to obtain a pollable which can be
polled for using wasi:io/poll.
Dropping an output-stream while there's still an active write in
progress may result in the data being lost. Before dropping the stream,
be sure to fully flush your writes.
check-write: func() -> result<u64, stream-error>since 0.2.0Check readiness for writing. This function never blocks.
Returns the number of bytes permitted for the next call to
write, or an error. Callingwritewith more bytes than this function has permitted will trap.When this function returns 0 bytes, the
subscribepollable will become ready when this function will report at least 1 byte, or an error.write: func(contents: list<u8>) -> result<_, stream-error>since 0.2.0Perform a write. This function never blocks.
When the destination of a
writeis binary data, the bytes fromcontentsare written verbatim. When the destination of awriteis known to the implementation to be text, the bytes ofcontentsare transcoded from UTF-8 into the encoding of the destination and then written.Precondition: check-write gave permit of Ok(n) and contents has a length of less than or equal to n. Otherwise, this function will trap.
returns Err(closed) without writing if the stream has closed since the last call to check-write provided a permit.
blocking-write-and-flush: func( contents: list<u8>, ) -> result<_, stream-error>since 0.2.0Perform a write of up to 4096 bytes, and then flush the stream. Block until all of these operations are complete, or an error occurs.
This is a convenience wrapper around the use of
check-write,subscribe,write, andflush, and is implemented with the following pseudo-code:let pollable = this.subscribe(); while !contents.is_empty() { // Wait for the stream to become writable pollable.block(); let Ok(n) = this.check-write(); // eliding error handling let len = min(n, contents.len()); let (chunk, rest) = contents.split_at(len); this.write(chunk ); // eliding error handling contents = rest; } this.flush(); // Wait for completion of `flush` pollable.block(); // Check for any errors that arose during `flush` let _ = this.check-write(); // eliding error handlingflush: func() -> result<_, stream-error>since 0.2.0Request to flush buffered output. This function never blocks.
This tells the output-stream that the caller intends any buffered output to be flushed. the output which is expected to be flushed is all that has been passed to
writeprior to this call.Upon calling this function, the
output-streamwill not accept any writes (check-writewill returnok(0)) until the flush has completed. Thesubscribepollable will become ready when the flush has completed and the stream can accept more writes.blocking-flush: func() -> result<_, stream-error>since 0.2.0Request to flush buffered output, and block until flush completes and stream is ready for writing again.
subscribe: func() -> pollablesince 0.2.0Create a
pollablewhich will resolve once the output-stream is ready for more writing, or an error has occurred. When this pollable is ready,check-writewill returnok(n)with n>0, or an error.If the stream is closed, this pollable is always ready immediately.
The created
pollableis a child resource of theoutput-stream. Implementations may trap if theoutput-streamis dropped before all derivedpollables created with this function are dropped.write-zeroes: func(len: u64) -> result<_, stream-error>since 0.2.0Write zeroes to a stream.
This should be used precisely like
writewith the exact same preconditions (must use check-write first), but instead of passing a list of bytes, you simply pass the number of zero-bytes that should be written.blocking-write-zeroes-and-flush: func( len: u64, ) -> result<_, stream-error>since 0.2.0Perform a write of up to 4096 zeroes, and then flush the stream. Block until all of these operations are complete, or an error occurs.
This is a convenience wrapper around the use of
check-write,subscribe,write-zeroes, andflush, and is implemented with the following pseudo-code:let pollable = this.subscribe(); while num_zeroes != 0 { // Wait for the stream to become writable pollable.block(); let Ok(n) = this.check-write(); // eliding error handling let len = min(n, num_zeroes); this.write-zeroes(len); // eliding error handling num_zeroes -= len; } this.flush(); // Wait for completion of `flush` pollable.block(); // Check for any errors that arose during `flush` let _ = this.check-write(); // eliding error handlingsplice: func( src: borrow<input-stream>, len: u64, ) -> result<u64, stream-error>since 0.2.0Read from one stream and write to another.
The behavior of splice is equivalent to:
- calling
check-writeon theoutput-stream - calling
readon theinput-streamwith the smaller of thecheck-writepermitted length and thelenprovided tosplice - calling
writeon theoutput-streamwith that read data.
Any error reported by the call to
check-write,read, orwriteends the splice and reports that error.This function returns the number of bytes transferred; it may be less than
len.- calling
blocking-splice: func( src: borrow<input-stream>, len: u64, ) -> result<u64, stream-error>since 0.2.0Read from one stream and write to another, with blocking.
This is similar to
splice, except that it blocks until theoutput-streamis ready for writing, and theinput-streamis ready for reading, before performing thesplice.
use resource io-errorsince 0.2.0
from wasi:io/error@0.2.6
A resource which represents some error information.
The only method provided by this resource is to-debug-string,
which provides some human-readable information about the error.
In the wasi:io package, this resource is returned through the
wasi:io/streams/stream-error type.
To provide more specific error information, other interfaces may
offer functions to "downcast" this error into more specific types. For example,
errors returned from streams derived from filesystem types can be described using
the filesystem's own error-code type. This is done using the function
wasi:filesystem/types/filesystem-error-code, which takes a borrow<error>
parameter and returns an option<wasi:filesystem/types/error-code>.
The set of functions which can "downcast" an error into a more
concrete type is open.
to-debug-string: func() -> stringsince 0.2.0Returns a string that is suitable to assist humans in debugging this error.
WARNING: The returned string should not be consumed mechanically! It may change across platforms, hosts, or other implementation details. Parsing this string is a major platform-compatibility hazard.
use resource pollablesince 0.2.0
from wasi:io/poll@0.2.6
pollable represents a single I/O event which may be ready, or not.
ready: func() -> boolsince 0.2.0Return the readiness of a pollable. This function never blocks.
Returns
truewhen the pollable is ready, andfalseotherwise.block: func()since 0.2.0blockreturns immediately if the pollable is ready, and otherwise blocks until ready.This function is equivalent to calling
poll.pollon a list containing only this pollable.
variant methodsince 0.2.0
This type corresponds to HTTP standard Methods.
getheadpostputdeleteconnectoptionstracepatchother:string
variant schemesince 0.2.0
This type corresponds to HTTP standard Related Schemes.
HTTPHTTPSother:string
record DNS-error-payloadsince 0.2.0
Defines the case payload type for DNS-error above:
rcode:option<string>info-code:option<u16>
record TLS-alert-received-payloadsince 0.2.0
Defines the case payload type for TLS-alert-received above:
alert-id:option<u8>alert-message:option<string>
record field-size-payloadsince 0.2.0
Defines the case payload type for HTTP-response-{header,trailer}-size above:
field-name:option<string>field-size:option<u32>
variant error-codesince 0.2.0
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
DNS-timeoutDNS-error:DNS-error-payloaddestination-not-founddestination-unavailabledestination-IP-prohibiteddestination-IP-unroutableconnection-refusedconnection-terminatedconnection-timeoutconnection-read-timeoutconnection-write-timeoutconnection-limit-reachedTLS-protocol-errorTLS-certificate-errorTLS-alert-received:TLS-alert-received-payloadHTTP-request-deniedHTTP-request-length-requiredHTTP-request-body-size:option<u64>HTTP-request-method-invalidHTTP-request-URI-invalidHTTP-request-URI-too-longHTTP-request-header-section-size:option<u32>HTTP-request-header-size:option<field-size-payload>HTTP-request-trailer-section-size:option<u32>HTTP-request-trailer-size:field-size-payloadHTTP-response-incompleteHTTP-response-header-section-size:option<u32>HTTP-response-header-size:field-size-payloadHTTP-response-body-size:option<u64>HTTP-response-trailer-section-size:option<u32>HTTP-response-trailer-size:field-size-payloadHTTP-response-transfer-coding:option<string>HTTP-response-content-coding:option<string>HTTP-response-timeoutHTTP-upgrade-failedHTTP-protocol-errorloop-detectedconfiguration-errorinternal-error:option<string>This is a catch-all error for anything that doesn't fit cleanly into a more specific case. It also includes an optional string for an unstructured description of the error. Users should not depend on the string for diagnosing errors, as it's not required to be consistent between implementations.
variant header-errorsince 0.2.0
This type enumerates the different kinds of errors that may occur when
setting or appending to a fields resource.
invalid-syntaxThis error indicates that a
field-nameorfield-valuewas syntactically invalid when used with an operation that sets headers in afields.forbiddenThis error indicates that a forbidden
field-namewas used when trying to set a header in afields.immutableThis error indicates that the operation on the
fieldswas not permitted because the fields are immutable.
type field-keysince 0.2.0deprecated 0.2.2
Field keys are always strings.
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.
string
type field-namesince 0.2.1
Field names are always strings.
Field names should always be treated as case insensitive by the fields
resource for the purposes of equality checking.
type field-valuesince 0.2.0
Field values should always be ASCII strings. However, in reality, HTTP implementations often have to interpret malformed values, so they are provided as a list of bytes.
list<u8>
resource fieldssince 0.2.0
This following block defines the fields resource which corresponds to
HTTP standard Fields. Fields are a common representation used for both
Headers and Trailers.
A fields may be mutable or immutable. A fields created using the
constructor, from-list, or clone will be mutable, but a fields
resource given by other means (including, but not limited to,
incoming-request.headers, outgoing-request.headers) might be
immutable. In an immutable fields, the set, append, and delete
operations will fail with header-error.immutable.
constructor()since 0.2.0Construct an empty HTTP Fields.
The resulting
fieldsis mutable.from-list: static func( entries: list<tuple<field-name, field-value>>, ) -> result<fields, header-error>since 0.2.0Construct an HTTP Fields.
The resulting
fieldsis mutable.The list represents each name-value pair in the Fields. Names which have multiple values are represented by multiple entries in this list with the same name.
The tuple is a pair of the field name, represented as a string, and Value, represented as a list of bytes.
An error result will be returned if any
field-nameorfield-valueis syntactically invalid, or if a field is forbidden.get: func(name: field-name) -> list<field-value>since 0.2.0Get all of the values corresponding to a name. If the name is not present in this
fieldsor is syntactically invalid, an empty list is returned. However, if the name is present but empty, this is represented by a list with one or more empty field-values present.has: func(name: field-name) -> boolsince 0.2.0Returns
truewhen the name is present in thisfields. If the name is syntactically invalid,falseis returned.set: func( name: field-name, value: list<field-value>, ) -> result<_, header-error>since 0.2.0Set all of the values for a name. Clears any existing values for that name, if they have been set.
Fails with
header-error.immutableif thefieldsare immutable.Fails with
header-error.invalid-syntaxif thefield-nameor any of thefield-values are syntactically invalid.delete: func(name: field-name) -> result<_, header-error>since 0.2.0Delete all values for a name. Does nothing if no values for the name exist.
Fails with
header-error.immutableif thefieldsare immutable.Fails with
header-error.invalid-syntaxif thefield-nameis syntactically invalid.append: func( name: field-name, value: field-value, ) -> result<_, header-error>since 0.2.0Append a value for a name. Does not change or delete any existing values for that name.
Fails with
header-error.immutableif thefieldsare immutable.Fails with
header-error.invalid-syntaxif thefield-nameorfield-valueare syntactically invalid.entries: func() -> list<tuple<field-name, field-value>>since 0.2.0Retrieve the full set of names and values in the Fields. Like the constructor, the list represents each name-value pair.
The outer list represents each name-value pair in the Fields. Names which have multiple values are represented by multiple entries in this list with the same name.
The names and values are always returned in the original casing and in the order in which they will be serialized for transport.
clone: func() -> fieldssince 0.2.0Make a deep copy of the Fields. Equivalent in behavior to calling the
fieldsconstructor on the return value ofentries. The resultingfieldsis mutable.
resource incoming-requestsince 0.2.0
Represents an incoming HTTP Request.
method: func() -> methodsince 0.2.0Returns the method of the incoming request.
path-with-query: func() -> option<string>since 0.2.0Returns the path with query parameters from the request, as a string.
scheme: func() -> option<scheme>since 0.2.0Returns the protocol scheme from the request.
headers: func() -> headerssince 0.2.0Get the
headersassociated with the request.The returned
headersresource is immutable:set,append, anddeleteoperations will fail withheader-error.immutable.The
headersreturned are a child resource: it must be dropped before the parentincoming-requestis dropped. Dropping thisincoming-requestbefore all children are dropped will trap.consume: func() -> result<incoming-body>since 0.2.0Gives the
incoming-bodyassociated with this request. Will only return success at most once, and subsequent calls will return error.
resource outgoing-requestsince 0.2.0
Represents an outgoing HTTP Request.
constructor(headers: headers)since 0.2.0Construct a new
outgoing-requestwith a defaultmethodofGET, andnonevalues forpath-with-query,scheme, andauthority.headersis the HTTP Headers for the Request.
It is possible to construct, or manipulate with the accessor functions below, an
outgoing-requestwith an invalid combination ofschemeandauthority, orheaderswhich are not permitted to be sent. It is the obligation of theoutgoing-handler.handleimplementation to reject invalid constructions ofoutgoing-request.body: func() -> result<outgoing-body>since 0.2.0Returns the resource corresponding to the outgoing Body for this Request.
Returns success on the first call: the
outgoing-bodyresource for thisoutgoing-requestcan be retrieved at most once. Subsequent calls will return error.method: func() -> methodsince 0.2.0Get the Method for the Request.
set-method: func(method: method) -> resultsince 0.2.0Set the Method for the Request. Fails if the string present in a
method.otherargument is not a syntactically valid method.path-with-query: func() -> option<string>since 0.2.0Get the combination of the HTTP Path and Query for the Request. When
none, this represents an empty Path and empty Query.set-path-with-query: func(path-with-query: option<string>) -> resultsince 0.2.0Set the combination of the HTTP Path and Query for the Request. When
none, this represents an empty Path and empty Query. Fails is the string given is not a syntactically valid path and query uri component.scheme: func() -> option<scheme>since 0.2.0Get the HTTP Related Scheme for the Request. When
none, the implementation may choose an appropriate default scheme.set-scheme: func(scheme: option<scheme>) -> resultsince 0.2.0Set the HTTP Related Scheme for the Request. When
none, the implementation may choose an appropriate default scheme. Fails if the string given is not a syntactically valid uri scheme.headers: func() -> headerssince 0.2.0Get the headers associated with the Request.
The returned
headersresource is immutable:set,append, anddeleteoperations will fail withheader-error.immutable.This headers resource is a child: it must be dropped before the parent
outgoing-requestis dropped, or its ownership is transferred to another component by e.g.outgoing-handler.handle.
resource request-optionssince 0.2.0
Parameters for making an HTTP Request. Each of these parameters is currently an optional timeout applicable to the transport layer of the HTTP protocol.
These timeouts are separate from any the user may use to bound a
blocking call to wasi:io/poll.poll.
constructor()since 0.2.0Construct a default
request-optionsvalue.connect-timeout: func() -> option<duration>since 0.2.0The timeout for the initial connect to the HTTP Server.
set-connect-timeout: func(duration: option<duration>) -> resultsince 0.2.0Set the timeout for the initial connect to the HTTP Server. An error return value indicates that this timeout is not supported.
first-byte-timeout: func() -> option<duration>since 0.2.0The timeout for receiving the first byte of the Response body.
set-first-byte-timeout: func(duration: option<duration>) -> resultsince 0.2.0Set the timeout for receiving the first byte of the Response body. An error return value indicates that this timeout is not supported.
between-bytes-timeout: func() -> option<duration>since 0.2.0The timeout for receiving subsequent chunks of bytes in the Response body stream.
set-between-bytes-timeout: func(duration: option<duration>) -> resultsince 0.2.0Set the timeout for receiving subsequent chunks of bytes in the Response body stream. An error return value indicates that this timeout is not supported.
resource response-outparamsince 0.2.0
Represents the ability to send an HTTP Response.
This resource is used by the wasi:http/incoming-handler interface to
allow a Response to be sent corresponding to the Request provided as the
other argument to incoming-handler.handle.
set: static func( param: response-outparam, response: result<outgoing-response, error-code>, )since 0.2.0Set the value of the
response-outparamto either send a response, or indicate an error.This method consumes the
response-outparamto ensure that it is called at most once. If it is never called, the implementation will respond with an error.The user may provide an
errortoresponseto allow the implementation determine how to respond with an HTTP error response.
type status-codesince 0.2.0
This type corresponds to the HTTP standard Status Code.
u16
resource incoming-responsesince 0.2.0
Represents an incoming HTTP Response.
status: func() -> status-codesince 0.2.0Returns the status code from the incoming response.
headers: func() -> headerssince 0.2.0Returns the headers from the incoming response.
The returned
headersresource is immutable:set,append, anddeleteoperations will fail withheader-error.immutable.This headers resource is a child: it must be dropped before the parent
incoming-responseis dropped.consume: func() -> result<incoming-body>since 0.2.0Returns the incoming body. May be called at most once. Returns error if called additional times.
resource incoming-bodysince 0.2.0
Represents an incoming HTTP Request or Response's Body.
A body has both its contents - a stream of bytes - and a (possibly
empty) set of trailers, indicating that the full contents of the
body have been received. This resource represents the contents as
an input-stream and the delivery of trailers as a future-trailers,
and ensures that the user of this interface may only be consuming either
the body contents or waiting on trailers at any given time.
stream: func() -> result<input-stream>since 0.2.0Returns the contents of the body, as a stream of bytes.
Returns success on first call: the stream representing the contents can be retrieved at most once. Subsequent calls will return error.
The returned
input-streamresource is a child: it must be dropped before the parentincoming-bodyis dropped, or consumed byincoming-body.finish.This invariant ensures that the implementation can determine whether the user is consuming the contents of the body, waiting on the
future-trailersto be ready, or neither. This allows for network backpressure is to be applied when the user is consuming the body, and for that backpressure to not inhibit delivery of the trailers if the user does not read the entire body.finish: static func(this: incoming-body) -> future-trailerssince 0.2.0Takes ownership of
incoming-body, and returns afuture-trailers. This function will trap if theinput-streamchild is still alive.
resource future-trailerssince 0.2.0
Represents a future which may eventually return trailers, or an error.
In the case that the incoming HTTP Request or Response did not have any trailers, this future will resolve to the empty set of trailers once the complete Request or Response body has been received.
subscribe: func() -> pollablesince 0.2.0Returns a pollable which becomes ready when either the trailers have been received, or an error has occurred. When this pollable is ready, the
getmethod will returnsome.get: func() -> option<result<result<option<trailers>, error-code>>>since 0.2.0Returns the contents of the trailers, or an error which occurred, once the future is ready.
The outer
optionrepresents future readiness. Users can wait on thisoptionto becomesomeusing thesubscribemethod.The outer
resultis used to retrieve the trailers or error at most once. It will be success on the first call in which the outer option issome, and error on subsequent calls.The inner
resultrepresents that either the HTTP Request or Response body, as well as any trailers, were received successfully, or that an error occurred receiving them. The optionaltrailersindicates whether or not trailers were present in the body.When some
trailersare returned by this method, thetrailersresource is immutable, and a child. Use of theset,append, ordeletemethods will return an error, and the resource must be dropped before the parentfuture-trailersis dropped.
resource outgoing-responsesince 0.2.0
Represents an outgoing HTTP Response.
constructor(headers: headers)since 0.2.0Construct an
outgoing-response, with a defaultstatus-codeof200. If a differentstatus-codeis needed, it must be set via theset-status-codemethod.headersis the HTTP Headers for the Response.
status-code: func() -> status-codesince 0.2.0Get the HTTP Status Code for the Response.
set-status-code: func(status-code: status-code) -> resultsince 0.2.0Set the HTTP Status Code for the Response. Fails if the status-code given is not a valid http status code.
headers: func() -> headerssince 0.2.0Get the headers associated with the Request.
The returned
headersresource is immutable:set,append, anddeleteoperations will fail withheader-error.immutable.This headers resource is a child: it must be dropped before the parent
outgoing-requestis dropped, or its ownership is transferred to another component by e.g.outgoing-handler.handle.body: func() -> result<outgoing-body>since 0.2.0Returns the resource corresponding to the outgoing Body for this Response.
Returns success on the first call: the
outgoing-bodyresource for thisoutgoing-responsecan be retrieved at most once. Subsequent calls will return error.
resource outgoing-bodysince 0.2.0
Represents an outgoing HTTP Request or Response's Body.
A body has both its contents - a stream of bytes - and a (possibly
empty) set of trailers, inducating the full contents of the body
have been sent. This resource represents the contents as an
output-stream child resource, and the completion of the body (with
optional trailers) with a static function that consumes the
outgoing-body resource, and ensures that the user of this interface
may not write to the body contents after the body has been finished.
If the user code drops this resource, as opposed to calling the static
method finish, the implementation should treat the body as incomplete,
and that an error has occurred. The implementation should propagate this
error to the HTTP protocol by whatever means it has available,
including: corrupting the body on the wire, aborting the associated
Request, or sending a late status code for the Response.
write: func() -> result<output-stream>since 0.2.0Returns a stream for writing the body contents.
The returned
output-streamis a child resource: it must be dropped before the parentoutgoing-bodyresource is dropped (or finished), otherwise theoutgoing-bodydrop orfinishwill trap.Returns success on the first call: the
output-streamresource for thisoutgoing-bodymay be retrieved at most once. Subsequent calls will return error.finish: static func( this: outgoing-body, trailers: option<trailers>, ) -> result<_, error-code>since 0.2.0Finalize an outgoing body, optionally providing trailers. This must be called to signal that the response is complete. If the
outgoing-bodyis dropped without callingoutgoing-body.finalize, the implementation should treat the body as corrupted.Fails if the body's
outgoing-requestoroutgoing-responsewas constructed with a Content-Length header, and the contents written to the body (viawrite) does not match the value given in the Content-Length.
resource future-incoming-responsesince 0.2.0
Represents a future which may eventually return an incoming HTTP Response, or an error.
This resource is returned by the wasi:http/outgoing-handler interface to
provide the HTTP Response corresponding to the sent Request.
subscribe: func() -> pollablesince 0.2.0Returns a pollable which becomes ready when either the Response has been received, or an error has occurred. When this pollable is ready, the
getmethod will returnsome.get: func() -> option<result<result<incoming-response, error-code>>>since 0.2.0Returns the incoming HTTP Response, or an error, once one is ready.
The outer
optionrepresents future readiness. Users can wait on thisoptionto becomesomeusing thesubscribemethod.The outer
resultis used to retrieve the response or error at most once. It will be success on the first call in which the outer option issome, and error on subsequent calls.The inner
resultrepresents that either the incoming HTTP Response status and headers have received successfully, or that an error occurred. Errors may also occur while consuming the response body, but those will be reported by theincoming-bodyand itsoutput-streamchild.
Functions
http-error-code: func(err: borrow<io-error>) -> option<error-code>since 0.2.0
Attempts to extract a http-related error from the wasi:io error
provided.
Stream operations which return
wasi:io/stream/stream-error::last-operation-failed have a payload of
type wasi:io/error/error with more information about the operation
that failed. This payload can be passed through to this function to see
if there's http-related information about the error to return.
Note that this function is fallible because not all io-errors are http-related errors.
WIT
/// This interface defines all of the types and methods for implementing
/// HTTP Requests and Responses, both incoming and outgoing, as well as
/// their headers, trailers, and bodies.
@since(version = 0.2.0)
interface types {
@since(version = 0.2.0)
use wasi:clocks/monotonic-clock@0.2.6.{duration};
@since(version = 0.2.0)
use wasi:io/streams@0.2.6.{input-stream, output-stream};
@since(version = 0.2.0)
use wasi:io/error@0.2.6.{error as io-error};
@since(version = 0.2.0)
use wasi:io/poll@0.2.6.{pollable};
/// This type corresponds to HTTP standard Methods.
@since(version = 0.2.0)
variant method {
get,
head,
post,
put,
delete,
connect,
options,
trace,
patch,
other(string),
}
/// This type corresponds to HTTP standard Related Schemes.
@since(version = 0.2.0)
variant scheme {
HTTP,
HTTPS,
other(string),
}
/// Defines the case payload type for `DNS-error` above:
@since(version = 0.2.0)
record DNS-error-payload {
rcode: option<string>,
info-code: option<u16>,
}
/// Defines the case payload type for `TLS-alert-received` above:
@since(version = 0.2.0)
record TLS-alert-received-payload {
alert-id: option<u8>,
alert-message: option<string>,
}
/// Defines the case payload type for `HTTP-response-{header,trailer}-size` above:
@since(version = 0.2.0)
record field-size-payload {
field-name: option<string>,
field-size: option<u32>,
}
/// 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>
@since(version = 0.2.0)
variant error-code {
DNS-timeout,
DNS-error(DNS-error-payload),
destination-not-found,
destination-unavailable,
destination-IP-prohibited,
destination-IP-unroutable,
connection-refused,
connection-terminated,
connection-timeout,
connection-read-timeout,
connection-write-timeout,
connection-limit-reached,
TLS-protocol-error,
TLS-certificate-error,
TLS-alert-received(TLS-alert-received-payload),
HTTP-request-denied,
HTTP-request-length-required,
HTTP-request-body-size(option<u64>),
HTTP-request-method-invalid,
HTTP-request-URI-invalid,
HTTP-request-URI-too-long,
HTTP-request-header-section-size(option<u32>),
HTTP-request-header-size(option<field-size-payload>),
HTTP-request-trailer-section-size(option<u32>),
HTTP-request-trailer-size(field-size-payload),
HTTP-response-incomplete,
HTTP-response-header-section-size(option<u32>),
HTTP-response-header-size(field-size-payload),
HTTP-response-body-size(option<u64>),
HTTP-response-trailer-section-size(option<u32>),
HTTP-response-trailer-size(field-size-payload),
HTTP-response-transfer-coding(option<string>),
HTTP-response-content-coding(option<string>),
HTTP-response-timeout,
HTTP-upgrade-failed,
HTTP-protocol-error,
loop-detected,
configuration-error,
/// This is a catch-all error for anything that doesn't fit cleanly into a
/// more specific case. It also includes an optional string for an
/// unstructured description of the error. Users should not depend on the
/// string for diagnosing errors, as it's not required to be consistent
/// between implementations.
internal-error(option<string>),
}
/// This type enumerates the different kinds of errors that may occur when
/// setting or appending to a `fields` resource.
@since(version = 0.2.0)
variant header-error {
/// This error indicates that a `field-name` or `field-value` was
/// syntactically invalid when used with an operation that sets headers in a
/// `fields`.
invalid-syntax,
/// This error indicates that a forbidden `field-name` was used when trying
/// to set a header in a `fields`.
forbidden,
/// This error indicates that the operation on the `fields` was not
/// permitted because the fields are immutable.
immutable,
}
/// Field keys are always strings.
///
/// 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)
type field-key = string;
/// Field names are always strings.
///
/// Field names should always be treated as case insensitive by the `fields`
/// resource for the purposes of equality checking.
@since(version = 0.2.1)
type field-name = field-key;
/// Field values should always be ASCII strings. However, in
/// reality, HTTP implementations often have to interpret malformed values,
/// so they are provided as a list of bytes.
@since(version = 0.2.0)
type field-value = list<u8>;
/// This following block defines the `fields` resource which corresponds to
/// HTTP standard Fields. Fields are a common representation used for both
/// Headers and Trailers.
///
/// A `fields` may be mutable or immutable. A `fields` created using the
/// constructor, `from-list`, or `clone` will be mutable, but a `fields`
/// resource given by other means (including, but not limited to,
/// `incoming-request.headers`, `outgoing-request.headers`) might be
/// immutable. In an immutable fields, the `set`, `append`, and `delete`
/// operations will fail with `header-error.immutable`.
@since(version = 0.2.0)
resource fields {
/// Construct an empty HTTP Fields.
///
/// The resulting `fields` is mutable.
@since(version = 0.2.0)
constructor();
/// Construct an HTTP Fields.
///
/// The resulting `fields` is mutable.
///
/// The list represents each name-value pair in the Fields. Names
/// which have multiple values are represented by multiple entries in this
/// list with the same name.
///
/// The tuple is a pair of the field name, represented as a string, and
/// Value, represented as a list of bytes.
///
/// An error result will be returned if any `field-name` or `field-value` is
/// syntactically invalid, or if a field is forbidden.
@since(version = 0.2.0)
from-list: static func(entries: list<tuple<field-name, field-value>>) -> result<fields, header-error>;
/// Get all of the values corresponding to a name. If the name is not present
/// in this `fields` or is syntactically invalid, an empty list is returned.
/// However, if the name is present but empty, this is represented by a list
/// with one or more empty field-values present.
@since(version = 0.2.0)
get: func(name: field-name) -> list<field-value>;
/// Returns `true` when the name is present in this `fields`. If the name is
/// syntactically invalid, `false` is returned.
@since(version = 0.2.0)
has: func(name: field-name) -> bool;
/// Set all of the values for a name. Clears any existing values for that
/// name, if they have been set.
///
/// Fails with `header-error.immutable` if the `fields` are immutable.
///
/// Fails with `header-error.invalid-syntax` if the `field-name` or any of
/// the `field-value`s are syntactically invalid.
@since(version = 0.2.0)
set: func(name: field-name, value: list<field-value>) -> result<_, header-error>;
/// Delete all values for a name. Does nothing if no values for the name
/// exist.
///
/// Fails with `header-error.immutable` if the `fields` are immutable.
///
/// Fails with `header-error.invalid-syntax` if the `field-name` is
/// syntactically invalid.
@since(version = 0.2.0)
delete: func(name: field-name) -> result<_, header-error>;
/// Append a value for a name. Does not change or delete any existing
/// values for that name.
///
/// Fails with `header-error.immutable` if the `fields` are immutable.
///
/// Fails with `header-error.invalid-syntax` if the `field-name` or
/// `field-value` are syntactically invalid.
@since(version = 0.2.0)
append: func(name: field-name, value: field-value) -> result<_, header-error>;
/// Retrieve the full set of names and values in the Fields. Like the
/// constructor, the list represents each name-value pair.
///
/// The outer list represents each name-value pair in the Fields. Names
/// which have multiple values are represented by multiple entries in this
/// list with the same name.
///
/// The names and values are always returned in the original casing and in
/// the order in which they will be serialized for transport.
@since(version = 0.2.0)
entries: func() -> list<tuple<field-name, field-value>>;
/// Make a deep copy of the Fields. Equivalent in behavior to calling the
/// `fields` constructor on the return value of `entries`. The resulting
/// `fields` is mutable.
@since(version = 0.2.0)
clone: func() -> fields;
}
/// Headers is an alias for Fields.
@since(version = 0.2.0)
type headers = fields;
/// Trailers is an alias for Fields.
@since(version = 0.2.0)
type trailers = fields;
/// Represents an incoming HTTP Request.
@since(version = 0.2.0)
resource incoming-request {
/// Returns the method of the incoming request.
@since(version = 0.2.0)
method: func() -> method;
/// Returns the path with query parameters from the request, as a string.
@since(version = 0.2.0)
path-with-query: func() -> option<string>;
/// Returns the protocol scheme from the request.
@since(version = 0.2.0)
scheme: func() -> option<scheme>;
/// Returns the authority of the Request's target URI, if present.
@since(version = 0.2.0)
authority: func() -> option<string>;
/// Get the `headers` associated with the request.
///
/// The returned `headers` resource is immutable: `set`, `append`, and
/// `delete` operations will fail with `header-error.immutable`.
///
/// The `headers` returned are a child resource: it must be dropped before
/// the parent `incoming-request` is dropped. Dropping this
/// `incoming-request` before all children are dropped will trap.
@since(version = 0.2.0)
headers: func() -> headers;
/// Gives the `incoming-body` associated with this request. Will only
/// return success at most once, and subsequent calls will return error.
@since(version = 0.2.0)
consume: func() -> result<incoming-body>;
}
/// Represents an outgoing HTTP Request.
@since(version = 0.2.0)
resource outgoing-request {
/// Construct a new `outgoing-request` with a default `method` of `GET`, and
/// `none` values for `path-with-query`, `scheme`, and `authority`.
///
/// * `headers` is the HTTP Headers for the Request.
///
/// It is possible to construct, or manipulate with the accessor functions
/// below, an `outgoing-request` with an invalid combination of `scheme`
/// and `authority`, or `headers` which are not permitted to be sent.
/// It is the obligation of the `outgoing-handler.handle` implementation
/// to reject invalid constructions of `outgoing-request`.
@since(version = 0.2.0)
constructor(headers: headers);
/// Returns the resource corresponding to the outgoing Body for this
/// Request.
///
/// Returns success on the first call: the `outgoing-body` resource for
/// this `outgoing-request` can be retrieved at most once. Subsequent
/// calls will return error.
@since(version = 0.2.0)
body: func() -> result<outgoing-body>;
/// Get the Method for the Request.
@since(version = 0.2.0)
method: func() -> method;
/// Set the Method for the Request. Fails if the string present in a
/// `method.other` argument is not a syntactically valid method.
@since(version = 0.2.0)
set-method: func(method: method) -> result;
/// Get the combination of the HTTP Path and Query for the Request.
/// When `none`, this represents an empty Path and empty Query.
@since(version = 0.2.0)
path-with-query: func() -> option<string>;
/// Set the combination of the HTTP Path and Query for the Request.
/// When `none`, this represents an empty Path and empty Query. Fails is the
/// string given is not a syntactically valid path and query uri component.
@since(version = 0.2.0)
set-path-with-query: func(path-with-query: option<string>) -> result;
/// Get the HTTP Related Scheme for the Request. When `none`, the
/// implementation may choose an appropriate default scheme.
@since(version = 0.2.0)
scheme: func() -> option<scheme>;
/// Set the HTTP Related Scheme for the Request. When `none`, the
/// implementation may choose an appropriate default scheme. Fails if the
/// string given is not a syntactically valid uri scheme.
@since(version = 0.2.0)
set-scheme: func(scheme: option<scheme>) -> result;
/// Get the authority of the Request's target URI. A value of `none` may be used
/// with Related Schemes which do not require an authority. The HTTP and
/// HTTPS schemes always require an authority.
@since(version = 0.2.0)
authority: func() -> option<string>;
/// Set the authority of the Request's target URI. A value of `none` may be used
/// with Related Schemes which do not require an authority. The HTTP and
/// HTTPS schemes always require an authority. Fails if the string given is
/// not a syntactically valid URI authority.
@since(version = 0.2.0)
set-authority: func(authority: option<string>) -> result;
/// Get the headers associated with the Request.
///
/// The returned `headers` resource is immutable: `set`, `append`, and
/// `delete` operations will fail with `header-error.immutable`.
///
/// This headers resource is a child: it must be dropped before the parent
/// `outgoing-request` is dropped, or its ownership is transferred to
/// another component by e.g. `outgoing-handler.handle`.
@since(version = 0.2.0)
headers: func() -> headers;
}
/// Parameters for making an HTTP Request. Each of these parameters is
/// currently an optional timeout applicable to the transport layer of the
/// HTTP protocol.
///
/// These timeouts are separate from any the user may use to bound a
/// blocking call to `wasi:io/poll.poll`.
@since(version = 0.2.0)
resource request-options {
/// Construct a default `request-options` value.
@since(version = 0.2.0)
constructor();
/// The timeout for the initial connect to the HTTP Server.
@since(version = 0.2.0)
connect-timeout: func() -> option<duration>;
/// Set the timeout for the initial connect to the HTTP Server. An error
/// return value indicates that this timeout is not supported.
@since(version = 0.2.0)
set-connect-timeout: func(duration: option<duration>) -> result;
/// The timeout for receiving the first byte of the Response body.
@since(version = 0.2.0)
first-byte-timeout: func() -> option<duration>;
/// Set the timeout for receiving the first byte of the Response body. An
/// error return value indicates that this timeout is not supported.
@since(version = 0.2.0)
set-first-byte-timeout: func(duration: option<duration>) -> result;
/// The timeout for receiving subsequent chunks of bytes in the Response
/// body stream.
@since(version = 0.2.0)
between-bytes-timeout: func() -> option<duration>;
/// Set the timeout for receiving subsequent chunks of bytes in the Response
/// body stream. An error return value indicates that this timeout is not
/// supported.
@since(version = 0.2.0)
set-between-bytes-timeout: func(duration: option<duration>) -> result;
}
/// Represents the ability to send an HTTP Response.
///
/// This resource is used by the `wasi:http/incoming-handler` interface to
/// allow a Response to be sent corresponding to the Request provided as the
/// other argument to `incoming-handler.handle`.
@since(version = 0.2.0)
resource response-outparam {
/// Set the value of the `response-outparam` to either send a response,
/// or indicate an error.
///
/// This method consumes the `response-outparam` to ensure that it is
/// called at most once. If it is never called, the implementation
/// will respond with an error.
///
/// The user may provide an `error` to `response` to allow the
/// implementation determine how to respond with an HTTP error response.
@since(version = 0.2.0)
set: static func(param: response-outparam, response: result<outgoing-response, error-code>);
}
/// This type corresponds to the HTTP standard Status Code.
@since(version = 0.2.0)
type status-code = u16;
/// Represents an incoming HTTP Response.
@since(version = 0.2.0)
resource incoming-response {
/// Returns the status code from the incoming response.
@since(version = 0.2.0)
status: func() -> status-code;
/// Returns the headers from the incoming response.
///
/// The returned `headers` resource is immutable: `set`, `append`, and
/// `delete` operations will fail with `header-error.immutable`.
///
/// This headers resource is a child: it must be dropped before the parent
/// `incoming-response` is dropped.
@since(version = 0.2.0)
headers: func() -> headers;
/// Returns the incoming body. May be called at most once. Returns error
/// if called additional times.
@since(version = 0.2.0)
consume: func() -> result<incoming-body>;
}
/// Represents an incoming HTTP Request or Response's Body.
///
/// A body has both its contents - a stream of bytes - and a (possibly
/// empty) set of trailers, indicating that the full contents of the
/// body have been received. This resource represents the contents as
/// an `input-stream` and the delivery of trailers as a `future-trailers`,
/// and ensures that the user of this interface may only be consuming either
/// the body contents or waiting on trailers at any given time.
@since(version = 0.2.0)
resource incoming-body {
/// Returns the contents of the body, as a stream of bytes.
///
/// Returns success on first call: the stream representing the contents
/// can be retrieved at most once. Subsequent calls will return error.
///
/// The returned `input-stream` resource is a child: it must be dropped
/// before the parent `incoming-body` is dropped, or consumed by
/// `incoming-body.finish`.
///
/// This invariant ensures that the implementation can determine whether
/// the user is consuming the contents of the body, waiting on the
/// `future-trailers` to be ready, or neither. This allows for network
/// backpressure is to be applied when the user is consuming the body,
/// and for that backpressure to not inhibit delivery of the trailers if
/// the user does not read the entire body.
@since(version = 0.2.0)
%stream: func() -> result<input-stream>;
/// Takes ownership of `incoming-body`, and returns a `future-trailers`.
/// This function will trap if the `input-stream` child is still alive.
@since(version = 0.2.0)
finish: static func(this: incoming-body) -> future-trailers;
}
/// Represents a future which may eventually return trailers, or an error.
///
/// In the case that the incoming HTTP Request or Response did not have any
/// trailers, this future will resolve to the empty set of trailers once the
/// complete Request or Response body has been received.
@since(version = 0.2.0)
resource future-trailers {
/// Returns a pollable which becomes ready when either the trailers have
/// been received, or an error has occurred. When this pollable is ready,
/// the `get` method will return `some`.
@since(version = 0.2.0)
subscribe: func() -> pollable;
/// Returns the contents of the trailers, or an error which occurred,
/// once the future is ready.
///
/// The outer `option` represents future readiness. Users can wait on this
/// `option` to become `some` using the `subscribe` method.
///
/// The outer `result` is used to retrieve the trailers or error at most
/// once. It will be success on the first call in which the outer option
/// is `some`, and error on subsequent calls.
///
/// The inner `result` represents that either the HTTP Request or Response
/// body, as well as any trailers, were received successfully, or that an
/// error occurred receiving them. The optional `trailers` indicates whether
/// or not trailers were present in the body.
///
/// When some `trailers` are returned by this method, the `trailers`
/// resource is immutable, and a child. Use of the `set`, `append`, or
/// `delete` methods will return an error, and the resource must be
/// dropped before the parent `future-trailers` is dropped.
@since(version = 0.2.0)
get: func() -> option<result<result<option<trailers>, error-code>>>;
}
/// Represents an outgoing HTTP Response.
@since(version = 0.2.0)
resource outgoing-response {
/// Construct an `outgoing-response`, with a default `status-code` of `200`.
/// If a different `status-code` is needed, it must be set via the
/// `set-status-code` method.
///
/// * `headers` is the HTTP Headers for the Response.
@since(version = 0.2.0)
constructor(headers: headers);
/// Get the HTTP Status Code for the Response.
@since(version = 0.2.0)
status-code: func() -> status-code;
/// Set the HTTP Status Code for the Response. Fails if the status-code
/// given is not a valid http status code.
@since(version = 0.2.0)
set-status-code: func(status-code: status-code) -> result;
/// Get the headers associated with the Request.
///
/// The returned `headers` resource is immutable: `set`, `append`, and
/// `delete` operations will fail with `header-error.immutable`.
///
/// This headers resource is a child: it must be dropped before the parent
/// `outgoing-request` is dropped, or its ownership is transferred to
/// another component by e.g. `outgoing-handler.handle`.
@since(version = 0.2.0)
headers: func() -> headers;
/// Returns the resource corresponding to the outgoing Body for this Response.
///
/// Returns success on the first call: the `outgoing-body` resource for
/// this `outgoing-response` can be retrieved at most once. Subsequent
/// calls will return error.
@since(version = 0.2.0)
body: func() -> result<outgoing-body>;
}
/// Represents an outgoing HTTP Request or Response's Body.
///
/// A body has both its contents - a stream of bytes - and a (possibly
/// empty) set of trailers, inducating the full contents of the body
/// have been sent. This resource represents the contents as an
/// `output-stream` child resource, and the completion of the body (with
/// optional trailers) with a static function that consumes the
/// `outgoing-body` resource, and ensures that the user of this interface
/// may not write to the body contents after the body has been finished.
///
/// If the user code drops this resource, as opposed to calling the static
/// method `finish`, the implementation should treat the body as incomplete,
/// and that an error has occurred. The implementation should propagate this
/// error to the HTTP protocol by whatever means it has available,
/// including: corrupting the body on the wire, aborting the associated
/// Request, or sending a late status code for the Response.
@since(version = 0.2.0)
resource outgoing-body {
/// Returns a stream for writing the body contents.
///
/// The returned `output-stream` is a child resource: it must be dropped
/// before the parent `outgoing-body` resource is dropped (or finished),
/// otherwise the `outgoing-body` drop or `finish` will trap.
///
/// Returns success on the first call: the `output-stream` resource for
/// this `outgoing-body` may be retrieved at most once. Subsequent calls
/// will return error.
@since(version = 0.2.0)
write: func() -> result<output-stream>;
/// Finalize an outgoing body, optionally providing trailers. This must be
/// called to signal that the response is complete. If the `outgoing-body`
/// is dropped without calling `outgoing-body.finalize`, the implementation
/// should treat the body as corrupted.
///
/// Fails if the body's `outgoing-request` or `outgoing-response` was
/// constructed with a Content-Length header, and the contents written
/// to the body (via `write`) does not match the value given in the
/// Content-Length.
@since(version = 0.2.0)
finish: static func(this: outgoing-body, trailers: option<trailers>) -> result<_, error-code>;
}
/// Represents a future which may eventually return an incoming HTTP
/// Response, or an error.
///
/// This resource is returned by the `wasi:http/outgoing-handler` interface to
/// provide the HTTP Response corresponding to the sent Request.
@since(version = 0.2.0)
resource future-incoming-response {
/// Returns a pollable which becomes ready when either the Response has
/// been received, or an error has occurred. When this pollable is ready,
/// the `get` method will return `some`.
@since(version = 0.2.0)
subscribe: func() -> pollable;
/// Returns the incoming HTTP Response, or an error, once one is ready.
///
/// The outer `option` represents future readiness. Users can wait on this
/// `option` to become `some` using the `subscribe` method.
///
/// The outer `result` is used to retrieve the response or error at most
/// once. It will be success on the first call in which the outer option
/// is `some`, and error on subsequent calls.
///
/// The inner `result` represents that either the incoming HTTP Response
/// status and headers have received successfully, or that an error
/// occurred. Errors may also occur while consuming the response body,
/// but those will be reported by the `incoming-body` and its
/// `output-stream` child.
@since(version = 0.2.0)
get: func() -> option<result<result<incoming-response, error-code>>>;
}
/// Attempts to extract a http-related `error` from the wasi:io `error`
/// provided.
///
/// Stream operations which return
/// `wasi:io/stream/stream-error::last-operation-failed` have a payload of
/// type `wasi:io/error/error` with more information about the operation
/// that failed. This payload can be passed through to this function to see
/// if there's http-related information about the error to return.
///
/// Note that this function is fallible because not all io-errors are
/// http-related errors.
@since(version = 0.2.0)
http-error-code: func(err: borrow<io-error>) -> option<error-code>;
}