fetch_js/
lib.rs

1pub mod url;
2
3use std::collections::HashMap;
4use crate::url::URL;
5
6pub enum Method {
7  GET,
8  POST,
9  PUT,
10  DELETE,
11  PATCH,
12  HEAD,
13  OPTIONS,
14}
15
16fn get_method_string(method: &Method) -> String {
17  match method {
18    Method::GET => "GET".to_string(),
19    Method::POST => "POST".to_string(),
20    Method::PUT => "PUT".to_string(),
21    Method::DELETE => "DELETE".to_string(),
22    Method::PATCH => "PATCH".to_string(),
23    Method::HEAD => "HEAD".to_string(),
24    Method::OPTIONS => "OPTIONS".to_string(),
25  }
26}
27
28fn header_sort(headers: &HashMap<String, String>) -> Vec<String> {
29  let sorted_headers = headers.iter().collect::<Vec<(&String, &String)>>();
30  sorted_headers.iter().map(|(k, v)| format!("{}: {}", k, v)).collect()
31}
32
33pub struct RequestInit {
34  method: Method,
35  headers: HashMap<String, String>,
36  body: Option<String>,
37}
38
39#[cfg(feature = "tokio-fetch")]
40use tokio::{
41  net::TcpStream,
42  io::{AsyncWriteExt, AsyncReadExt},
43};
44
45#[cfg(feature = "tokio-fetch")]
46pub struct Response {
47  stream: TcpStream,
48}
49#[cfg(feature = "tokio-fetch")]
50impl Response {
51  pub async fn text(&mut self) -> Result<String, Box<dyn std::error::Error>> {
52    let mut buffer = vec![0; 1024];
53    let mut text = String::new();
54    loop {
55      let n = self.stream.read(&mut buffer).await?;
56      if n == 0 {
57        break;
58      }
59      text.push_str(&String::from_utf8_lossy(&buffer[..n]));
60    }
61    Ok(text)
62  }
63}
64
65#[cfg(feature = "tokio-fetch")]
66pub async fn fetch(input: URL, init: RequestInit) -> Result<Response, Box<dyn std::error::Error>> {
67  let mut stream = TcpStream::connect(input.get_hostname()).await?;
68  let request = format!(
69    "{} {} HTTP/1.1\r\nHost: {}\r\n{}\r\n\r\n{}",
70    get_method_string(&init.method),
71    input.get_pathname(),
72    input.get_hostname(),
73    header_sort(&init.headers).join("\r\n"),
74    init.body.unwrap_or("".to_string())
75  );
76  stream.write_all(request.as_bytes()).await?;
77  Ok(Response { stream })
78}
79