diff --git a/services/identity/src/http/errors.rs b/services/identity/src/http/errors.rs new file mode 100644 index 000000000..82d9f7c5b --- /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 index 4efa0b144..62c6cc61d 100644 --- a/services/identity/src/http/mod.rs +++ b/services/identity/src/http/mod.rs @@ -1,23 +1,24 @@ -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( req: HttpRequest, _db_client: crate::DatabaseClient, ) -> Result { tracing::Span::current() .record("request_id", uuid::Uuid::new_v4().to_string()); 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) }