1use std::collections::HashMap;
2use std::sync::Arc;
3use http::{Uri, uri::Authority};
4
5use crate::error::*;
6
7pub struct NatMap {
8 natmap: HashMap<String, Authority>
9}
10
11impl NatMap {
12 pub fn new(mut src: impl Iterator<Item=(String, String)>) -> Result<NatMap> {
13 src
14 .try_fold(
15 HashMap::new(),
16 |mut m, (k, v)| v.parse().aerr_f(|| format!("cannot parse NAT value for k={}", k)).map(|v| { m.insert(k, v); m } )
17 ).map(|natmap| NatMap { natmap })
18 }
19 pub fn translate(&self, uri: Uri) -> Result<Uri> {
20 if self.natmap.is_empty() {
21 Ok(uri)
22 } else {
23 if let Some(s) = uri.authority() {
24 if let Some(replacement) = self.natmap.get(s.as_str()) {
25 let mut parts = uri.into_parts();
26 parts.authority = Some(replacement.clone());
27 Ok(http::uri::Uri::from_parts(parts).aerr("Could not assemble redirect uri after NAT")?)
28 } else {
29 Ok(uri)
30 }
31 } else {
32 Ok(uri)
33 }
34 }
35 }
36}
37
38#[derive(Clone)]
39pub struct NatMapPtr {
40 ptr: Option<Arc<NatMap>>
41}
42
43impl NatMapPtr {
44 pub fn new(natmap: NatMap) -> NatMapPtr {
45 NatMapPtr { ptr: if natmap.natmap.is_empty() { None } else { Some(Arc::new(natmap)) } }
46 }
47
48 pub fn empty() -> NatMapPtr {
49 NatMapPtr { ptr: None }
50 }
51
52 pub fn translate(&self, uri: Uri) -> Result<Uri> {
53 if let Some(p) = &self.ptr {
54 p.translate(uri)
55 } else {
56 Ok(uri)
57 }
58 }
59}