Skip to main content

agentkit_http/
request.rs

1use std::sync::Arc;
2
3use bytes::Bytes;
4use http::{HeaderMap, HeaderName, HeaderValue, Method};
5use serde::Serialize;
6
7use crate::{HttpClient, HttpError, HttpResponse};
8
9#[derive(Debug, Clone)]
10pub struct HttpRequest {
11    pub method: Method,
12    pub url: String,
13    pub headers: HeaderMap,
14    pub body: Option<Bytes>,
15}
16
17impl HttpRequest {
18    pub fn new(method: Method, url: impl Into<String>) -> Self {
19        Self {
20            method,
21            url: url.into(),
22            headers: HeaderMap::new(),
23            body: None,
24        }
25    }
26}
27
28pub struct HttpRequestBuilder {
29    client: Arc<dyn HttpClient>,
30    request: Result<HttpRequest, HttpError>,
31}
32
33impl HttpRequestBuilder {
34    pub fn new(client: Arc<dyn HttpClient>, method: Method, url: impl Into<String>) -> Self {
35        Self {
36            client,
37            request: Ok(HttpRequest::new(method, url)),
38        }
39    }
40
41    pub fn header<K, V>(mut self, key: K, value: V) -> Self
42    where
43        HeaderName: TryFrom<K>,
44        <HeaderName as TryFrom<K>>::Error: std::fmt::Display,
45        HeaderValue: TryFrom<V>,
46        <HeaderValue as TryFrom<V>>::Error: std::fmt::Display,
47    {
48        if let Ok(req) = self.request.as_mut() {
49            match (HeaderName::try_from(key), HeaderValue::try_from(value)) {
50                (Ok(name), Ok(val)) => {
51                    req.headers.append(name, val);
52                }
53                (Err(e), _) => {
54                    self.request = Err(HttpError::InvalidHeader(format!("header name: {e}")));
55                }
56                (_, Err(e)) => {
57                    self.request = Err(HttpError::InvalidHeader(format!("header value: {e}")));
58                }
59            }
60        }
61        self
62    }
63
64    pub fn headers(mut self, headers: HeaderMap) -> Self {
65        if let Ok(req) = self.request.as_mut() {
66            req.headers.extend(headers);
67        }
68        self
69    }
70
71    pub fn bearer_auth(self, token: impl std::fmt::Display) -> Self {
72        self.header(http::header::AUTHORIZATION, format!("Bearer {token}"))
73    }
74
75    pub fn body(mut self, body: impl Into<Bytes>) -> Self {
76        if let Ok(req) = self.request.as_mut() {
77            req.body = Some(body.into());
78        }
79        self
80    }
81
82    pub fn json<T: Serialize + ?Sized>(mut self, value: &T) -> Self {
83        if let Ok(req) = self.request.as_mut() {
84            match serde_json::to_vec(value) {
85                Ok(bytes) => {
86                    if !req.headers.contains_key(http::header::CONTENT_TYPE) {
87                        req.headers.insert(
88                            http::header::CONTENT_TYPE,
89                            HeaderValue::from_static("application/json"),
90                        );
91                    }
92                    req.body = Some(Bytes::from(bytes));
93                }
94                Err(e) => {
95                    self.request = Err(HttpError::Serialize(e));
96                }
97            }
98        }
99        self
100    }
101
102    pub fn build(self) -> Result<HttpRequest, HttpError> {
103        self.request
104    }
105
106    pub async fn send(self) -> Result<HttpResponse, HttpError> {
107        let Self { client, request } = self;
108        let request = request?;
109        client.execute(request).await
110    }
111}