Skip to content

Commit 3be05cd

Browse files
Return the apns-unique-id header in APNSResponse (#198)
Added support for returning the apns-unique-id header from responses
1 parent c5b6aaf commit 3be05cd

File tree

4 files changed

+30
-3
lines changed

4 files changed

+30
-3
lines changed

Sources/APNS/APNSClient.swift

+3-1
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,10 @@ extension APNSClient {
192192
let response = try await self.httpClient.execute(httpClientRequest, deadline: .distantFuture)
193193

194194
let apnsID = response.headers.first(name: "apns-id").flatMap { UUID(uuidString: $0) }
195+
let apnsUniqueID = response.headers.first(name: "apns-unique-id").flatMap { UUID(uuidString: $0) }
195196

196197
if response.status == .ok {
197-
return APNSResponse(apnsID: apnsID)
198+
return APNSResponse(apnsID: apnsID, apnsUniqueID: apnsUniqueID)
198199
}
199200

200201
let body = try await response.body.collect(upTo: 1024)
@@ -203,6 +204,7 @@ extension APNSClient {
203204
let error = APNSError(
204205
responseStatus: Int(response.status.code),
205206
apnsID: apnsID,
207+
apnsUniqueID: apnsUniqueID,
206208
apnsResponse: errorResponse,
207209
timestamp: errorResponse.timestampInSeconds.flatMap { Date(timeIntervalSince1970: $0) }
208210
)

Sources/APNSCore/APNSError.swift

+9
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,11 @@ public struct APNSError: Error {
393393
/// Use this value to identify the notification. If you don’t specify an `apnsID` in your request,
394394
/// APNs creates a new `UUID` and returns it in this header.
395395
public let apnsID: UUID?
396+
397+
/// A unique ID for the notification used for development, as determined by the APNs servers.
398+
///
399+
/// In the development or sandbox environement, this value can be used to look up information about notifications on the [Push Notifications Console](https://icloud.developer.apple.com/dashboard/notifications). This value is not provided in the production environement.
400+
public var apnsUniqueID: UUID?
396401

397402
/// The error code indicating the reason for the failure.
398403
public let reason: ErrorReason?
@@ -405,11 +410,13 @@ public struct APNSError: Error {
405410
public init(
406411
responseStatus: Int,
407412
apnsID: UUID? = nil,
413+
apnsUniqueID: UUID? = nil,
408414
apnsResponse: APNSErrorResponse? = nil,
409415
timestamp: Date? = nil
410416
) {
411417
self.responseStatus = responseStatus
412418
self.apnsID = apnsID
419+
self.apnsUniqueID = apnsUniqueID
413420
if let apnsResponse {
414421
self.reason = .init(_reason: .init(rawValue: apnsResponse.reason))
415422
} else {
@@ -425,13 +432,15 @@ extension APNSError: Hashable {
425432
return
426433
lhs.responseStatus == rhs.responseStatus &&
427434
lhs.apnsID == rhs.apnsID &&
435+
lhs.apnsUniqueID == rhs.apnsUniqueID &&
428436
lhs.reason == rhs.reason &&
429437
lhs.timestamp == rhs.timestamp
430438
}
431439

432440
public func hash(into hasher: inout Hasher) {
433441
hasher.combine(self.responseStatus)
434442
hasher.combine(self.apnsID)
443+
hasher.combine(self.apnsUniqueID)
435444
hasher.combine(self.reason)
436445
hasher.combine(self.timestamp)
437446
}

Sources/APNSCore/APNSResponse.swift

+15-1
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,25 @@ public struct APNSResponse: Hashable {
2121
/// Use this value to identify the notification. If you don’t specify an `apnsID` in your request,
2222
/// APNs creates a new `UUID` and returns it in this header.
2323
public var apnsID: UUID?
24+
25+
/// A unique ID for the notification used for development, as determined by the APNs servers.
26+
///
27+
/// In the development or sandbox environement, this value can be used to look up information about notifications on the [Push Notifications Console](https://icloud.developer.apple.com/dashboard/notifications). This value is not provided in the production environement.
28+
public var apnsUniqueID: UUID?
2429

2530
/// Initializes a new ``APNSResponse``.
2631
///
2732
/// - Parameter apnsID: The same value as the `apnsID` send in the request.
28-
public init(apnsID: UUID? = nil) {
33+
/// - Parameter apnsUniqueID: A unique ID for the notification used only in the development environment.
34+
public init(apnsID: UUID? = nil, apnsUniqueID: UUID? = nil) {
2935
self.apnsID = apnsID
36+
self.apnsUniqueID = apnsUniqueID
37+
}
38+
}
39+
40+
/// The [Push Notifications Console](https://icloud.developer.apple.com/dashboard/notifications) expects IDs to be lowercased, so prep them ahead of time here to make it easier for users to copy and paste these IDs.
41+
extension APNSResponse: CustomStringConvertible {
42+
public var description: String {
43+
"APNSResponse(apns-id: \(apnsID?.uuidString.lowercased() ?? "nil"), apns-unique-id: \(apnsUniqueID?.uuidString.lowercased() ?? "nil"))"
3044
}
3145
}

Sources/APNSURLSession/APNSUrlSessionClient.swift

+3-1
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,21 @@ public struct APNSURLSessionClient: APNSClientProtocol {
4444
}
4545

4646
let apnsID = UUID(uuidString: apnsIDString)
47+
let apnsUniqueID = (response.allHeaderFields["apns-unique-id"] as? String).flatMap { UUID(uuidString: $0) }
4748

4849
/// Detect an error
4950
if let errorResponse = try? decoder.decode(APNSErrorResponse.self, from: data) {
5051
let error = APNSError(
5152
responseStatus: response.statusCode,
5253
apnsID: apnsID,
54+
apnsUniqueID: apnsUniqueID,
5355
apnsResponse: errorResponse,
5456
timestamp: errorResponse.timestampInSeconds.flatMap { Date(timeIntervalSince1970: $0) }
5557
)
5658
throw error
5759
} else {
5860
/// Return APNSResponse
59-
return APNSResponse(apnsID: apnsID)
61+
return APNSResponse(apnsID: apnsID, apnsUniqueID: apnsUniqueID)
6062
}
6163
}
6264
}

0 commit comments

Comments
 (0)