wasi_hyperium/hyperium1/
outgoing.rs1use std::{
2 pin::Pin,
3 task::{Context, Poll},
4};
5
6use bytes::Buf;
7
8use crate::{
9 outgoing::{Copied, OutgoingBodyCopier},
10 poll::PollableRegistry,
11 wasi::{OutgoingBody, OutgoingRequest, OutgoingResponse},
12 Error,
13};
14
15pub fn outgoing_request<B, Registry>(
16 request: &http1::Request<B>,
17 registry: Registry,
18) -> Result<OutgoingRequest<Registry>, Error>
19where
20 Registry: PollableRegistry,
21{
22 let mut req = OutgoingRequest::from_headers(&request.headers().into(), registry)?;
23 req.set_method(request.method().into())?;
24 if let Some(path_with_query) = request.uri().path_and_query() {
25 req.set_path_with_query(Some(path_with_query.as_str()))?;
26 }
27 if let Some(scheme) = request.uri().scheme() {
28 req.set_scheme(Some(scheme.into()))?;
29 }
30 if let Some(authority) = request.uri().authority() {
31 req.set_authority(Some(authority.as_str()))?;
32 }
33
34 Ok(req)
35}
36
37pub fn outgoing_response<B, Registry>(
38 resp: &http1::Response<B>,
39 registry: Registry,
40) -> Result<OutgoingResponse<Registry>, Error>
41where
42 Registry: PollableRegistry,
43{
44 let mut outgoing = OutgoingResponse::from_headers(&resp.headers().into(), registry)?;
45 outgoing.set_status_code(resp.status().as_u16())?;
46 Ok(outgoing)
47}
48
49pub struct Hyperium1OutgoingBodyCopier<HttpBody, Registry>
50where
51 HttpBody: http_body1::Body,
52 Registry: PollableRegistry,
53{
54 src: HttpBody,
55 dest: Option<OutgoingBody<Registry>>,
56 buf: Option<HttpBody::Data>,
57}
58
59impl<HttpBody, Registry> Hyperium1OutgoingBodyCopier<HttpBody, Registry>
60where
61 HttpBody: http_body1::Body,
62 Registry: PollableRegistry,
63{
64 pub fn new(src: HttpBody, dest: OutgoingBody<Registry>) -> Result<Self, Error> {
65 Ok(Self {
66 src,
67 dest: Some(dest),
68 buf: None,
69 })
70 }
71}
72
73impl<HttpBody, Registry> OutgoingBodyCopier for Hyperium1OutgoingBodyCopier<HttpBody, Registry>
74where
75 HttpBody: http_body1::Body + Unpin,
76 anyhow::Error: From<HttpBody::Error>,
77 Registry: PollableRegistry,
78{
79 fn poll_copy(&mut self, cx: &mut Context) -> Poll<Option<Result<Copied, Error>>> {
80 if self.dest.is_none() {
81 return Poll::Ready(None);
82 }
83
84 if self.buf.is_none() {
85 match Pin::new(&mut self.src)
87 .poll_frame(cx)
88 .map_err(|err| Error::BodyError(err.into()))?
89 {
90 Poll::Ready(Some(frame)) => {
91 if frame.is_data() {
92 self.buf =
93 Some(frame.into_data().unwrap_or_else(|_| {
94 panic!("into_data failed when is_data = true")
95 }));
96 } else {
97 let trailers = frame.into_trailers().unwrap_or_else(|_| {
99 panic!("into_trailers failed when is_data = false")
100 });
101 self.dest.take().unwrap().finish(Some(trailers.into()))?;
102 return Poll::Ready(Some(Ok(Copied::Trailers)));
103 }
104 }
105 Poll::Ready(None) => {
106 self.dest.take().unwrap().finish(None)?;
108 return Poll::Ready(None);
109 }
110 Poll::Pending => return Poll::Pending,
111 }
112 }
113
114 let stream = self.dest.as_mut().unwrap().stream();
116 match stream.poll_check_write(cx)? {
117 Poll::Ready(permit) => {
118 let buf = self.buf.as_mut().unwrap();
119 let len = permit.write(buf.chunk())?;
120 buf.advance(len);
121 if !buf.has_remaining() {
122 self.buf = None;
123 }
124 Poll::Ready(Some(Ok(Copied::Body(len))))
125 }
126 Poll::Pending => Poll::Pending,
127 }
128 }
129}