mockforge_ui/handlers/
chains.rs1use axum::{
6 extract::{Path, State},
7 http::StatusCode,
8 response::{IntoResponse, Response},
9 Json,
10};
11use serde_json::Value;
12
13use super::AdminState;
14
15pub async fn proxy_chains_list(State(state): State<AdminState>) -> Response {
17 proxy_to_http_server(&state, "/chains", None).await
18}
19
20pub async fn proxy_chains_create(
22 State(state): State<AdminState>,
23 Json(body): Json<Value>,
24) -> Response {
25 proxy_to_http_server(&state, "/chains", Some(body)).await
26}
27
28pub async fn proxy_chain_get(State(state): State<AdminState>, Path(id): Path<String>) -> Response {
30 proxy_to_http_server(&state, &format!("/chains/{}", id), None).await
31}
32
33pub async fn proxy_chain_update(
35 State(state): State<AdminState>,
36 Path(id): Path<String>,
37 Json(body): Json<Value>,
38) -> Response {
39 proxy_to_http_server(&state, &format!("/chains/{}", id), Some(body)).await
40}
41
42pub async fn proxy_chain_delete(
44 State(state): State<AdminState>,
45 Path(id): Path<String>,
46) -> Response {
47 proxy_to_http_server(&state, &format!("/chains/{}", id), None).await
48}
49
50pub async fn proxy_chain_execute(
52 State(state): State<AdminState>,
53 Path(id): Path<String>,
54 Json(body): Json<Value>,
55) -> Response {
56 proxy_to_http_server(&state, &format!("/chains/{}/execute", id), Some(body)).await
57}
58
59pub async fn proxy_chain_validate(
61 State(state): State<AdminState>,
62 Path(id): Path<String>,
63) -> Response {
64 proxy_to_http_server(&state, &format!("/chains/{}/validate", id), None).await
65}
66
67pub async fn proxy_chain_history(
69 State(state): State<AdminState>,
70 Path(id): Path<String>,
71) -> Response {
72 proxy_to_http_server(&state, &format!("/chains/{}/history", id), None).await
73}
74
75async fn proxy_to_http_server(state: &AdminState, path: &str, body: Option<Value>) -> Response {
77 let Some(http_addr) = state.http_server_addr else {
78 return (StatusCode::SERVICE_UNAVAILABLE, "HTTP server address not configured")
79 .into_response();
80 };
81
82 let url = format!("http://{}/__mockforge{}", http_addr, path);
83
84 let client = reqwest::Client::new();
85 let mut request_builder = if body.is_some() {
86 client.post(&url)
87 } else {
88 client.get(&url)
89 };
90
91 if let Some(json_body) = body {
92 request_builder = request_builder.json(&json_body);
93 }
94
95 match request_builder.send().await {
96 Ok(response) => {
97 let status = response.status();
98 match response.text().await {
99 Ok(text) => {
100 if let Ok(json) = serde_json::from_str::<Value>(&text) {
102 (
103 StatusCode::from_u16(status.as_u16()).unwrap_or(StatusCode::OK),
104 Json(json),
105 )
106 .into_response()
107 } else {
108 (StatusCode::from_u16(status.as_u16()).unwrap_or(StatusCode::OK), text)
109 .into_response()
110 }
111 }
112 Err(e) => {
113 (StatusCode::INTERNAL_SERVER_ERROR, format!("Failed to read response: {}", e))
114 .into_response()
115 }
116 }
117 }
118 Err(e) => {
119 (StatusCode::BAD_GATEWAY, format!("Failed to proxy request: {}", e)).into_response()
120 }
121 }
122}
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127 use std::net::SocketAddr;
128
129 fn create_test_state(http_addr: Option<SocketAddr>) -> AdminState {
130 AdminState::new(http_addr, None, None, None, false, 8080)
131 }
132
133 #[tokio::test]
134 async fn test_proxy_to_http_server_no_addr() {
135 let state = create_test_state(None);
136 let response = proxy_to_http_server(&state, "/test", None).await;
137
138 let _ = response;
141 }
142}