scrapr_bindings/
request.rs1use pyo3::prelude::*;
2use std::collections::HashMap;
3
4#[pyclass]
5#[derive(Clone, Debug, Default)]
6pub struct RequestOptions {
7 #[pyo3(get, set)]
8 pub headers: HashMap<String, String>,
9
10 #[pyo3(get, set)]
11 pub cookies: HashMap<String, String>,
12
13 #[pyo3(get, set)]
14 pub query: HashMap<String, String>,
15}
16
17#[pymethods]
35impl RequestOptions {
36 #[new]
37 fn new(
38 headers: Option<HashMap<String, String>>,
39 cookies: Option<HashMap<String, String>>,
40 query: Option<HashMap<String, String>>,
41 ) -> Self {
42 RequestOptions {
43 headers: headers.unwrap_or_default(),
44 cookies: cookies.unwrap_or_default(),
45 query: query.unwrap_or_default(),
46 }
47 }
48}
49
50pub fn build_url(base: &str, path: &str, query: &HashMap<String, String>) -> String {
51 let mut url = format!("{base}{path}");
52 if !query.is_empty() {
53 let query_string = query
54 .iter()
55 .map(|(k, v)| format!("{}={}", k, v))
56 .collect::<Vec<_>>()
57 .join("&");
58 url.push('?');
59 url.push_str(&query_string);
60 }
61 url
62}
63
64pub fn format_headers(host: &str, options: &RequestOptions) -> String {
65 let mut headers = vec![
66 format!("Host: {host}"),
67 "Connection: close".to_string(),
68 "User-Agent: Scraper/0.1".to_string(),
69 ];
70
71 for (k, v) in &options.headers {
72 headers.push(format!("{k}: {v}"));
73 }
74
75 if !options.cookies.is_empty() {
76 let cookie_string = options
77 .cookies
78 .iter()
79 .map(|(k, v)| format!("{k}: {v}"))
80 .collect::<Vec<_>>()
81 .join("; ");
82 headers.push(format!("Cookie: {cookie_string}"));
83 }
84
85 headers.join("\r\n")
86}