reactive_graph_runtime_web_impl/
web_resource_manager_handler.rs

1use std::sync::Arc;
2
3use actix_http::body::BoxBody;
4use actix_web::HttpRequest;
5use actix_web::HttpResponse;
6use actix_web::HttpResponseBuilder;
7use actix_web::web;
8use http::Request;
9use http::Response;
10use http::header::CONTENT_TYPE;
11use log::debug;
12
13use reactive_graph_plugin_api::HttpBody;
14use reactive_graph_runtime_web_api::RootPathInfo;
15use reactive_graph_runtime_web_api::WebResourceManager;
16use reactive_graph_runtime_web_api::WebResourcePathInfo;
17
18pub async fn handle_web_resource(
19    web_resource_manager: web::Data<Arc<dyn WebResourceManager + Send + Sync>>,
20    path_info: web::Path<WebResourcePathInfo>,
21    request: HttpRequest,
22) -> HttpResponse {
23    let context_path = path_info.web_resource_context_path.clone();
24    let path = path_info.path.clone();
25    let uri = request.uri().clone();
26    let http_request = convert_request(request);
27    match web_resource_manager.get(context_path.clone()) {
28        Some(web_resource) => match web_resource.handle_web_resource(path, http_request).await {
29            Ok(response) => convert_response(response),
30            Err(e) => HttpResponse::InternalServerError().body(format!("500 Internal Server Error: {e}")),
31        },
32        None => match web_resource_manager.get_default() {
33            Some(web_resource) => match web_resource.handle_web_resource(format!("{context_path}/{path}"), http_request).await {
34                Ok(response) => convert_response(response),
35                Err(e) => HttpResponse::InternalServerError().body(format!("500 Internal Server Error: {e}")),
36            },
37            None => HttpResponse::NotFound().body(format!("404 Not Found: {uri}")),
38        },
39    }
40}
41
42pub async fn handle_root_web_resource(
43    web_resource_manager: web::Data<Arc<dyn WebResourceManager + Send + Sync>>,
44    path_info: web::Path<RootPathInfo>,
45    request: HttpRequest,
46) -> HttpResponse {
47    let path = path_info.path.clone();
48    let uri = request.uri().clone();
49    debug!("Handle root web resource on path: {path} uri: {uri}");
50    let http_request = convert_request(request);
51    match web_resource_manager.get_default() {
52        Some(web_resource) => match web_resource.handle_web_resource(path, http_request).await {
53            Ok(response) => convert_response(response),
54            Err(e) => HttpResponse::InternalServerError().body(format!("500 Internal Server Error: {e}")),
55        },
56        None => HttpResponse::NotFound().body(format!("404 Not Found: {uri}")),
57    }
58}
59
60fn convert_request(request: HttpRequest) -> Request<HttpBody> {
61    let mut request_builder = http::request::Builder::new()
62        .uri(request.uri())
63        .method(request.method())
64        .version(request.version());
65    if let Some(headers_map) = request_builder.headers_mut() {
66        request.headers().into_iter().for_each(|(header_name, header_value)| {
67            headers_map.insert(header_name, header_value.clone());
68        });
69    }
70    request_builder.body(HttpBody::None).unwrap()
71}
72
73fn convert_response(response: Response<HttpBody>) -> HttpResponse {
74    let mut response_builder = HttpResponseBuilder::new(response.status());
75    if let Some(header) = response.headers().get(CONTENT_TYPE) {
76        response_builder.content_type(header);
77    }
78    response.headers().into_iter().for_each(|header| {
79        response_builder.append_header(header);
80    });
81    response_builder.body(match response.into_body() {
82        HttpBody::None => BoxBody::new(()),
83        HttpBody::Binary(bytes) => BoxBody::new(bytes),
84        HttpBody::Json(value) => BoxBody::new(serde_json::to_string(&value).unwrap_or_default()),
85        HttpBody::PlainText(content) => BoxBody::new(content),
86    })
87}