pforge_runtime/handlers/
http.rs1use crate::{Error, Result};
2use reqwest::{Client, Method};
3use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7#[derive(Debug, Clone)]
8pub struct HttpHandler {
9 pub endpoint: String,
10 pub method: HttpMethod,
11 pub headers: HashMap<String, String>,
12 pub auth: Option<AuthConfig>,
13 client: Client,
14}
15
16#[derive(Debug, Clone)]
17pub enum HttpMethod {
18 Get,
19 Post,
20 Put,
21 Delete,
22 Patch,
23}
24
25#[derive(Debug, Clone)]
26pub enum AuthConfig {
27 Bearer { token: String },
28 Basic { username: String, password: String },
29 ApiKey { key: String, header: String },
30}
31
32#[derive(Debug, Deserialize, JsonSchema)]
33pub struct HttpInput {
34 #[serde(default)]
35 pub body: Option<serde_json::Value>,
36 #[serde(default)]
37 pub query: HashMap<String, String>,
38}
39
40#[derive(Debug, Serialize, JsonSchema)]
41pub struct HttpOutput {
42 pub status: u16,
43 pub body: serde_json::Value,
44 pub headers: HashMap<String, String>,
45}
46
47impl HttpHandler {
48 pub fn new(
49 endpoint: String,
50 method: HttpMethod,
51 headers: HashMap<String, String>,
52 auth: Option<AuthConfig>,
53 ) -> Self {
54 Self {
55 endpoint,
56 method,
57 headers,
58 auth,
59 client: Client::new(),
60 }
61 }
62
63 pub async fn execute(&self, input: HttpInput) -> Result<HttpOutput> {
64 let method = match self.method {
65 HttpMethod::Get => Method::GET,
66 HttpMethod::Post => Method::POST,
67 HttpMethod::Put => Method::PUT,
68 HttpMethod::Delete => Method::DELETE,
69 HttpMethod::Patch => Method::PATCH,
70 };
71
72 let mut request = self.client.request(method, &self.endpoint);
73
74 for (k, v) in &self.headers {
76 request = request.header(k, v);
77 }
78
79 if let Some(auth) = &self.auth {
81 request = match auth {
82 AuthConfig::Bearer { token } => request.bearer_auth(token),
83 AuthConfig::Basic { username, password } => {
84 request.basic_auth(username, Some(password))
85 }
86 AuthConfig::ApiKey { key, header } => request.header(header, key),
87 };
88 }
89
90 if !input.query.is_empty() {
92 request = request.query(&input.query);
93 }
94
95 if let Some(body) = input.body {
97 request = request.json(&body);
98 }
99
100 let response = request
102 .send()
103 .await
104 .map_err(|e| Error::Http(format!("Request failed: {}", e)))?;
105
106 let status = response.status().as_u16();
107
108 let mut headers = HashMap::new();
110 for (k, v) in response.headers() {
111 if let Ok(v_str) = v.to_str() {
112 headers.insert(k.to_string(), v_str.to_string());
113 }
114 }
115
116 let body = response
118 .json::<serde_json::Value>()
119 .await
120 .unwrap_or(serde_json::json!({}));
121
122 Ok(HttpOutput {
123 status,
124 body,
125 headers,
126 })
127 }
128}