jules_api/http/
endpoint.rs1use super::Method;
4
5#[derive(Debug, Clone)]
7pub struct Endpoint {
8 base_url: String,
9 path: String,
10 method: Method,
11 query_params: Vec<(String, String)>,
12}
13
14impl Endpoint {
15 #[must_use]
17 pub fn new(base_url: impl Into<String>, path: impl Into<String>) -> Self {
18 Self {
19 base_url: base_url.into(),
20 path: path.into(),
21 method: Method::Get,
22 query_params: Vec::new(),
23 }
24 }
25
26 #[must_use]
28 pub fn with_method(mut self, method: Method) -> Self {
29 self.method = method;
30 self
31 }
32
33 #[must_use]
35 pub fn with_query(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
36 self.query_params.push((key.into(), value.into()));
37 self
38 }
39
40 #[must_use]
42 pub fn build_url(&self) -> String {
43 let capacity = self.base_url.len()
44 + self.path.len()
45 + usize::from(!self.query_params.is_empty())
46 + self
47 .query_params
48 .iter()
49 .map(|(k, v)| k.len() + v.len() + 2)
50 .sum::<usize>();
51
52 let mut url = String::with_capacity(capacity);
53 url.push_str(&self.base_url);
54 url.push_str(&self.path);
55
56 if !self.query_params.is_empty() {
57 url.push('?');
58 for (i, (k, v)) in self.query_params.iter().enumerate() {
59 if i > 0 {
60 url.push('&');
61 }
62 url.push_str(k);
63 url.push('=');
64 url.push_str(v);
65 }
66 }
67
68 url
69 }
70
71 #[must_use]
73 pub fn method(&self) -> Method {
74 self.method
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 #[test]
83 fn test_endpoint_construction() {
84 let endpoint = Endpoint::new("https://api.example.com", "/v1/users")
85 .with_method(Method::Post)
86 .with_query("limit", "10")
87 .with_query("offset", "0");
88
89 assert_eq!(endpoint.method(), Method::Post);
90 assert_eq!(
91 endpoint.build_url(),
92 "https://api.example.com/v1/users?limit=10&offset=0"
93 );
94 }
95
96 #[test]
97 fn test_endpoint_no_query() {
98 let endpoint = Endpoint::new("https://api.example.com", "/v1/users");
99 assert_eq!(endpoint.build_url(), "https://api.example.com/v1/users");
100 assert_eq!(endpoint.method(), Method::Get);
101 }
102}