nginx_config_mod/checks/
proxy_pass.rs1use 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}