From 2d8bdf93ba98cdfd680fab79abf7bcd407f4a37c Mon Sep 17 00:00:00 2001 From: James MacMahon Date: Tue, 12 Mar 2024 15:13:16 -0400 Subject: [PATCH] Add Error::not_found variant (#5242) Add a variant to our external Error so that a 404 can be returned without requiring a ResourceType - adding one may not make sense for a particular endpoint. --- common/src/api/external/error.rs | 29 +++++++++++++++++++++++++++++ nexus/src/app/session.rs | 3 ++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/common/src/api/external/error.rs b/common/src/api/external/error.rs index 2cb3dc0d6e..ef64aa3bbb 100644 --- a/common/src/api/external/error.rs +++ b/common/src/api/external/error.rs @@ -71,6 +71,11 @@ pub enum Error { #[error("Conflict: {}", .message.display_internal())] Conflict { message: MessagePair }, + + /// A generic 404 response. If there is an applicable ResourceType, use + /// ObjectNotFound instead. + #[error("Not found: {}", .message.display_internal())] + NotFound { message: MessagePair }, } /// Represents an error message which has an external component, along with @@ -199,6 +204,7 @@ impl Error { | Error::InsufficientCapacity { .. } | Error::InternalError { .. } | Error::TypeVersionMismatch { .. } + | Error::NotFound { .. } | Error::Conflict { .. } => false, } } @@ -300,6 +306,15 @@ impl Error { Error::Conflict { message: MessagePair::new(message.into()) } } + /// Generates an [`Error::NotFound`] with a specific message. + /// + /// This is used in cases where a generic 404 is required. For cases where + /// there is a ResourceType, use a function that produces + /// [`Error::ObjectNotFound`] instead. + pub fn non_resourcetype_not_found(message: impl Into) -> Error { + Error::NotFound { message: MessagePair::new(message.into()) } + } + /// Given an [`Error`] with an internal message, return the same error with /// `context` prepended to it to provide more context /// @@ -354,6 +369,9 @@ impl Error { Error::Conflict { message } => Error::Conflict { message: message.with_internal_context(context), }, + Error::NotFound { message } => Error::NotFound { + message: message.with_internal_context(context), + }, } } } @@ -475,6 +493,17 @@ impl From for HttpError { internal_message, } } + + Error::NotFound { message } => { + let (internal_message, external_message) = + message.into_internal_external(); + HttpError { + status_code: http::StatusCode::NOT_FOUND, + error_code: Some(String::from("Not Found")), + external_message, + internal_message, + } + } } } } diff --git a/nexus/src/app/session.rs b/nexus/src/app/session.rs index 7adf1c9bdd..dd3665161a 100644 --- a/nexus/src/app/session.rs +++ b/nexus/src/app/session.rs @@ -156,7 +156,8 @@ impl super::Nexus { | Error::ServiceUnavailable { .. } | Error::InsufficientCapacity { .. } | Error::TypeVersionMismatch { .. } - | Error::Conflict { .. } => { + | Error::Conflict { .. } + | Error::NotFound { .. } => { Reason::UnknownError { source: error } } })?;