-
Couldn't load subscription status.
- Fork 1.5k
feat(p3): implement wasi:http
#11440
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(p3): implement wasi:http
#11440
Conversation
480558d to
4819aad
Compare
| fn get_fields<'a>( | ||
| table: &'a ResourceTable, | ||
| fields: &Resource<Fields>, | ||
| ) -> wasmtime::Result<&'a Fields> { | ||
| table | ||
| .get(&fields) | ||
| .context("failed to get fields from table") | ||
| } | ||
|
|
||
| fn get_fields_mut<'a>( | ||
| table: &'a mut ResourceTable, | ||
| fields: &Resource<Fields>, | ||
| ) -> wasmtime::Result<&'a mut Fields> { | ||
| table | ||
| .get_mut(&fields) | ||
| .context("failed to get fields from table") | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One suggestion perhaps for many of these methods is to have a generic extension trait which supports an arbitrary T for Resource<T> which could help deduplicate these methods?
a68602e to
07e7597
Compare
41d8d1a to
19f51fc
Compare
19f51fc to
1916d2a
Compare
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
1916d2a to
3f80110
Compare
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
3f80110 to
d26886d
Compare
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
d26886d to
d7b5ed6
Compare
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
|
I'm done for the week and will continue on Monday, but this is pretty close to having all test cases passing. @alexcrichton @dicej feel free to make the necessary changes in the PR to make the rest of the test cases work and get this over the line if there's a desire to still finish If we're okay with waiting until next week, this should be complete by Monday evening |
Try to keep fields private and use public ctors instead.
It's still semi-failing, but defer that to bytecodealliance#11631
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok I've gone over this and it looks good to me, thanks again @rvolosatovs!
I've left a bunch of comments below which I'd like to resolve at some point, but doesn't need to block. I'm going to flag this for merge and I'll file follow-ups.
| pub fn into_http<T: WasiHttpView + 'static>( | ||
| self, | ||
| store: impl AsContextMut<Data = T>, | ||
| fut: impl Future<Output = Result<(), ErrorCode>> + Send + 'static, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you comment this function to the purpose of fut?
| body: impl Into<BoxBody<Bytes, ErrorCode>>, | ||
| ) -> ( | ||
| Self, | ||
| impl Future<Output = Result<(), ErrorCode>> + Send + 'static, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you comment function as to what this future is?
| req: http::Request<T>, | ||
| ) -> ( | ||
| Self, | ||
| impl Future<Output = Result<(), ErrorCode>> + Send + 'static, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like response below, could you comment this returned future here and with new?
| } | ||
| } | ||
|
|
||
| pub(crate) struct IncomingResponseBody { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mind adding a small doc block here explaining what this is doing? The code is pretty self-explanatory but I still think it'd be good to have an intro
| fn poll_frame( | ||
| mut self: Pin<&mut Self>, | ||
| cx: &mut Context<'_>, | ||
| ) -> Poll<Option<Result<http_body::Frame<Self::Data>, Self::Error>>> { | ||
| if let Some(contents_rx) = self.contents_rx.as_mut() { | ||
| while let Some(buf) = ready!(contents_rx.poll_recv(cx)) { | ||
| return Poll::Ready(Some(Ok(http_body::Frame::data(buf)))); | ||
| } | ||
| self.contents_rx = None; | ||
| } | ||
|
|
||
| let Some(trailers_rx) = self.trailers_rx.as_mut() else { | ||
| return Poll::Ready(None); | ||
| }; | ||
|
|
||
| let res = ready!(Pin::new(trailers_rx).poll(cx)); | ||
| self.trailers_rx = None; | ||
| match res { | ||
| Ok(Ok(Some(trailers))) => Poll::Ready(Some(Ok(http_body::Frame::trailers( | ||
| Arc::unwrap_or_clone(trailers), | ||
| )))), | ||
| Ok(Ok(None)) => Poll::Ready(None), | ||
| Ok(Err(err)) => Poll::Ready(Some(Err(err))), | ||
| Err(..) => Poll::Ready(None), | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mind leaving some comments here (and in is_end_stream) about the state machine being managed here? Doesn't need to be too wordy but having headings to grasp on I think would be helpful
| fn poll_produce<'a>( | ||
| mut self: Pin<&mut Self>, | ||
| cx: &mut Context<'_>, | ||
| mut store: StoreContextMut<'a, D>, | ||
| mut dst: Destination<'a, Self::Item, Self::Buffer>, | ||
| finish: bool, | ||
| ) -> Poll<wasmtime::Result<StreamResult>> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mind leaving some small comments in this function body to help navigate what the state machine is doing? (e.g. a ocmment explaining the signficance of each arm here and there)
crates/test-programs/src/bin/p3_http_outbound_request_content_length.rs
Outdated
Show resolved
Hide resolved
5674e4b
* feat(p3-http): begin implementation Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> * feat(p3-http): implement incoming HTTP Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> * feat(p3-http): switch to new API Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> * feat(p3-http): begin outgoing implementation Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> * test(p3-http): test invalid header Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> * fix(p3-http): await I/O if future receiver dropped Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> * Re-internalize some fields Try to keep fields private and use public ctors instead. * Uncomment `p3_http_outbound_request_content_length` test It's still semi-failing, but defer that to bytecodealliance#11631 * Get tests passing CI again --------- Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> Co-authored-by: Alex Crichton <alex@alexcrichton.com>
* wasip3: Update std{out,err} implementation (#11618)
* wasip3: Update std{out,err} implementation
Match the WASIp2 stdio implementation and "lie" about stdio actually
being async. Instead of using Tokio's primitives use the `std::io`
primitives which will block the current program while the output is
produced. This matches WASIp2 semantics and we always have the option of
making this more async in the future (or even have it as a runtime
flag). This avoids the need to call `poll_flush` in stdio
unconditionally in the `wasi:cli` implementation which didn't feel quite
right.
* One fewer run for Windows
It's got a shorter command line length limit
* wasip3: Refactor file in/out streams (#11619)
* Deduplicate write/append streams
* Deduplicate poll-the-task and spawn-the-task-then-poll
* Explicitly ignore the `finish` flag
* Support store-access in `bindgen!` generated imports (#11628)
* Support store-access in `bindgen!` generated imports
This commit adds support to accessing the store in `bindgen!`-generated
import functions in traits. Since the inception of `bindgen!` this has
never been possible and access to the store requires manually working
with `Linker`, for example. This is not easy to do because it requires
surgically editing code or working around what bindings generation parts
you do want.
The implementation here is a small step away from what
component-model-async has already implemented for async functions.
Effectively it's a small extension of the `*WithStore` traits to also
have synchronous functions with `Access` parameters instead of `async`
functions with an `Accessor` parameter.
This is something we're going to want for the WASIp3 implementation
where I've noticed some resource destructors are going to want access to
the store to close out streams and such and this'll provide the bindings
necessary for that.
Closes #11590
* Update test expectations
* feat(p3): implement `wasi:http` (#11440)
* feat(p3-http): begin implementation
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
* feat(p3-http): implement incoming HTTP
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
* feat(p3-http): switch to new API
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
* feat(p3-http): begin outgoing implementation
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
* test(p3-http): test invalid header
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
* fix(p3-http): await I/O if future receiver dropped
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
* Re-internalize some fields
Try to keep fields private and use public ctors instead.
* Uncomment `p3_http_outbound_request_content_length` test
It's still semi-failing, but defer that to #11631
* Get tests passing CI again
---------
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
Co-authored-by: Alex Crichton <alex@alexcrichton.com>
* Tune new "much stdout" test for runtime (#11635)
On Pulley platforms this test is taking 40+ minutes in CI. Locally it
took 2 minutes to complete. After this change it should still roughly
test the same thing but takes less than 100ms to complete locally.
---------
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
Co-authored-by: Roman Volosatovs <rvolosatovs@users.noreply.github.com>
* feat(p3-http): begin implementation Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> * feat(p3-http): implement incoming HTTP Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> * feat(p3-http): switch to new API Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> * feat(p3-http): begin outgoing implementation Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> * test(p3-http): test invalid header Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> * fix(p3-http): await I/O if future receiver dropped Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> * Re-internalize some fields Try to keep fields private and use public ctors instead. * Uncomment `p3_http_outbound_request_content_length` test It's still semi-failing, but defer that to bytecodealliance#11631 * Get tests passing CI again --------- Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net> Co-authored-by: Alex Crichton <alex@alexcrichton.com>
This PR builds on top of #11221 and will contain the full implementation of
wasi:httpproposal with refcounting (no child resources). This will be made ready-for-review once all currently ignored tests pass4819aad is currently the only commit here worth looking at