expose_rs/
utils.rs

1use std::{ io::{ Read, Write }, net::TcpStream, str::Lines };
2use std::net::SocketAddr;
3
4pub struct Url {
5    pub protocol: String,
6    pub host:     String,
7    pub path:     String
8}
9
10pub fn find_line<'a> (name: &str, lines: Lines<'a>) -> Option<&'a str> {
11    let name = name.to_uppercase();
12    let name = &format!("{name}: ");
13    for line in lines {
14        if line.starts_with(name) {
15            return Some(line.trim_start_matches(name).trim())
16        }
17    }
18    None
19}
20
21#[macro_export]
22macro_rules! find_lines {
23    ($list:expr, $($l:expr),+) => {
24        ($(
25            find_line($l, $list),
26        )+)
27    };
28}
29
30pub fn get_xml_tag_childs (xml: &str, tag: &str) -> Option<String> {
31    let open_tag = &format!("<{tag}>");
32    let close_tag = &format!("</{}>", tag.split_whitespace().nth(0)?);
33
34    if let Some(x) = xml.find(open_tag) {
35        let start = x + open_tag.len();
36        if let Some(y) = &xml[start..].find(close_tag) {
37            let end = start + y;
38            return Some(xml[start .. end].into())
39        }
40    }
41
42    None
43}
44
45pub fn format_url (url: &str) -> Url {
46    let url = url.replace("://", " ").replacen("/", " ", 1);
47    let mut url = url.split_whitespace();
48    Url {
49        protocol: url.next().expect("URL to format is not correct: protocol is missing").into(),
50        host: url.next().expect("URL to format is not correct: host is missing").into(),
51        path: url.next().unwrap_or("").into()
52    }
53}
54
55pub fn open_http (url: &Url, method: &str, other: &str) -> Result<String, std::io::Error> {
56    let (host, path) = (&url.host, &url.path);
57
58    let method = method.to_uppercase();
59
60    let mut stream = TcpStream::connect(host)?;
61    let request = format!("{method} /{path} HTTP/1.1\r\n\
62    HOST: {host}\r\n\
63    {other}
64    \r\n");
65
66    stream.write_all(request.as_bytes())?;
67    let mut response = String::new();
68    stream.read_to_string(&mut response)?;
69    Ok(response)
70}
71
72pub fn get_bind () -> Result<SocketAddr, std::io::Error> {
73    use std::net::UdpSocket;
74
75    let socket = UdpSocket::bind("0.0.0.0:0")?;
76    socket.connect("8.8.8.8:80")?;
77
78    socket.local_addr()
79}