pub async fn read_body<B>(encoding: ContentEncoding, body: &mut B) -> io::Result<Vec<u8>>
where
    B: Body + Sized + Unpin + 'static,
    B::Data: AsRef<[u8]>,
    B::Error: Into<Box<(dyn ::std::error::Error + Send + Sync + 'static)>>,
{
    let mut raw_body = Vec::new();

    let mut body_stream = body.into_data_stream();
    while let Some(data) = body_stream.next().await {
        match data {
            Ok(data) => raw_body.extend_from_slice(data.as_ref()),
            Err(err) => return Err(io::Error::other(err)),
        }
    }

    match encoding {
        ContentEncoding::Identity => Ok(raw_body),

        ContentEncoding::Deflate => {
            use flate2::read::DeflateDecoder;

            let mut decoder = DeflateDecoder::new(&raw_body[..]);
            let mut decoded_body = Vec::new();
            decoder.read_to_end(&mut decoded_body)?;

            Ok(decoded_body)
        }

        ContentEncoding::Gzip => {
            use flate2::read::GzDecoder;

            let mut decoder = GzDecoder::new(&raw_body[..]);
            let mut decoded_body = Vec::new();
            decoder.read_to_end(&mut decoded_body)?;

            Ok(decoded_body)
        }

        ContentEncoding::Br => {
            let mut decoded_body = Vec::new();
            brotli::BrotliDecompress(&mut Cursor::new(&raw_body[..]), &mut decoded_body)?;
            Ok(decoded_body)
        }

        ContentEncoding::Zstd => zstd::decode_all(Cursor::new(&raw_body[..])),
    }
}
Read data from body, decode automatically with specific Content-Encoding
crates/shadowsocks-service/src/local/online_config/content_encoding.rs