use std::collections::HashMap;
use anyhow::{Context, Result};
use bytes::Bytes;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct HttpRequestPayload {
pub method: String,
pub uri: String,
pub headers: HashMap<String, String>,
pub body: Bytes,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct HttpResponsePayload {
pub status: u16,
pub headers: HashMap<String, String>,
pub body: Bytes,
}
pub async fn encode_request<B>(req: hyper::Request<B>) -> Result<Bytes>
where
B: hyper::body::Body<Data = Bytes> + Send,
B::Error: std::error::Error + Send + Sync + 'static,
{
let (parts, body) = req.into_parts();
let body_bytes = http_body_util::BodyExt::collect(body)
.await
.context("read request body")?
.to_bytes();
let headers: HashMap<String, String> = parts
.headers
.iter()
.filter_map(|(k, v)| Some((k.to_string(), v.to_str().ok()?.to_string())))
.collect();
let payload = HttpRequestPayload {
method: parts.method.to_string(),
uri: parts.uri.to_string(),
headers,
body: body_bytes,
};
let encoded = rmp_serde::to_vec_named(&payload).context("encode request")?;
Ok(Bytes::from(encoded))
}
pub fn decode_response(bytes: Bytes) -> Result<hyper::Response<http_body_util::Full<Bytes>>> {
let payload: HttpResponsePayload = rmp_serde::from_slice(&bytes).context("decode response")?;
let mut builder = hyper::Response::builder().status(payload.status);
for (k, v) in &payload.headers {
builder = builder.header(k.as_str(), v.as_str());
}
builder
.body(http_body_util::Full::new(payload.body))
.context("build response")
}