Page MenuHomePhabricator

D8972.id30634.diff
No OneTemporary

D8972.id30634.diff

diff --git a/services/reports/src/http/handlers.rs b/services/reports/src/http/handlers.rs
--- a/services/reports/src/http/handlers.rs
+++ b/services/reports/src/http/handlers.rs
@@ -1,4 +1,5 @@
use actix_web::{get, post, web, HttpResponse};
+use http::header;
use serde::Deserialize;
use super::NotFoundHandler;
@@ -49,3 +50,23 @@
let response = HttpResponse::Ok().json(report);
Ok(response)
}
+
+#[get("/{report_id}/redux-devtools.json")]
+async fn redux_devtools_import(
+ path: web::Path<String>,
+ service: ReportsService,
+) -> actix_web::Result<HttpResponse> {
+ let report_id = path.into_inner();
+ let devtools_json = service
+ .get_redux_devtools_import(report_id.clone().into())
+ .await?
+ .unwrap_or_404()?;
+
+ let response = HttpResponse::Ok()
+ .insert_header((
+ header::CONTENT_DISPOSITION,
+ format!("attachment; filename=report-{}.json", report_id),
+ ))
+ .json(devtools_json);
+ Ok(response)
+}
diff --git a/services/reports/src/http/mod.rs b/services/reports/src/http/mod.rs
--- a/services/reports/src/http/mod.rs
+++ b/services/reports/src/http/mod.rs
@@ -37,7 +37,8 @@
.service(
web::scope("/reports")
.service(handlers::post_reports)
- .service(handlers::get_single_report),
+ .service(handlers::get_single_report)
+ .service(handlers::redux_devtools_import),
)
})
.bind(("0.0.0.0", CONFIG.http_port))?
diff --git a/services/reports/src/service.rs b/services/reports/src/service.rs
--- a/services/reports/src/service.rs
+++ b/services/reports/src/service.rs
@@ -5,12 +5,15 @@
database,
};
use derive_more::{Display, Error, From};
-use std::future::{ready, Ready};
+use std::{
+ collections::HashMap,
+ future::{ready, Ready},
+};
use tracing::error;
use crate::{
database::{client::DatabaseClient, item::ReportItem},
- report_types::{ReportID, ReportInput, ReportOutput},
+ report_types::{ReportID, ReportInput, ReportOutput, ReportType},
};
#[derive(Debug, Display, Error, From)]
@@ -125,6 +128,22 @@
};
Ok(Some(output))
}
+
+ pub async fn get_redux_devtools_import(
+ &self,
+ report_id: ReportID,
+ ) -> ServiceResult<Option<serde_json::Value>> {
+ let Some(report) = self.get_report(report_id).await? else {
+ return Ok(None);
+ };
+ if !matches!(report.report_type, ReportType::ErrorReport) {
+ return Err(ReportsServiceError::UnsupportedReportType);
+ };
+
+ let redux_devtools_payload = prepare_redux_devtools_import(report.content)
+ .map_err(ReportsServiceError::SerdeError)?;
+ Ok(Some(redux_devtools_payload))
+ }
}
impl FromRequest for ReportsService {
@@ -160,3 +179,29 @@
ready(Ok(auth_service))
}
}
+
+/// Transforms report content JSON into format that can be
+/// imported into Redux DevTools.
+fn prepare_redux_devtools_import(
+ mut error_report: HashMap<String, serde_json::Value>,
+) -> Result<serde_json::Value, serde_json::Error> {
+ use serde_json::{json, map::Map, Value};
+
+ let nav_state = error_report.remove("navState");
+ let actions = error_report.remove("actions");
+ let mut preloaded_state = error_report
+ .remove("preloadedState")
+ .unwrap_or_else(|| Value::Object(Map::new()));
+
+ preloaded_state["navState"] = nav_state.into();
+ preloaded_state["frozen"] = true.into();
+ preloaded_state["_persist"]["rehydrated"] = false.into();
+
+ let preload_state_str = serde_json::to_string(&preloaded_state)?;
+ let payload_str = serde_json::to_string(&actions)?;
+
+ Ok(json!({
+ "preloadedState": preload_state_str,
+ "payload": payload_str,
+ }))
+}

File Metadata

Mime Type
text/plain
Expires
Sun, Sep 29, 9:54 AM (22 h, 38 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2198214
Default Alt Text
D8972.id30634.diff (3 KB)

Event Timeline