autoendpoint/routers/apns/
error.rs

1use crate::error::ApiErrorKind;
2use crate::routers::RouterError;
3use actix_web::http::StatusCode;
4use autopush_common::errors::ReportableError;
5use std::io;
6
7/// Errors that may occur in the Apple Push Notification Service router
8#[derive(thiserror::Error, Debug)]
9pub enum ApnsError {
10    #[error("Failed to decode the channel settings")]
11    ChannelSettingsDecode(#[from] serde_json::Error),
12
13    #[error("IO Error: {0}")]
14    Io(#[from] io::Error),
15
16    #[error("Error while setting up APNS clients: {0}")]
17    ApnsClient(#[source] a2::Error),
18
19    #[error("Error while checking the message size limit: {0}")]
20    SizeLimit(#[source] a2::Error),
21
22    #[error("APNS error, {0}")]
23    ApnsUpstream(#[source] a2::Error),
24
25    /// Configuration error {Type of error}, {Error string}
26    #[error("APNS config, {0}:{1}")]
27    Config(String, String),
28
29    #[error("No device token found for user")]
30    NoDeviceToken,
31
32    #[error("No release channel found for user")]
33    NoReleaseChannel,
34
35    #[error("Release channel is invalid")]
36    InvalidReleaseChannel,
37
38    #[error("Invalid APS data")]
39    InvalidApsData,
40
41    #[error("APNS recipient no longer available")]
42    Unregistered,
43}
44
45impl ApnsError {
46    /// Get the associated HTTP status code
47    pub fn status(&self) -> StatusCode {
48        match self {
49            ApnsError::InvalidReleaseChannel
50            | ApnsError::InvalidApsData
51            | ApnsError::SizeLimit(_) => StatusCode::BAD_REQUEST,
52
53            ApnsError::NoDeviceToken | ApnsError::NoReleaseChannel | ApnsError::Unregistered => {
54                StatusCode::GONE
55            }
56
57            ApnsError::ChannelSettingsDecode(_)
58            | ApnsError::Io(_)
59            | ApnsError::ApnsClient(_)
60            | ApnsError::Config(..) => StatusCode::INTERNAL_SERVER_ERROR,
61
62            ApnsError::ApnsUpstream(_) => StatusCode::BAD_GATEWAY,
63        }
64    }
65
66    /// Get the associated error number
67    pub fn errno(&self) -> Option<usize> {
68        match self {
69            ApnsError::NoDeviceToken | ApnsError::NoReleaseChannel | ApnsError::Unregistered => {
70                Some(106)
71            }
72
73            ApnsError::ChannelSettingsDecode(_)
74            | ApnsError::Io(_)
75            | ApnsError::ApnsClient(_)
76            | ApnsError::ApnsUpstream(_)
77            | ApnsError::InvalidReleaseChannel
78            | ApnsError::InvalidApsData
79            | ApnsError::Config(..)
80            | ApnsError::SizeLimit(_) => None,
81        }
82    }
83}
84
85impl From<ApnsError> for ApiErrorKind {
86    fn from(e: ApnsError) -> Self {
87        ApiErrorKind::Router(RouterError::Apns(e))
88    }
89}
90
91impl ReportableError for ApnsError {
92    fn is_sentry_event(&self) -> bool {
93        !matches!(self, ApnsError::SizeLimit(_) | ApnsError::Unregistered)
94    }
95
96    fn metric_label(&self) -> Option<&'static str> {
97        match &self {
98            ApnsError::SizeLimit(_) => Some("notification.bridge.error.apns.oversized"),
99            ApnsError::ApnsUpstream(_) => Some("notification.bridge.error.apns.upstream"),
100            _ => None,
101        }
102    }
103
104    fn extras(&self) -> Vec<(&str, String)> {
105        match self {
106            ApnsError::ApnsUpstream(e) => vec![("error", e.to_string())],
107            _ => vec![],
108        }
109    }
110}