apple_apns/header.rs
1use http::header::{HeaderName, HeaderValue};
2use serde::{Deserialize, Serialize};
3use serde_plain::{derive_display_from_serialize, derive_fromstr_from_deserialize};
4use serde_repr::{Deserialize_repr, Serialize_repr};
5
6/// Payload size limit for message types other than VoIP.
7pub const PAYLOAD_SIZE_LIMIT: usize = 4096;
8
9/// Payload size limit for the VoIP message type.
10pub const VOIP_PAYLOAD_SIZE_LIMIT: usize = 5120;
11
12/// (Required for watchOS 6 and later; recommended for macOS, iOS, tvOS, and
13/// iPadOS) The value of this header must accurately reflect the contents of
14/// your notification’s payload. If there’s a mismatch, or if the header is
15/// missing on required systems, APNs may return an error, delay the delivery of
16/// the notification, or drop it altogether.
17pub static APNS_PUSH_TYPE: HeaderName = HeaderName::from_static("apns-push-type");
18
19/// A canonical UUID that is the unique ID for the notification. If an error
20/// occurs when sending the notification, APNs includes this value when
21/// reporting the error to your server. Canonical UUIDs are 32 lowercase
22/// hexadecimal digits, displayed in five groups separated by hyphens in the
23/// form 8-4-4-4-12. For example: 123e4567-e89b-12d3-a456-4266554400a0. If you
24/// omit this header, APNs creates a UUID for you and returns it in its
25/// response.
26pub static APNS_ID: HeaderName = HeaderName::from_static("apns-id");
27
28/// The date at which the notification is no longer valid. This value is a UNIX
29/// epoch expressed in seconds (UTC). If the value is nonzero, APNs stores the
30/// notification and tries to deliver it at least once, repeating the attempt as
31/// needed until the specified date. If the value is 0, APNs attempts to deliver
32/// the notification only once and doesn’t store it.
33///
34/// A single APNs attempt may involve retries over multiple network interfaces
35/// and connections of the destination device. Often these retries span over
36/// some time period, depending on the network characteristics. In addition, a
37/// push notification may take some time on the network after APNs sends it to
38/// the device. APNs uses best efforts to honor the expiry date without any
39/// guarantee. If the value is nonzero, the notification may be delivered after
40/// the mentioned date. If the value is 0, the notification may be delivered
41/// with some delay.
42pub static APNS_EXPIRATION: HeaderName = HeaderName::from_static("apns-expiration");
43
44/// The priority of the notification. If you omit this header, APNs sets the
45/// notification priority to 10.
46///
47/// Specify 10 to send the notification immediately.
48///
49/// Specify 5 to send the notification based on power considerations on the
50/// user’s device.
51///
52/// Specify 1 to prioritize the device’s power considerations over all other
53/// factors for delivery, and prevent awakening the device.
54pub static APNS_PRIORITY: HeaderName = HeaderName::from_static("apns-priority");
55
56/// The topic for the notification. In general, the topic is your app’s bundle
57/// ID/app ID. It can have a suffix based on the type of push notification. If
58/// you’re using a certificate that supports PushKit VoIP or watchOS
59/// complication notifications, you must include this header with bundle ID of
60/// you app and if applicable, the proper suffix. If you’re using token-based
61/// authentication with APNs, you must include this header with the correct
62/// bundle ID and suffix combination. To learn more about app ID, see [Register
63/// an App ID](https://help.apple.com/developer-account/#/dev1b35d6f83).
64pub static APNS_TOPIC: HeaderName = HeaderName::from_static("apns-topic");
65
66/// An identifier you use to coalesce multiple notifications into a single
67/// notification for the user. Typically, each notification request causes a new
68/// notification to be displayed on the user’s device. When sending the same
69/// notification more than once, use the same value in this header to coalesce
70/// the requests. The value of this key must not exceed 64 bytes.
71pub static APNS_COLLAPSE_ID: HeaderName = HeaderName::from_static("apns-collapse-id");
72
73/// Use the `alert` push type for notifications that trigger a user
74/// interaction—for example, an alert, badge, or sound. If you set this push
75/// type, the `apns-topic` header field must use your app’s bundle ID as the
76/// topic. For more information, see [Generating a remote
77/// notification](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/generating_a_remote_notification).
78///
79/// If the notification requires immediate action from the user, set
80/// notification priority to 10; otherwise use 5.
81///
82/// The `alert` push type is required on watchOS 6 and later. It is recommended
83/// on macOS, iOS, tvOS, and iPadOS.
84pub static ALERT: HeaderValue = HeaderValue::from_static("alert");
85
86/// Use the `background` push type for notifications that deliver content in the
87/// background, and don’t trigger any user interactions. If you set this push
88/// type, the `apns-topic header` field must use your app’s bundle ID as the
89/// topic. Always use priority 5. Using priority 10 is an error. For more
90/// information, see [Pushing Background Updates to Your
91/// App](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/pushing_background_updates_to_your_app).
92///
93/// The `background` push type is required on watchOS 6 and later. It is
94/// recommended on macOS, iOS, tvOS, and iPadOS.
95pub static BACKGROUND: HeaderValue = HeaderValue::from_static("background");
96
97/// Use the `location` push type for notifications that request a user’s
98/// location. If you set this push type, the `apns-topic` header field must use
99/// your app’s bundle ID with `.location-query` appended to the end. For more
100/// information, see Creating a location push service extension.
101///
102/// The `location` push type is recommended for iOS and iPadOS. It isn’t
103/// available on macOS, tvOS, and watchOS.
104///
105/// If the location query requires an immediate response from the Location Push
106/// Service Extension, set notification `apns-priority` to 10; otherwise, use 5.
107///
108/// The `location` push type supports only token-based authentication.
109pub static LOCATION: HeaderValue = HeaderValue::from_static("location");
110
111/// Use the `voip` push type for notifications that provide information about an
112/// incoming Voice-over-IP (VoIP) call. For more information, see [Responding to
113/// VoIP Notifications from
114/// PushKit](https://developer.apple.com/documentation/pushkit/responding_to_voip_notifications_from_pushkit).
115///
116/// If you set this push type, the apns-topic header field must use your app’s
117/// bundle ID with `.voip` appended to the end. If you’re using
118/// certificate-based authentication, you must also register the certificate for
119/// VoIP services. The topic is then part of the 1.2.840.113635.100.6.3.4 or
120/// 1.2.840.113635.100.6.3.6 extension.
121///
122/// The `voip` push type is not available on watchOS. It is recommended on
123/// macOS, iOS, tvOS, and iPadOS.
124pub static VOIP: HeaderValue = HeaderValue::from_static("voip");
125
126/// Use the `complication` push type for notifications that contain update
127/// information for a watchOS app’s complications. For more information, see
128/// Keeping Your Complications Up to Date.
129///
130/// If you set this push type, the `apns-topic` header field must use your app’s
131/// bundle ID with `.complication` appended to the end. If you’re using
132/// certificate-based authentication, you must also register the certificate for
133/// WatchKit services. The topic is then part of the 1.2.840.113635.100.6.3.6
134/// extension.
135///
136/// The `complication` push type is recommended for watchOS and iOS. It is not
137/// available on macOS, tvOS, and iPadOS.
138pub static COMPLICATION: HeaderValue = HeaderValue::from_static("complication");
139
140/// Use the `fileprovider` push type to signal changes to a File Provider
141/// extension. If you set this push type, the `apns-topic` header field must use
142/// your app’s bundle ID with `.pushkit.fileprovider` appended to the end. For
143/// more information, see Using push notifications to signal changes.
144///
145/// The `fileprovider` push type is not available on watchOS. It is recommended
146/// on macOS, iOS, tvOS, and iPadOS.
147pub static FILEPROVIDER: HeaderValue = HeaderValue::from_static("fileprovider");
148
149/// Use the `mdm` push type for notifications that tell managed devices to
150/// contact the MDM server. If you set this push type, you must use the topic
151/// from the UID attribute in the subject of your MDM push certificate. For more
152/// information, see [Device
153/// Management](https://developer.apple.com/documentation/devicemanagement).
154///
155/// The mdm push type is not available on watchOS. It is recommended on macOS,
156/// iOS, tvOS, and iPadOS.
157pub static MDM: HeaderValue = HeaderValue::from_static("mdm");
158
159/// Send the notification immediately.
160pub static PRIORITY_IMMEDIATE: HeaderValue = HeaderValue::from_static("10");
161
162/// Send the notification based on power considerations on the user’s device
163pub static PRIORITY_CONSIDER_POWER: HeaderValue = HeaderValue::from_static("5");
164
165/// Prioritize the device’s power considerations over all other factors for
166/// delivery, and prevent awakening the device.
167pub static PRIORITY_PRIORITIZE_POWER: HeaderValue = HeaderValue::from_static("1");
168
169/// The `apns-push-type` header field has the following valid values. The
170/// descriptions below describe when and how to use these values.
171#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)]
172#[serde(rename_all = "kebab-case")]
173pub enum PushType {
174 /// Use the `alert` push type for notifications that trigger a user
175 /// interaction—for example, an alert, badge, or sound. If you set this push
176 /// type, the `apns-topic` header field must use your app’s bundle ID as the
177 /// topic. For more information, see [Generating a remote
178 /// notification](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/generating_a_remote_notification).
179 ///
180 /// If the notification requires immediate action from the user, set
181 /// notification priority to 10; otherwise use 5.
182 ///
183 /// The `alert` push type is required on watchOS 6 and later. It is
184 /// recommended on macOS, iOS, tvOS, and iPadOS.
185 Alert,
186
187 /// Use the `background` push type for notifications that deliver content in
188 /// the background, and don’t trigger any user interactions. If you set this
189 /// push type, the `apns-topic header` field must use your app’s bundle ID
190 /// as the topic. Always use priority 5. Using priority 10 is an error. For
191 /// more information, see [Pushing Background Updates to Your
192 /// App](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/pushing_background_updates_to_your_app).
193 ///
194 /// The `background` push type is required on watchOS 6 and later. It is
195 /// recommended on macOS, iOS, tvOS, and iPadOS.
196 Background,
197
198 /// Use the `location` push type for notifications that request a user’s
199 /// location. If you set this push type, the `apns-topic` header field must
200 /// use your app’s bundle ID with `.location-query` appended to the end. For
201 /// more information, see Creating a location push service extension.
202 ///
203 /// The `location` push type is recommended for iOS and iPadOS. It isn’t
204 /// available on macOS, tvOS, and watchOS.
205 ///
206 /// If the location query requires an immediate response from the Location
207 /// Push Service Extension, set notification `apns-priority` to 10;
208 /// otherwise, use 5.
209 ///
210 /// The location push type supports only token-based authentication.
211 Location,
212
213 /// Use the `voip` push type for notifications that provide information
214 /// about an incoming Voice-over-IP (VoIP) call. For more information, see
215 /// [Responding to VoIP Notifications from
216 /// PushKit](https://developer.apple.com/documentation/pushkit/responding_to_voip_notifications_from_pushkit).
217 ///
218 /// If you set this push type, the apns-topic header field must use your
219 /// app’s bundle ID with `.voip` appended to the end. If you’re using
220 /// certificate-based authentication, you must also register the certificate
221 /// for VoIP services. The topic is then part of the
222 /// 1.2.840.113635.100.6.3.4 or 1.2.840.113635.100.6.3.6 extension.
223 ///
224 /// The voip push type is not available on watchOS. It is recommended on
225 /// macOS, iOS, tvOS, and iPadOS.
226 Voip,
227
228 /// Use the `complication` push type for notifications that contain update
229 /// information for a watchOS app’s complications. For more information, see
230 /// Keeping Your Complications Up to Date.
231 ///
232 /// If you set this push type, the `apns-topic` header field must use your
233 /// app’s bundle ID with `.complication` appended to the end. If you’re
234 /// using certificate-based authentication, you must also register the
235 /// certificate for WatchKit services. The topic is then part of the
236 /// 1.2.840.113635.100.6.3.6 extension.
237 ///
238 /// The `complication` push type is recommended for watchOS and iOS. It is
239 /// not available on macOS, tvOS, and iPadOS.
240 Complication,
241
242 /// Use the `fileprovider` push type to signal changes to a File Provider
243 /// extension. If you set this push type, the `apns-topic` header field must
244 /// use your app’s bundle ID with `.pushkit.fileprovider` appended to the
245 /// end. For more information, see Using push notifications to signal
246 /// changes.
247 ///
248 /// The `fileprovider` push type is not available on watchOS. It is
249 /// recommended on macOS, iOS, tvOS, and iPadOS.
250 Fileprovider,
251
252 /// Use the `mdm` push type for notifications that tell managed devices to
253 /// contact the MDM server. If you set this push type, you must use the
254 /// topic from the UID attribute in the subject of your MDM push
255 /// certificate. For more information, see [Device
256 /// Management](https://developer.apple.com/documentation/devicemanagement).
257 ///
258 /// The mdm push type is not available on watchOS. It is recommended on
259 /// macOS, iOS, tvOS, and iPadOS.
260 Mdm,
261}
262
263impl Default for PushType {
264 fn default() -> Self {
265 Self::Alert
266 }
267}
268
269impl From<PushType> for HeaderValue {
270 fn from(apns_push_type: PushType) -> Self {
271 match apns_push_type {
272 PushType::Alert => ALERT.clone(),
273 PushType::Background => BACKGROUND.clone(),
274 PushType::Location => LOCATION.clone(),
275 PushType::Voip => VOIP.clone(),
276 PushType::Complication => COMPLICATION.clone(),
277 PushType::Fileprovider => FILEPROVIDER.clone(),
278 PushType::Mdm => MDM.clone(),
279 }
280 }
281}
282
283derive_fromstr_from_deserialize!(PushType);
284derive_display_from_serialize!(PushType);
285
286impl PushType {
287 pub fn payload_size_limit(&self) -> usize {
288 if *self == PushType::Voip {
289 VOIP_PAYLOAD_SIZE_LIMIT
290 } else {
291 PAYLOAD_SIZE_LIMIT
292 }
293 }
294}
295
296/// Push notification priority.
297#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize_repr, Serialize_repr)]
298#[repr(u8)]
299pub enum Priority {
300 /// Send the notification immediately.
301 Immediate = 10,
302
303 /// Send the notification based on power considerations on the user’s device
304 ConsiderPower = 5,
305
306 /// Prioritize the device’s power considerations over all other factors for
307 /// delivery, and prevent awakening the device.
308 PrioritizePower = 1,
309}
310
311impl Default for Priority {
312 fn default() -> Self {
313 Self::Immediate
314 }
315}
316
317impl From<Priority> for HeaderValue {
318 fn from(this: Priority) -> Self {
319 match this {
320 Priority::Immediate => PRIORITY_IMMEDIATE.clone(),
321 Priority::ConsiderPower => PRIORITY_CONSIDER_POWER.clone(),
322 Priority::PrioritizePower => PRIORITY_PRIORITIZE_POWER.clone(),
323 }
324 }
325}
326
327derive_fromstr_from_deserialize!(Priority);
328derive_display_from_serialize!(Priority);