11use wasi:: http:: types:: { IncomingBody as WasiIncomingBody , IncomingResponse } ;
22use wasi:: io:: streams:: { InputStream , StreamError } ;
33
4- use super :: { fields:: header_map_from_wasi, Body , HeaderMap , StatusCode } ;
4+ use super :: { fields:: header_map_from_wasi, Body , Error , HeaderMap , Result , StatusCode } ;
55use crate :: io:: AsyncRead ;
66use crate :: runtime:: Reactor ;
77
@@ -16,39 +16,36 @@ pub struct Response<B: Body> {
1616 body : B ,
1717}
1818
19- // #[derive(Debug)]
20- // enum BodyKind {
21- // Fixed(u64),
22- // Chunked,
23- // }
24-
25- // impl BodyKind {
26- // fn from_headers(headers: &Fields) -> BodyKind {
27- // dbg!(&headers);
28- // if let Some(values) = headers.0.get("content-length") {
29- // let value = values
30- // .get(0)
31- // .expect("no value found for content-length; violates HTTP/1.1");
32- // let content_length = String::from_utf8(value.to_owned())
33- // .unwrap()
34- // .parse::<u64>()
35- // .expect("content-length should be a u64; violates HTTP/1.1");
36- // BodyKind::Fixed(content_length)
37- // } else if let Some(values) = headers.0.get("transfer-encoding") {
38- // dbg!(values);
39- // BodyKind::Chunked
40- // } else {
41- // dbg!("Encoding neither has a content-length nor transfer-encoding");
42- // BodyKind::Chunked
43- // }
44- // }
45- // }
19+ #[ derive( Debug ) ]
20+ enum BodyKind {
21+ Fixed ( u64 ) ,
22+ Chunked ,
23+ }
24+
25+ impl BodyKind {
26+ fn from_headers ( headers : & HeaderMap ) -> Result < BodyKind > {
27+ if let Some ( value) = headers. get ( "content-length" ) {
28+ let content_length = std:: str:: from_utf8 ( value. as_ref ( ) )
29+ . unwrap ( )
30+ . parse :: < u64 > ( )
31+ . map_err ( |_| {
32+ Error :: other ( "incoming content-length should be a u64; violates HTTP/1.1" )
33+ } ) ?;
34+ Ok ( BodyKind :: Fixed ( content_length) )
35+ } else if headers. contains_key ( "transfer-encoding" ) {
36+ Ok ( BodyKind :: Chunked )
37+ } else {
38+ Ok ( BodyKind :: Chunked )
39+ }
40+ }
41+ }
4642
4743impl Response < IncomingBody > {
48- pub ( crate ) fn try_from_incoming_response ( incoming : IncomingResponse ) -> super :: Result < Self > {
44+ pub ( crate ) fn try_from_incoming_response ( incoming : IncomingResponse ) -> Result < Self > {
4945 let headers: HeaderMap = header_map_from_wasi ( incoming. headers ( ) ) ?;
5046 let status = incoming. status ( ) . into ( ) ;
5147
48+ let kind = BodyKind :: from_headers ( & headers) ?;
5249 // `body_stream` is a child of `incoming_body` which means we cannot
5350 // drop the parent before we drop the child
5451 let incoming_body = incoming
@@ -59,6 +56,7 @@ impl Response<IncomingBody> {
5956 . expect ( "cannot call `stream` twice on an incoming body" ) ;
6057
6158 let body = IncomingBody {
59+ kind,
6260 buf_offset : 0 ,
6361 buf : None ,
6462 body_stream,
@@ -97,6 +95,7 @@ impl<B: Body> Response<B> {
9795/// An incoming HTTP body
9896#[ derive( Debug ) ]
9997pub struct IncomingBody {
98+ kind : BodyKind ,
10099 buf : Option < Vec < u8 > > ,
101100 // How many bytes have we already read from the buf?
102101 buf_offset : usize ,
@@ -147,3 +146,18 @@ impl AsyncRead for IncomingBody {
147146 Ok ( len)
148147 }
149148}
149+
150+ impl Body for IncomingBody {
151+ fn len ( & self ) -> Option < usize > {
152+ match self . kind {
153+ BodyKind :: Fixed ( l) => {
154+ if l > ( usize:: MAX as u64 ) {
155+ None
156+ } else {
157+ Some ( l as usize )
158+ }
159+ }
160+ BodyKind :: Chunked => None ,
161+ }
162+ }
163+ }
0 commit comments