1use std::{collections::HashMap, str::FromStr};
4
5use actix_http::Uri;
6use actix_web::{HttpRequest, web::Query};
7use mod_rewrite::context::RequestCtx;
8
9use super::error::Error;
10
11type QueryMap = Query<HashMap<String, String>>;
12
13#[inline]
14pub(crate) fn recode(uri: String) -> Result<Uri, Error> {
15 Ok(Uri::from_str(&uri)?)
16}
17
18pub fn request_ctx(req: &HttpRequest) -> RequestCtx {
21 RequestCtx::default()
22 .path_info(req.match_info().unprocessed())
23 .request_uri(req.uri().to_string())
24 .request_method(req.method().to_string())
25 .query_string(req.uri().query().unwrap_or(""))
26 .maybe_remote_addr(req.peer_addr())
27 .expect("invalid peer address")
28}
29
30#[inline]
31fn get_query(uri: &Uri) -> Result<QueryMap, Error> {
32 Ok(QueryMap::from_query(uri.query().unwrap_or(""))?)
33}
34
35#[inline]
38pub fn join_uri(before: &Uri, after: &Uri) -> Result<Uri, Error> {
39 let mut query = get_query(before)?;
40 query.extend(get_query(after)?.into_inner());
41 let query = serde_urlencoded::to_string(query.into_inner())?;
42
43 let scheme = after
44 .scheme()
45 .or(before.scheme())
46 .map(|scheme| format!("{}://", scheme.as_str()))
47 .unwrap_or_default();
48 let authority = after
49 .authority()
50 .or(before.authority())
51 .map(|authority| authority.as_str())
52 .unwrap_or_default();
53 let path = after.path();
54
55 let uri = &format!("{scheme}{authority}{path}?{query}");
56 Ok(Uri::from_str(&uri)?)
57}