diff options
author | Profpatsch <mail@profpatsch.de> | 2020-07-03 13:11:03 +0200 |
---|---|---|
committer | Profpatsch <mail@profpatsch.de> | 2020-07-06 20:13:42 +0200 |
commit | 97f05263ef490a063a33733d7ea607411a097df8 (patch) | |
tree | f1617705e22437c908459e1de059993bcab09ed3 /pkgs/profpatsch/xdg-open/read-http.rs | |
parent | e409df3861f48de44d0e37277ce007e348a7a0dc (diff) |
pkgs/profpatsch/xdg-open: Prepare decoding http urls
I want to be able to open http(s) links that are e.g. images directly in the right application. Aka web urls should be transparent, instead of always opening everthing in the browser. This adds some silly ways of connecting to the server and parsing out the headers, in order to fetch the content-type.
Diffstat (limited to 'pkgs/profpatsch/xdg-open/read-http.rs')
-rw-r--r-- | pkgs/profpatsch/xdg-open/read-http.rs | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/pkgs/profpatsch/xdg-open/read-http.rs b/pkgs/profpatsch/xdg-open/read-http.rs new file mode 100644 index 00000000..9fe8d6a9 --- /dev/null +++ b/pkgs/profpatsch/xdg-open/read-http.rs @@ -0,0 +1,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) + ) +} |