diff --git a/services/identity/src/http/errors.rs b/services/identity/src/http/errors.rs new file mode 100644 --- /dev/null +++ b/services/identity/src/http/errors.rs @@ -0,0 +1,61 @@ +use hyper::{Body, Response, StatusCode}; +use tracing::error; + +use super::ErrorResponse; +pub use crate::websockets::errors::BoxedError; + +pub fn create_error_response( + code: StatusCode, + message: &'static str, +) -> ErrorResponse { + let response = Response::builder().status(code).body(Body::from(message))?; + Ok(response) +} + +pub fn http500() -> ErrorResponse { + create_error_response(StatusCode::INTERNAL_SERVER_ERROR, "unexpected error") +} + +pub fn http400(message: &'static str) -> ErrorResponse { + create_error_response(StatusCode::BAD_REQUEST, message) +} + +pub fn http404(message: &'static str) -> ErrorResponse { + create_error_response(StatusCode::NOT_FOUND, message) +} + +pub fn http405() -> ErrorResponse { + create_error_response(StatusCode::METHOD_NOT_ALLOWED, "method not allowed") +} + +impl From for ErrorResponse { + fn from(db_error: crate::error::Error) -> Self { + use crate::constants::error_types; + use crate::error::DeviceListError; + use crate::error::Error as DBError; + use comm_lib::aws::DynamoDBError; + + match db_error { + DBError::AwsSdk(DynamoDBError::InternalServerError(_)) + | DBError::AwsSdk( + DynamoDBError::ProvisionedThroughputExceededException(_), + ) + | DBError::AwsSdk(DynamoDBError::RequestLimitExceeded(_)) => { + create_error_response(StatusCode::SERVICE_UNAVAILABLE, "please retry") + } + DBError::DeviceList(DeviceListError::InvalidDeviceListUpdate) => { + http400("invalid device list update") + } + DBError::DeviceList(DeviceListError::InvalidSignature) => { + http400("invalid device list signature") + } + e => { + error!( + errorType = error_types::GENERIC_DB_LOG, + "Encountered an unexpected error: {}", e + ); + http500() + } + } + } +} diff --git a/services/identity/src/http/mod.rs b/services/identity/src/http/mod.rs --- a/services/identity/src/http/mod.rs +++ b/services/identity/src/http/mod.rs @@ -1,9 +1,12 @@ -use http::StatusCode; use hyper::{Body, Request, Response}; +mod errors; + type HttpRequest = Request; type HttpResponse = Response; +type ErrorResponse = Result; + /// Main router for HTTP requests #[tracing::instrument(skip_all, name = "http_request", fields(request_id))] pub(super) async fn handle_http_request( @@ -15,9 +18,7 @@ let response = match req.uri().path() { "/health" => Response::new(Body::from("OK")), - _ => Response::builder() - .status(StatusCode::NOT_FOUND) - .body(Body::from("Not found"))?, + _ => errors::http404("Not found")?, }; Ok(response) }