openzeppelin_relayer/api/routes/
plugin.rs

1//! This module defines the HTTP routes for plugin operations.
2//! It includes handlers for calling plugin methods.
3//! The routes are integrated with the Actix-web framework and interact with the plugin controller.
4use crate::{
5    api::controllers::plugin,
6    models::{DefaultAppState, PaginationQuery, PluginCallRequest},
7};
8use actix_web::{get, post, web, Responder};
9
10/// List plugins
11#[get("/plugins")]
12async fn list_plugins(
13    query: web::Query<PaginationQuery>,
14    data: web::ThinData<DefaultAppState>,
15) -> impl Responder {
16    plugin::list_plugins(query.into_inner(), data).await
17}
18
19/// Calls a plugin method.
20#[post("/plugins/{plugin_id}/call")]
21async fn plugin_call(
22    plugin_id: web::Path<String>,
23    req: web::Json<PluginCallRequest>,
24    data: web::ThinData<DefaultAppState>,
25) -> impl Responder {
26    plugin::call_plugin(plugin_id.into_inner(), req.into_inner(), data).await
27}
28
29/// Initializes the routes for the plugins module.
30pub fn init(cfg: &mut web::ServiceConfig) {
31    // Register routes with literal segments before routes with path parameters
32    cfg.service(plugin_call); // /plugins/{plugin_id}/call
33    cfg.service(list_plugins); // /plugins
34}
35
36#[cfg(test)]
37mod tests {
38    use std::time::Duration;
39
40    use super::*;
41    use crate::{models::PluginModel, services::plugins::PluginCallResponse};
42    use actix_web::{test, App, HttpResponse};
43
44    async fn mock_plugin_call() -> impl Responder {
45        HttpResponse::Ok().json(PluginCallResponse {
46            success: true,
47            message: "Plugin called successfully".to_string(),
48            return_value: String::from(""),
49            logs: vec![],
50            error: String::from(""),
51            traces: Vec::new(),
52        })
53    }
54
55    async fn mock_list_plugins() -> impl Responder {
56        HttpResponse::Ok().json(vec![
57            PluginModel {
58                id: "test-plugin".to_string(),
59                path: "test-path".to_string(),
60                timeout: Duration::from_secs(69),
61            },
62            PluginModel {
63                id: "test-plugin2".to_string(),
64                path: "test-path2".to_string(),
65                timeout: Duration::from_secs(69),
66            },
67        ])
68    }
69
70    #[actix_web::test]
71    async fn test_plugin_call() {
72        let app = test::init_service(
73            App::new()
74                .service(
75                    web::resource("/plugins/{plugin_id}/call")
76                        .route(web::post().to(mock_plugin_call)),
77                )
78                .configure(init),
79        )
80        .await;
81
82        let req = test::TestRequest::post()
83            .uri("/plugins/test-plugin/call")
84            .insert_header(("Content-Type", "application/json"))
85            .set_json(serde_json::json!({
86                "params": serde_json::Value::Null,
87            }))
88            .to_request();
89        let resp = test::call_service(&app, req).await;
90
91        assert!(resp.status().is_success());
92
93        let body = test::read_body(resp).await;
94        let plugin_call_response: PluginCallResponse = serde_json::from_slice(&body).unwrap();
95        assert!(plugin_call_response.success);
96    }
97
98    #[actix_web::test]
99    async fn test_list_plugins() {
100        let app = test::init_service(
101            App::new()
102                .service(web::resource("/plugins").route(web::get().to(mock_list_plugins)))
103                .configure(init),
104        )
105        .await;
106
107        let req = test::TestRequest::get().uri("/plugins").to_request();
108        let resp = test::call_service(&app, req).await;
109
110        assert!(resp.status().is_success());
111
112        let body = test::read_body(resp).await;
113        let plugin_call_response: Vec<PluginModel> = serde_json::from_slice(&body).unwrap();
114
115        assert_eq!(plugin_call_response.len(), 2);
116        assert_eq!(plugin_call_response[0].id, "test-plugin");
117        assert_eq!(plugin_call_response[0].path, "test-path");
118        assert_eq!(plugin_call_response[1].id, "test-plugin2");
119        assert_eq!(plugin_call_response[1].path, "test-path2");
120    }
121}