Skip to content

Commit d163277

Browse files
authored
[v0.3] model bodies after stream<u8, trailers, error-code>, trap less (#162)
* feat(p3): be less trappy Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> * chore(p3): orphan `headers` returned by `headers()` Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> * doc(p3): improve wording Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> * feat(p3): avoid auto-close semantics Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> * p3: allow multiple active body refs to exist, drop `into-parts` Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> * p3: add `request-options#clone` Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> * p3: model `body` after `stream<u8, trailers, error-code>` Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> * p3: remove `body` resource Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> * p3: use `result`, not `option` in `body()` Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> * p3: make request/response bodies optional Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> * p3: document optional content stream optimization Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> --------- Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
1 parent 042bdf2 commit d163277

File tree

1 file changed

+75
-93
lines changed

1 file changed

+75
-93
lines changed

wit-0.3.0-draft/types.wit

Lines changed: 75 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -230,77 +230,36 @@ interface types {
230230
/// Trailers is an alias for Fields.
231231
type trailers = fields;
232232

233-
/// Represents an HTTP Request or Response's Body.
234-
///
235-
/// A body has both its contents - a stream of bytes - and a (possibly empty)
236-
/// set of trailers, indicating that the full contents of the body have been
237-
/// received. This resource represents the contents as a `stream<u8>` and the
238-
/// delivery of trailers as a `trailers`, and ensures that the user of this
239-
/// interface may only be consuming either the body contents or waiting on
240-
/// trailers at any given time.
241-
resource body {
242-
243-
/// Construct a new `body` with the specified stream.
244-
///
245-
/// This function returns a future, which will resolve
246-
/// to an error code if transmitting stream data fails.
247-
///
248-
/// The returned future resolves to success once body stream
249-
/// is fully transmitted.
250-
new: static func(
251-
%stream: stream<u8>,
252-
) -> tuple<body, future<result<_, error-code>>>;
253-
254-
/// Construct a new `body` with the specified stream and trailers.
255-
///
256-
/// This function returns a future, which will resolve
257-
/// to an error code if transmitting stream data or trailers fails.
258-
///
259-
/// The returned future resolves to success once body stream and trailers
260-
/// are fully transmitted.
261-
new-with-trailers: static func(
262-
%stream: stream<u8>,
263-
trailers: future<trailers>
264-
) -> tuple<body, future<result<_, error-code>>>;
265-
266-
/// Returns the contents of the body, as a stream of bytes.
267-
///
268-
/// This function may be called multiple times as long as any `stream`s
269-
/// returned by previous calls have been dropped first.
270-
///
271-
/// On success, this function returns a stream and a future, which will resolve
272-
/// to an error code if receiving data from stream fails.
273-
/// The returned future resolves to success if body is closed.
274-
%stream: func() -> result<tuple<stream<u8>, future<result<_, error-code>>>>;
275-
276-
/// Takes ownership of `body`, and returns an unresolved optional `trailers` result.
277-
///
278-
/// This function will trap if a `stream` child is still alive.
279-
finish: static func(this: body) -> future<result<option<trailers>, error-code>>;
280-
}
281-
282233
/// Represents an HTTP Request.
283234
resource request {
284235

285236
/// Construct a new `request` with a default `method` of `GET`, and
286237
/// `none` values for `path-with-query`, `scheme`, and `authority`.
287238
///
288-
/// * `headers` is the HTTP Headers for the Response.
289-
/// * `body` is the optional contents of the body, possibly including
290-
/// trailers.
291-
/// * `options` is optional `request-options` to be used if the request is
292-
/// sent over a network connection.
239+
/// `headers` is the HTTP Headers for the Request.
240+
///
241+
/// `contents` is the optional body content stream with `none`
242+
/// representing a zero-length content stream.
243+
/// Once it is closed, `trailers` future must resolve to a result.
244+
/// If `trailers` resolves to an error, underlying connection
245+
/// will be closed immediately.
246+
///
247+
/// `options` is optional `request-options` resource to be used
248+
/// if the request is sent over a network connection.
293249
///
294250
/// It is possible to construct, or manipulate with the accessor functions
295-
/// below, an `request` with an invalid combination of `scheme`
251+
/// below, a `request` with an invalid combination of `scheme`
296252
/// and `authority`, or `headers` which are not permitted to be sent.
297253
/// It is the obligation of the `handler.handle` implementation
298254
/// to reject invalid constructions of `request`.
299-
constructor(
255+
///
256+
/// The returned future resolves to result of transmission of this request.
257+
new: static func(
300258
headers: headers,
301-
body: option<body>,
259+
contents: option<stream<u8>>,
260+
trailers: future<result<option<trailers>, error-code>>,
302261
options: option<request-options>
303-
);
262+
) -> tuple<request, future<result<_, error-code>>>;
304263

305264
/// Get the Method for the Request.
306265
method: func() -> method;
@@ -348,22 +307,28 @@ interface types {
348307
///
349308
/// The returned `headers` resource is immutable: `set`, `append`, and
350309
/// `delete` operations will fail with `header-error.immutable`.
351-
///
352-
/// This headers resource is a child: it must be dropped before the parent
353-
/// `request` is dropped, or its ownership is transferred to another
354-
/// component by e.g. `handler.handle`.
355310
headers: func() -> headers;
356311

357-
/// Get the body associated with the Request, if any.
312+
/// Get body of the Request.
358313
///
359-
/// This body resource is a child: it must be dropped before the parent
360-
/// `request` is dropped, or its ownership is transferred to another
361-
/// component by e.g. `handler.handle`.
362-
body: func() -> option<body>;
363-
364-
/// Takes ownership of the `request` and returns the `headers`, `body`
365-
/// and `request-options`, if any.
366-
into-parts: static func(this: request) -> tuple<headers, option<body>, option<request-options>>;
314+
/// Stream returned by this method represents the contents of the body.
315+
/// Once the stream is reported as closed, callers should await the returned future
316+
/// to determine whether the body was received successfully.
317+
/// The future will only resolve after the stream is reported as closed.
318+
///
319+
/// The stream and future returned by this method are children:
320+
/// they should be closed or consumed before the parent `response`
321+
/// is dropped, or its ownership is transferred to another component
322+
/// by e.g. `handler.handle`.
323+
///
324+
/// This method may be called multiple times.
325+
///
326+
/// This method will return an error if it is called while either:
327+
/// - a stream or future returned by a previous call to this method is still open
328+
/// - a stream returned by a previous call to this method has reported itself as closed
329+
/// Thus there will always be at most one readable stream open for a given body.
330+
/// Each subsequent stream picks up where the last stream left off, up until it is finished.
331+
body: func() -> result<tuple<stream<u8>, future<result<option<trailers>, error-code>>>>;
367332
}
368333

369334
/// Parameters for making an HTTP Request. Each of these parameters is
@@ -400,6 +365,10 @@ interface types {
400365
/// body stream. An error return value indicates that this timeout is not
401366
/// supported or that this handle is immutable.
402367
set-between-bytes-timeout: func(duration: option<duration>) -> result<_, request-options-error>;
368+
369+
/// Make a deep copy of the `request-options`.
370+
/// The resulting `request-options` is mutable.
371+
clone: func() -> request-options;
403372
}
404373

405374
/// This type corresponds to the HTTP standard Status Code.
@@ -408,17 +377,24 @@ interface types {
408377
/// Represents an HTTP Response.
409378
resource response {
410379

411-
/// Construct an `response`, with a default `status-code` of `200`. If a
412-
/// different `status-code` is needed, it must be set via the
380+
/// Construct a new `response`, with a default `status-code` of `200`.
381+
/// If a different `status-code` is needed, it must be set via the
413382
/// `set-status-code` method.
414383
///
415-
/// * `headers` is the HTTP Headers for the Response.
416-
/// * `body` is the optional contents of the body, possibly including
417-
/// trailers.
418-
constructor(
384+
/// `headers` is the HTTP Headers for the Response.
385+
///
386+
/// `contents` is the optional body content stream with `none`
387+
/// representing a zero-length content stream.
388+
/// Once it is closed, `trailers` future must resolve to a result.
389+
/// If `trailers` resolves to an error, underlying connection
390+
/// will be closed immediately.
391+
///
392+
/// The returned future resolves to result of transmission of this response.
393+
new: static func(
419394
headers: headers,
420-
body: option<body>,
421-
);
395+
contents: option<stream<u8>>,
396+
trailers: future<result<option<trailers>, error-code>>,
397+
) -> tuple<response, future<result<_, error-code>>>;
422398

423399
/// Get the HTTP Status Code for the Response.
424400
status-code: func() -> status-code;
@@ -427,25 +403,31 @@ interface types {
427403
/// given is not a valid http status code.
428404
set-status-code: func(status-code: status-code) -> result;
429405

430-
/// Get the headers associated with the Request.
406+
/// Get the headers associated with the Response.
431407
///
432408
/// The returned `headers` resource is immutable: `set`, `append`, and
433409
/// `delete` operations will fail with `header-error.immutable`.
434-
///
435-
/// This headers resource is a child: it must be dropped before the parent
436-
/// `response` is dropped, or its ownership is transferred to another
437-
/// component by e.g. `handler.handle`.
438410
headers: func() -> headers;
439411

440-
/// Get the body associated with the Response, if any.
412+
/// Get body of the Response.
441413
///
442-
/// This body resource is a child: it must be dropped before the parent
443-
/// `response` is dropped, or its ownership is transferred to another
444-
/// component by e.g. `handler.handle`.
445-
body: func() -> option<body>;
446-
447-
/// Takes ownership of the `response` and returns the `headers` and `body`,
448-
/// if any.
449-
into-parts: static func(this: response) -> tuple<headers, option<body>>;
414+
/// Stream returned by this method represents the contents of the body.
415+
/// Once the stream is reported as closed, callers should await the returned future
416+
/// to determine whether the body was received successfully.
417+
/// The future will only resolve after the stream is reported as closed.
418+
///
419+
/// The stream and future returned by this method are children:
420+
/// they should be closed or consumed before the parent `response`
421+
/// is dropped, or its ownership is transferred to another component
422+
/// by e.g. `handler.handle`.
423+
///
424+
/// This method may be called multiple times.
425+
///
426+
/// This method will return an error if it is called while either:
427+
/// - a stream or future returned by a previous call to this method is still open
428+
/// - a stream returned by a previous call to this method has reported itself as closed
429+
/// Thus there will always be at most one readable stream open for a given body.
430+
/// Each subsequent stream picks up where the last stream left off, up until it is finished.
431+
body: func() -> result<tuple<stream<u8>, future<result<option<trailers>, error-code>>>>;
450432
}
451433
}

0 commit comments

Comments
 (0)