1use std::collections::HashMap;
4
5use actix_http::{Uri, uri::Scheme};
6use actix_web::{HttpRequest, web::Query};
7use mod_rewrite::context::RequestCtx;
8
9use super::error::Error;
10
11type QueryMap = Query<HashMap<String, String>>;
12
13pub fn request_ctx(req: &HttpRequest) -> RequestCtx {
16 RequestCtx::default()
17 .path_info(req.match_info().unprocessed())
18 .request_uri(req.uri().to_string())
19 .request_method(req.method().to_string())
20 .query_string(req.uri().query().unwrap_or(""))
21 .maybe_remote_addr(req.peer_addr())
22 .expect("invalid peer address")
23}
24
25#[inline]
26fn get_query(uri: &Uri) -> Result<QueryMap, Error> {
27 Ok(QueryMap::from_query(uri.query().unwrap_or(""))?)
28}
29
30#[inline]
33pub fn join_uri(before: &Uri, after: &Uri) -> Result<Uri, Error> {
34 let mut query = get_query(before)?;
35 query.extend(get_query(after)?.into_inner());
36 let query = serde_urlencoded::to_string(query.into_inner())?;
37
38 let mut builder = Uri::builder().scheme(
39 after
40 .scheme()
41 .or(before.scheme())
42 .cloned()
43 .unwrap_or(Scheme::HTTP),
44 );
45
46 if let Some(authority) = after.authority().or(before.authority()) {
47 builder = builder.authority(authority.clone());
48 }
49 let path = after.path();
50 Ok(builder.path_and_query(format!("{path}?{query}")).build()?)
51}