Skip to content
This repository was archived by the owner on Nov 25, 2025. It is now read-only.

fix(p3): remove body accessors#161

Closed
rvolosatovs wants to merge 1 commit intoWebAssembly:mainfrom
rvolosatovs:fix/p3-remove-body-accessors
Closed

fix(p3): remove body accessors#161
rvolosatovs wants to merge 1 commit intoWebAssembly:mainfrom
rvolosatovs:fix/p3-remove-body-accessors

Conversation

@rvolosatovs
Copy link
Contributor

@rvolosatovs rvolosatovs commented Mar 12, 2025

Currently, there are two ways to acquire a handle to the incoming request/response body handle:

  1. Call body method on the request/response
  2. Call into-parts static function on the request/response

Assume pseudocode:

body := response.body()
stream := body.stream()
stream.read(buf)
drop(stream)
drop(body) // Forgetting this would cause a trap
(_, body) := Response::into_parts(response)

There a few issues in the example above.

  1. It's very easy to make a mistake and cause a runtime trap, developers must very closely follow the WIT definition and read documentation to avoid a crash at runtime.
  2. The host must do a lot of work and state tracking to e.g. ensure underlying body stream state synchronisation. If body method can be called at most once, that simplifes the task and potentially, the host could move the ownership of the body into the returned resource and move it back on drop of the body resource. Regardless of the approach and semantics, introducing multiple accessors for the body requires increased complexity in the host.

To fix this, simply remove the body accessors. This way only a single way to acquire a body resource exists, which eliminates the possibility of misusing the interface by the application developer and simplifies implementation in the host.

This is an alternative solution to #159, will mark that PR as draft.
Closes #159

Currently, there are two ways to acquire a handle to the incoming
request/response body handle:
1. Call `body` method on the request/response
2. Call `into-parts` static function on the request/response

Assume pseudocode:
```
body := response.body()
stream := body.stream()
stream.read(buf)
drop(stream)
drop(body) // Forgetting this would cause a trap
(_, body) := Response::into_parts(response)
```

There are quite a few issues in the example above.

1. It's very easy to make a mistake and cause a runtime trap,
   developers must very closely follow the WIT definition and
   read documentation to avoid a crash at runtime.
2. The host must do a lot of work and state tracking to e.g. ensure
   underlying body stream state synchronisation. If `body` method can
   be called at most once, that simplifes the task and potentially,
   the host could *move* the ownership of the body into the returned
   resource and *move* it back on `drop` of the body resource.
   Regardless of the approach and semantics, introducing multiple
   accessors for the `body` requires increased complexity in the host.

To fix this, simply remove the `body` accessors. This way only a single
way to acquire a body resource exists, which eliminates the possibility
of misusing the interface by the application developer and simplifies
implementation in the host.

Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
@lukewagner
Copy link
Member

Depending on the resolution to #156, that might justify the continued existence of the body accessor.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants