about summary refs log tree commit diff
path: root/pkgs/profpatsch/xdg-open/read-http.rs
blob: 9fe8d6a917c5c583c715b532620afcf1b8a9abde (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
extern crate httparse;
extern crate netencode;

use std::os::unix::io::FromRawFd;
use std::io::Read;
use std::io::Write;

use netencode::{encode, U};

fn main() -> std::io::Result<()> {

    fn die<T: std::fmt::Display>(msg: T) {
        eprintln!("{}", msg);
        std::process::exit(1);
    }

    // max header size chosen arbitrarily
    let mut headers = [httparse::EMPTY_HEADER; 128];
    let mut resp = httparse::Response::new(&mut headers);
    let mut buf = vec![];
    std::io::stdin().read_to_end(&mut buf)?;
    let res = resp.parse(&mut buf);
    match res {
        Err(err) => die(format!("http response error: {:?}", err)),
        Ok(_start_of_body) => {
            match resp.code {
                Some(code) => write_dict(code, resp.reason, resp.headers)?,
                None => die(format!("no http status"))
            }
        }
    };
    Ok(())
}

fn write_dict<'buf>(code: u16, reason: Option<&'buf str>, headers: &mut [httparse::Header<'buf>]) -> std::io::Result<()> {
    let mut http = vec![
        ("status", Box::new(U::N6(code as u64))),
    ];

    if let Some(t) = reason {
        http.push(("status-text", Box::new(U::Text(t.as_bytes()))))
    };

    http.push(("headers", Box::new(U::Record(
        headers.iter_mut().map(
            |httparse::Header { name, value }|
            (*name,
             Box::new(U::Binary(value)))
        ).collect::<Vec<_>>()
    ))));

    encode(
        &mut std::io::stdout(),
        U::Record(http)
    )
}