Skip to main content

forge_runtime/gateway/
request.rs

1use serde::{Deserialize, Serialize};
2
3/// RPC request body for function calls.
4#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct RpcRequest {
6    /// Function name to invoke.
7    pub function: String,
8    /// Function arguments as JSON.
9    #[serde(default)]
10    pub args: serde_json::Value,
11}
12
13impl RpcRequest {
14    /// Create a new RPC request.
15    pub fn new(function: impl Into<String>, args: serde_json::Value) -> Self {
16        Self {
17            function: function.into(),
18            args,
19        }
20    }
21}
22
23/// Batch RPC request containing multiple function calls.
24#[derive(Debug, Clone, Serialize, Deserialize)]
25pub struct BatchRpcRequest {
26    /// List of requests to execute.
27    pub requests: Vec<RpcRequest>,
28}
29
30/// Batch RPC response containing results for each request.
31#[derive(Debug, Clone, Serialize, Deserialize)]
32pub struct BatchRpcResponse {
33    /// Individual results for each request.
34    pub results: Vec<super::response::RpcResponse>,
35}
36
37impl axum::response::IntoResponse for BatchRpcResponse {
38    fn into_response(self) -> axum::response::Response {
39        (axum::http::StatusCode::OK, axum::Json(self)).into_response()
40    }
41}
42
43#[cfg(test)]
44#[allow(clippy::unwrap_used, clippy::indexing_slicing, clippy::panic)]
45mod tests {
46    use super::*;
47
48    #[test]
49    fn test_rpc_request_deserialization() {
50        let json = r#"{"function": "getUser", "args": {"id": "123"}}"#;
51        let req: RpcRequest = serde_json::from_str(json).unwrap();
52        assert_eq!(req.function, "getUser");
53        assert_eq!(req.args["id"], "123");
54    }
55
56    #[test]
57    fn test_rpc_request_default_args() {
58        let json = r#"{"function": "healthCheck"}"#;
59        let req: RpcRequest = serde_json::from_str(json).unwrap();
60        assert_eq!(req.function, "healthCheck");
61        assert!(req.args.is_null());
62    }
63
64    #[test]
65    fn test_batch_request() {
66        let json = r#"{"requests": [{"function": "a"}, {"function": "b"}]}"#;
67        let batch: BatchRpcRequest = serde_json::from_str(json).unwrap();
68        assert_eq!(batch.requests.len(), 2);
69    }
70
71    #[test]
72    fn test_batch_response_serialization() {
73        use super::super::response::RpcResponse;
74
75        let resp = BatchRpcResponse {
76            results: vec![
77                RpcResponse::success(serde_json::json!({"id": 1})),
78                RpcResponse::error(super::super::response::RpcError::not_found("not found")),
79            ],
80        };
81        let json = serde_json::to_string(&resp).unwrap();
82        assert!(json.contains("\"results\""));
83
84        let parsed: BatchRpcResponse = serde_json::from_str(&json).unwrap();
85        assert_eq!(parsed.results.len(), 2);
86        assert!(parsed.results[0].success);
87        assert!(!parsed.results[1].success);
88    }
89}