nginx_config_mod/checks/
proxy_pass.rs

1use std::io;
2use std::net::ToSocketAddrs;
3
4use nginx_config::ast;
5use url::{self, Url, Host};
6use {Config};
7
8#[derive(Fail, Debug)]
9pub enum Error {
10    #[fail(display="Url {:?} is invalid: {}", _0, _1)]
11    InvalidUrl(String, url::ParseError),
12    #[fail(display="Can't resolve {:?} in url {:?}: {}", _0, _1, _2)]
13    Resolve(String, String, io::Error),
14    #[doc(hidden)]
15    #[fail(display="unreachable")]
16    __Nonexhaustive,
17}
18
19pub fn check_hostnames(cfg: &Config)
20    -> Result<(), Vec<Error>>
21{
22    check_selected_hostnames(cfg, |_| true)
23}
24
25pub fn check_selected_hostnames(cfg: &Config,
26    mut do_check: impl FnMut(&str) -> bool)
27    -> Result<(), Vec<Error>>
28{
29    use self::Error::*;
30    let mut errors = Vec::new();;
31    for dir in cfg.all_directives() {
32        match dir.item {
33            ast::Item::ProxyPass(ref texturl) => {
34                let texturl = texturl.to_string();
35                let url_part = if let Some(off) = texturl.find("$request_uri") {
36                    &texturl[..off]
37                } else {
38                    &texturl
39                };
40                let url = match Url::parse(&url_part) {
41                    Ok(url) => url,
42                    Err(e) => {
43                        errors.push(InvalidUrl(texturl.clone(), e));
44                        continue;
45                    }
46                };
47                match url.host() {
48                    Some(Host::Domain(val)) => {
49                        if !do_check(val) {
50                            continue;
51                        }
52                        match (val, url.port().unwrap_or(80)).to_socket_addrs()
53                        {
54                            Ok(_) => {}
55                            Err(e) => {
56                                errors.push(Resolve(val.to_string(),
57                                    texturl.clone(), e));
58                            }
59                        }
60                    }
61                    Some(Host::Ipv4(..)) => {}
62                    Some(Host::Ipv6(..)) => {}
63                    None => {}
64                }
65            }
66            _ => {}
67        }
68    }
69    if errors.is_empty() {
70        return Ok(());
71    }
72    return Err(errors);
73}