use crate::body::JsBody;
use crate::response::headermap_from_js;
use http::{HeaderMap, Method, Uri};
use multistore::route_handler::RequestInfo;
pub struct RequestParts {
pub method: Method,
pub path: String,
pub signing_path: String,
pub query: Option<String>,
pub headers: HeaderMap,
pub form_body: Option<String>,
}
impl RequestParts {
pub fn from_web_sys(req: &web_sys::Request) -> Result<(Self, JsBody), String> {
let body = JsBody::new(req.body());
let method: Method = req
.method()
.parse()
.map_err(|e| format!("invalid method: {e}"))?;
let uri: Uri = req.url().parse().map_err(|e| format!("invalid URL: {e}"))?;
let signing_path = uri.path().to_string();
let path = percent_encoding::percent_decode_str(uri.path())
.decode_utf8_lossy()
.to_string();
let query = uri.query().map(|q| q.to_string());
let headers = headermap_from_js(&req.headers());
Ok((
Self {
method,
path,
signing_path,
query,
headers,
form_body: None,
},
body,
))
}
pub async fn absorb_form_body(&mut self, body: JsBody) -> Result<JsBody, String> {
if !self.as_request_info().should_collect_form_body() {
return Ok(body);
}
let bytes = crate::body::collect_js_body(body).await?;
self.form_body = Some(String::from_utf8_lossy(&bytes).into_owned());
JsBody::from_bytes(&bytes)
}
pub fn as_request_info(&self) -> RequestInfo<'_> {
RequestInfo::new(
&self.method,
&self.path,
self.query.as_deref(),
&self.headers,
None,
)
.with_signing_path(&self.signing_path)
.with_form_body(self.form_body.as_deref())
}
}