Skip to main content

pacenotes_installer\selftest/
http_check.rs

1const PREVIEW_CHARS: usize = 400;
2
3/// `--selftest-http <url> [--token <bearer>] [--out <file>]`: one GET through
4/// `http`, which `tests/Test-HttpClient.ps1` drives against a live server.
5pub struct HttpSelfTest {
6    url: String,
7    /// Never written into the report, which may become a test artifact.
8    token: Option<String>,
9    out: Option<std::path::PathBuf>,
10}
11
12impl HttpSelfTest {
13    pub fn from_args() -> Option<HttpSelfTest> {
14        let mut arguments = std::env::args().skip(1);
15        let mut url = None;
16        let mut token = None;
17        let mut out = None;
18        while let Some(argument) = arguments.next() {
19            match argument.as_str() {
20                "--selftest-http" => url = arguments.next(),
21                "--token" => token = arguments.next(),
22                "--out" => out = arguments.next().map(std::path::PathBuf::from),
23                _ => {}
24            }
25        }
26        url.map(|url| HttpSelfTest { url, token, out })
27    }
28
29    /// The process exit code: 0 when the GET succeeded.
30    pub fn run(&self) -> i32 {
31        let cancel = std::sync::atomic::AtomicBool::new(false);
32        let mut content_length = None;
33        let mut progress = |_: u64, total: Option<u64>| content_length = total;
34
35        let (exit_code, report) =
36            match crate::http::get(&self.url, self.token.as_deref(), &mut progress, &cancel) {
37                Ok(body) => (0, self.success_report(&body, content_length)),
38                Err(e) => (1, self.failure_report(&e)),
39            };
40        super::report::deliver(self.out.as_deref(), &report, exit_code)
41    }
42
43    fn success_report(&self, body: &[u8], content_length: Option<u64>) -> String {
44        let preview: String = String::from_utf8_lossy(body)
45            .chars()
46            .take(PREVIEW_CHARS)
47            .collect();
48        let content_length = content_length
49            .map(|length| length.to_string())
50            .unwrap_or_else(|| "unknown".into());
51        format!(
52            "RESULT: OK\nURL: {}\nBYTES: {}\nCONTENT_LENGTH: {content_length}\nBODY: {preview}\n",
53            self.url,
54            body.len(),
55        )
56    }
57
58    fn failure_report(&self, error: &crate::http::HttpError) -> String {
59        let status = error
60            .status
61            .map(|status| status.to_string())
62            .unwrap_or_else(|| "-".into());
63        format!(
64            "RESULT: FAIL\nURL: {}\nSTATUS: {status}\nCODE: {}\nMESSAGE: {}\n",
65            self.url, error.code, error.message,
66        )
67    }
68}