Skip to content

Commit 22d0b12

Browse files
Added dedicated error for payloads that are too large
1 parent c18ac34 commit 22d0b12

File tree

3 files changed

+52
-1
lines changed

3 files changed

+52
-1
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//
2+
// MessageTooLargeError.swift
3+
// swift-webpush
4+
//
5+
// Created by Dimitri Bouniol on 2024-12-13.
6+
// Copyright © 2024 Mochi Development, Inc. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
/// The message was too large, and could not be delivered to the push service.
12+
///
13+
/// - SeeAlso: ``WebPushManager/maximumMessageSize``
14+
public struct MessageTooLargeError: LocalizedError, Hashable {
15+
public init() {}
16+
17+
public var errorDescription: String? {
18+
"The message was too large, and could not be delivered to the push service."
19+
}
20+
}

Sources/WebPush/WebPushManager.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,9 @@ public actor WebPushManager: Sendable {
494494
switch response.status {
495495
case .created: break
496496
case .notFound, .gone: throw BadSubscriberError()
497-
// TODO: 413 payload too large - log.error and throw error
497+
case .payloadTooLarge:
498+
logger.error("The encrypted payload was too large and was rejected by the push service.")
499+
throw MessageTooLargeError()
498500
// TODO: 429 too many requests, 500 internal server error, 503 server shutting down - check config and perform a retry after a delay?
499501
default: throw HTTPError(response: response)
500502
}

Tests/WebPushTests/WebPushManagerTests.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,35 @@ struct WebPushManagerTests {
508508
}
509509
}
510510

511+
@Test func sendExtraLargeMessageFails() async throws {
512+
await confirmation { requestWasMade in
513+
let vapidConfiguration = VAPID.Configuration.makeTesting()
514+
515+
let subscriberPrivateKey = P256.KeyAgreement.PrivateKey(compactRepresentable: false)
516+
var authenticationSecret: [UInt8] = Array(repeating: 0, count: 16)
517+
for index in authenticationSecret.indices { authenticationSecret[index] = .random(in: .min ... .max) }
518+
519+
let subscriber = Subscriber(
520+
endpoint: URL(string: "https://example.com/subscriber")!,
521+
userAgentKeyMaterial: UserAgentKeyMaterial(publicKey: subscriberPrivateKey.publicKey, authenticationSecret: Data(authenticationSecret)),
522+
vapidKeyID: vapidConfiguration.primaryKey!.id
523+
)
524+
525+
let manager = WebPushManager(
526+
vapidConfiguration: vapidConfiguration,
527+
backgroundActivityLogger: Logger(label: "WebPushManagerTests", factory: { PrintLogHandler(label: $0, metadataProvider: $1) }),
528+
executor: .httpClient(MockHTTPClient({ request in
529+
requestWasMade()
530+
return HTTPClientResponse(status: .payloadTooLarge)
531+
}))
532+
)
533+
534+
await #expect(throws: MessageTooLargeError()) {
535+
try await manager.send(data: Array(repeating: 0, count: 3994), to: subscriber)
536+
}
537+
}
538+
}
539+
511540
@Test func sendMessageToNotFoundPushServerError() async throws {
512541
await confirmation { requestWasMade in
513542
let vapidConfiguration = VAPID.Configuration.mockedConfiguration

0 commit comments

Comments
 (0)