pub(crate) async fn decode<IO>(mut io: IO) -> http_types::Result<Option<Request>>
where
    IO: Read + Write + Clone + Send + Sync + Unpin + 'static,
{
    let mut reader = BufReader::new(io.clone());
    let mut buf = Vec::new();
    let mut headers = [httparse::EMPTY_HEADER; MAX_HEADERS];
    let mut httparse_req = httparse::Request::new(&mut headers);

    // Keep reading bytes from the stream until we hit the end of the stream.
    loop {
        let bytes_read = reader.read_until(LF, &mut buf).await?;
        // No more bytes are yielded from the stream.
        if bytes_read == 0 {
            return Ok(None);
        }

        // Prevent CWE-400 DDOS with large HTTP Headers.
        ensure!(
            buf.len() < MAX_HEAD_LENGTH,
            "Head byte length should be less than 8kb"
        );

        // We've hit the end delimiter of the stream.
        let idx = buf.len() - 1;
        if idx >= 3 && &buf[idx - 3..=idx] == b"\r\n\r\n" {
            break;
        }
    }

    // Convert our header buf into an httparse instance, and validate.
    let status = httparse_req.parse(&buf)?;

    ensure!(!status.is_partial(), "Malformed HTTP head");

    // Convert httparse headers + body into a `http_types::Request` type.
    let method = httparse_req.method;
    let method = method.ok_or_else(|| format_err!("No method found"))?;

    let path = httparse_req.path;
    let path = path.ok_or_else(|| format_err!("No uri found"))?;

    let version = httparse_req.version;
    let version = version.ok_or_else(|| format_err!("No version found"))?;

    ensure_eq!(
        version,
        HTTP_1_1_VERSION,
        "Unsupported HTTP version 1.{}",
        version
    );

    let mut req = Request::new(
        Method::from_str(method)?,
        url::Url::parse("http://_").unwrap().join(path)?,
    );

    for header in httparse_req.headers.iter() {
        req.insert_header(header.name, std::str::from_utf8(header.value)?);
    }

    set_url_and_port_from_host_header(&mut req)?;
    handle_100_continue(&req, &mut io).await?;

    let content_length = req.header(CONTENT_LENGTH);
    let transfer_encoding = req.header(TRANSFER_ENCODING);

    http_types::ensure!(
        content_length.is_none() || transfer_encoding.is_none(),
        "Unexpected Content-Length header"
    );

    // Check for Transfer-Encoding
    if let Some(encoding) = transfer_encoding {
        if encoding.last().as_str() == "chunked" {
            let trailer_sender = req.send_trailers();
            let reader = BufReader::new(ChunkedDecoder::new(reader, trailer_sender));
            req.set_body(Body::from_reader(reader, None));
            return Ok(Some(req));
        }
        // Fall through to Content-Length
    }

    // Check for Content-Length.
    if let Some(len) = content_length {
        let len = len.last().as_str().parse::<usize>()?;
        req.set_body(Body::from_reader(reader.take(len as u64), Some(len)));
    }

    Ok(Some(req))
}
/// Decode an HTTP request on the server.
Decode an HTTP request on the server.
Decode an HTTP request on the server .
pub(crate) async fn decode<IO>(mut io: IO) -> http_types::Result<Option<Request>>
where
    IO: Read + Write + Clone + Send + Sync + Unpin + 'static,
{
    let mut reader = BufReader::new(io.clone());
    let mut buf = Vec::new();
    let mut headers = [httparse::EMPTY_HEADER; MAX_HEADERS];
    let mut httparse_req = httparse::Request::new(&mut headers);
    // Keep reading bytes from the stream until we hit the end of the stream.
    loop {
        let bytes_read = reader.read_until(LF, &mut buf).await?;
        // No more bytes are yielded from the stream.
        if bytes_read == 0 {
            return Ok(None);
        }
        // Prevent CWE-400 DDOS with large HTTP Headers.
        ensure!(
            buf.len() < MAX_HEAD_LENGTH,
            "Head byte length should be less than 8kb"
        );
        // We've hit the end delimiter of the stream.
        let idx = buf.len() - 1;
        if idx >= 3 && &buf[idx - 3..=idx] == b"\r\n\r\n" {
            break;
        }
    }
    // Convert our header buf into an httparse instance, and validate.
    let status = httparse_req.parse(&buf)?;
    ensure!(!status.is_partial(), "Malformed HTTP head");
    // Convert httparse headers + body into a `http_types::Request` type.
    let method = httparse_req.method;
    let method = method.ok_or_else(|| format_err!("No method found"))?;
    let path = httparse_req.path;
    let path = path.ok_or_else(|| format_err!("No uri found"))?;
    let version = httparse_req.version;
    let version = version.ok_or_else(|| format_err!("No version found"))?;
    ensure_eq!(
        version,
        HTTP_1_1_VERSION,
        "Unsupported HTTP version 1.{}",
        version
    );
    let mut req = Request::new(
        Method::from_str(method)?,
        url::Url::parse("http://_").unwrap().join(path)?,
    );
    for header in httparse_req.headers.iter() {
        req.insert_header(header.name, std::str::from_utf8(header.value)?);
    }
    set_url_and_port_from_host_header(&mut req)?;
    handle_100_continue(&req, &mut io).await?;
    let content_length = req.header(CONTENT_LENGTH);
    let transfer_encoding = req.header(TRANSFER_ENCODING);
    http_types::ensure!(
        content_length.is_none() || transfer_encoding.is_none(),
        "Unexpected Content-Length header"
    );
    // Check for Transfer-Encoding
    if let Some(encoding) = transfer_encoding {
        if encoding.last().as_str() == "chunked" {
            let trailer_sender = req.send_trailers();
            let reader = BufReader::new(ChunkedDecoder::new(reader, trailer_sender));
            req.set_body(Body::from_reader(reader, None));
            return Ok(Some(req));
        }
        // Fall through to Content-Length
    }
    // Check for Content-Length.
    if let Some(len) = content_length {
        let len = len.last().as_str().parse::<usize>()?;
        req.set_body(Body::from_reader(reader.take(len as u64), Some(len)));
    }
    Ok(Some(req))
}
pub ( crate ) async fn decode < IO > ( mut io : IO ) -> http_types :: Result < Option < Request > > where IO : Read + Write + Clone + Send + Sync + Unpin + ' static , { let mut reader = BufReader :: new ( io . clone ( ) ) ; let mut buf = Vec :: new ( ) ; let mut headers = [ httparse :: EMPTY_HEADER ; MAX_HEADERS ] ; let mut httparse_req = httparse :: Request :: new ( & mut headers ) ; // Keep reading bytes from the stream until we hit the end of the stream. loop { let bytes_read = reader . read_until ( LF , & mut buf ) . await ? ; // No more bytes are yielded from the stream. if bytes_read == 0 { return Ok ( None ) ; } // Prevent CWE-400 DDOS with large HTTP Headers. ensure ! ( buf len ( ) MAX_HEAD_LENGTH " " ) ; // We've hit the end delimiter of the stream. let idx = buf . len ( ) - 1 ; if idx >= 3 && & buf [ idx - 3 ..= idx ] == b" \r \n \r \n " { break ; } } // Convert our header buf into an httparse instance, and validate. let status = httparse_req . parse ( & buf ) ? ; ensure ! ( status is_partial ( ) " " ) ; // Convert httparse headers + body into a `http_types::Request` type. let method = httparse_req . method ; let method = method . ok_or_else ( | | format_err ! ( " " ) ) ? ; let path = httparse_req . path ; let path = path . ok_or_else ( | | format_err ! ( " " ) ) ? ; let version = httparse_req . version ; let version = version . ok_or_else ( | | format_err ! ( " " ) ) ? ; ensure_eq ! ( version HTTP_1_1_VERSION " " version ) ; let mut req = Request :: new ( Method :: from_str ( method ) ? , url :: Url :: parse ( " " ) . unwrap ( ) . join ( path ) ? , ) ; for header in httparse_req . headers . iter ( ) { req . insert_header ( header . name , std :: str :: from_utf8 ( header . value ) ? ) ; } set_url_and_port_from_host_header ( & mut req ) ? ; handle_100_continue ( & req , & mut io ) . await ? ; let content_length = req . header ( CONTENT_LENGTH ) ; let transfer_encoding = req . header ( TRANSFER_ENCODING ) ; http_types :: ensure ! ( content_length is_none ( ) transfer_encoding is_none ( ) " " ) ; // Check for Transfer-Encoding if let Some ( encoding ) = transfer_encoding { if encoding . last ( ) . as_str ( ) == " " { let trailer_sender = req . send_trailers ( ) ; let reader = BufReader :: new ( ChunkedDecoder :: new ( reader , trailer_sender ) ) ; req . set_body ( Body :: from_reader ( reader , None ) ) ; return Ok ( Some ( req ) ) ; } // Fall through to Content-Length } // Check for Content-Length. if let Some ( len ) = content_length { let len = len . last ( ) . as_str ( ) . parse :: < usize > ( ) ? ; req . set_body ( Body :: from_reader ( reader . take ( len as u64 ) , Some ( len ) ) ) ; } Ok ( Some ( req ) ) }
Decode an HTTP request on the server.
Decode an HTTP request on the server .
io
IO
io
IO