From a4b815eb01d9d17401deafa1e9f10eee284b0f0b Mon Sep 17 00:00:00 2001 From: Ross Savage <551697+dangeross@users.noreply.github.com> Date: Sat, 24 May 2025 05:18:24 +0000 Subject: [PATCH] Notification Plugin: Add Cache-Control header for responses (#902) * Add Cache-Control header for lnurlpay_info response * Add Cache-Control header for lnurlpay_verify response * Add max age constants --- .../main/kotlin/breez_sdk_liquid_notification/Constants.kt | 4 ++++ .../src/main/kotlin/breez_sdk_liquid_notification/job/Job.kt | 4 ++++ .../kotlin/breez_sdk_liquid_notification/job/LnurlPayInfo.kt | 3 ++- .../breez_sdk_liquid_notification/job/LnurlPayVerify.kt | 4 +++- .../langs/swift/Sources/BreezSDKLiquid/Constants.swift | 4 ++++ .../swift/Sources/BreezSDKLiquid/Task/LnurlPayInfo.swift | 2 +- .../swift/Sources/BreezSDKLiquid/Task/LnurlPayVerify.swift | 3 ++- .../langs/swift/Sources/BreezSDKLiquid/TaskProtocol.swift | 5 ++++- 8 files changed, 24 insertions(+), 5 deletions(-) diff --git a/lib/bindings/langs/android/lib/src/main/kotlin/breez_sdk_liquid_notification/Constants.kt b/lib/bindings/langs/android/lib/src/main/kotlin/breez_sdk_liquid_notification/Constants.kt index 45587ef..b17fd57 100644 --- a/lib/bindings/langs/android/lib/src/main/kotlin/breez_sdk_liquid_notification/Constants.kt +++ b/lib/bindings/langs/android/lib/src/main/kotlin/breez_sdk_liquid_notification/Constants.kt @@ -4,6 +4,10 @@ object Constants { const val SERVICE_TIMEOUT_MS = 3 * 60 * 1000L const val SHUTDOWN_DELAY_MS = 60 * 1000L + // Cache Control + const val CACHE_CONTROL_MAX_AGE_DAY = 60 * 60 * 24 + const val CACHE_CONTROL_MAX_AGE_WEEK = 60 * 60 * 24 * 7 + // Notification Channels const val NOTIFICATION_CHANNEL_DISMISSIBLE = "DISMISSIBLE" const val NOTIFICATION_CHANNEL_FOREGROUND_SERVICE = "FOREGROUND_SERVICE" diff --git a/lib/bindings/langs/android/lib/src/main/kotlin/breez_sdk_liquid_notification/job/Job.kt b/lib/bindings/langs/android/lib/src/main/kotlin/breez_sdk_liquid_notification/job/Job.kt index fd6e265..bbe5917 100644 --- a/lib/bindings/langs/android/lib/src/main/kotlin/breez_sdk_liquid_notification/job/Job.kt +++ b/lib/bindings/langs/android/lib/src/main/kotlin/breez_sdk_liquid_notification/job/Job.kt @@ -21,6 +21,7 @@ interface Job : EventListener { fun replyServer( payload: String, replyURL: String, + maxAge: Int = 0, ): Boolean { val url = URL(replyURL) val response = payload.toByteArray() @@ -31,6 +32,9 @@ interface Job : EventListener { useCaches = false setRequestProperty("Content-Type", "application/json") setRequestProperty("Content-Length", response.size.toString()) + if (maxAge > 0) { + setRequestProperty("Cache-Control", "max-age=$maxAge") + } DataOutputStream(outputStream).use { it.write(response, 0, response.size) } return responseCode == 200 diff --git a/lib/bindings/langs/android/lib/src/main/kotlin/breez_sdk_liquid_notification/job/LnurlPayInfo.kt b/lib/bindings/langs/android/lib/src/main/kotlin/breez_sdk_liquid_notification/job/LnurlPayInfo.kt index 0b3bec3..499a11d 100644 --- a/lib/bindings/langs/android/lib/src/main/kotlin/breez_sdk_liquid_notification/job/LnurlPayInfo.kt +++ b/lib/bindings/langs/android/lib/src/main/kotlin/breez_sdk_liquid_notification/job/LnurlPayInfo.kt @@ -2,6 +2,7 @@ package breez_sdk_liquid_notification.job import android.content.Context import breez_sdk_liquid.BindingLiquidSdk +import breez_sdk_liquid_notification.Constants.CACHE_CONTROL_MAX_AGE_DAY import breez_sdk_liquid_notification.Constants.DEFAULT_LNURL_PAY_INFO_NOTIFICATION_TITLE import breez_sdk_liquid_notification.Constants.DEFAULT_LNURL_PAY_METADATA_PLAIN_TEXT import breez_sdk_liquid_notification.Constants.DEFAULT_LNURL_PAY_NOTIFICATION_FAILURE_TITLE @@ -74,7 +75,7 @@ class LnurlPayInfoJob( "[[\"text/plain\",\"$plainTextMetadata\"]]", "payRequest", ) - val success = replyServer(Json.encodeToString(response), request.replyURL) + val success = replyServer(Json.encodeToString(response), request.replyURL, CACHE_CONTROL_MAX_AGE_DAY) notifyChannel( context, NOTIFICATION_CHANNEL_REPLACEABLE, diff --git a/lib/bindings/langs/android/lib/src/main/kotlin/breez_sdk_liquid_notification/job/LnurlPayVerify.kt b/lib/bindings/langs/android/lib/src/main/kotlin/breez_sdk_liquid_notification/job/LnurlPayVerify.kt index c1e6c43..ea903c7 100644 --- a/lib/bindings/langs/android/lib/src/main/kotlin/breez_sdk_liquid_notification/job/LnurlPayVerify.kt +++ b/lib/bindings/langs/android/lib/src/main/kotlin/breez_sdk_liquid_notification/job/LnurlPayVerify.kt @@ -5,6 +5,7 @@ import breez_sdk_liquid.BindingLiquidSdk import breez_sdk_liquid.GetPaymentRequest import breez_sdk_liquid.PaymentDetails import breez_sdk_liquid.PaymentState +import breez_sdk_liquid_notification.Constants.CACHE_CONTROL_MAX_AGE_WEEK import breez_sdk_liquid_notification.Constants.DEFAULT_LNURL_PAY_VERIFY_NOTIFICATION_TITLE import breez_sdk_liquid_notification.Constants.DEFAULT_LNURL_PAY_VERIFY_NOTIFICATION_FAILURE_TITLE import breez_sdk_liquid_notification.Constants.LNURL_PAY_VERIFY_NOTIFICATION_TITLE @@ -75,7 +76,8 @@ class LnurlPayVerifyJob( throw InvalidLnurlPayException("Not found") } - val success = replyServer(Json.encodeToString(response), request.replyURL) + val maxAge = if (response.settled) CACHE_CONTROL_MAX_AGE_WEEK else 0 + val success = replyServer(Json.encodeToString(response), request.replyURL, maxAge) notifyChannel( context, NOTIFICATION_CHANNEL_REPLACEABLE, diff --git a/lib/bindings/langs/swift/Sources/BreezSDKLiquid/Constants.swift b/lib/bindings/langs/swift/Sources/BreezSDKLiquid/Constants.swift index fc99e51..725ed10 100644 --- a/lib/bindings/langs/swift/Sources/BreezSDKLiquid/Constants.swift +++ b/lib/bindings/langs/swift/Sources/BreezSDKLiquid/Constants.swift @@ -1,6 +1,10 @@ import Foundation struct Constants { + // Cache Control + static let CACHE_CONTROL_MAX_AGE_DAY = 60 * 60 * 24 + static let CACHE_CONTROL_MAX_AGE_WEEK = 60 * 60 * 24 * 7 + // Notification Threads static let NOTIFICATION_THREAD_DISMISSIBLE = "DISMISSIBLE" static let NOTIFICATION_THREAD_REPLACEABLE = "REPLACEABLE" diff --git a/lib/bindings/langs/swift/Sources/BreezSDKLiquid/Task/LnurlPayInfo.swift b/lib/bindings/langs/swift/Sources/BreezSDKLiquid/Task/LnurlPayInfo.swift index 3cb9698..d83f7d8 100644 --- a/lib/bindings/langs/swift/Sources/BreezSDKLiquid/Task/LnurlPayInfo.swift +++ b/lib/bindings/langs/swift/Sources/BreezSDKLiquid/Task/LnurlPayInfo.swift @@ -55,7 +55,7 @@ class LnurlPayInfoTask : LnurlPayTask { let plainTextMetadata = ResourceHelper.shared.getString(key: Constants.LNURL_PAY_METADATA_PLAIN_TEXT, fallback: Constants.DEFAULT_LNURL_PAY_METADATA_PLAIN_TEXT) let metadata = "[[\"text/plain\",\"\(plainTextMetadata)\"]]" replyServer(encodable: LnurlInfoResponse(callback: request!.callback_url, maxSendable: maxSendableMsat, minSendable: minSendableMsat, metadata: metadata, tag: "payRequest"), - replyURL: request!.reply_url) + replyURL: request!.reply_url, maxAge: Constants.CACHE_CONTROL_MAX_AGE_DAY) } catch let e { self.logger.log(tag: TAG, line: "failed to process lnurl: \(e)", level: "ERROR") fail(withError: e.localizedDescription, replyURL: request!.reply_url) diff --git a/lib/bindings/langs/swift/Sources/BreezSDKLiquid/Task/LnurlPayVerify.swift b/lib/bindings/langs/swift/Sources/BreezSDKLiquid/Task/LnurlPayVerify.swift index bda68d8..b997e4f 100644 --- a/lib/bindings/langs/swift/Sources/BreezSDKLiquid/Task/LnurlPayVerify.swift +++ b/lib/bindings/langs/swift/Sources/BreezSDKLiquid/Task/LnurlPayVerify.swift @@ -64,7 +64,8 @@ class LnurlPayVerifyTask : LnurlPayTask { if response == nil { throw InvalidLnurlPayError.notFound } - replyServer(encodable: response, replyURL: request!.reply_url) + let maxAge = response!.settled ? Constants.CACHE_CONTROL_MAX_AGE_WEEK : 0 + replyServer(encodable: response, replyURL: request!.reply_url, maxAge: maxAge) } catch let e { self.logger.log(tag: TAG, line: "failed to process lnurl verify: \(e)", level: "ERROR") fail(withError: e.localizedDescription, replyURL: request!.reply_url) diff --git a/lib/bindings/langs/swift/Sources/BreezSDKLiquid/TaskProtocol.swift b/lib/bindings/langs/swift/Sources/BreezSDKLiquid/TaskProtocol.swift index c197adf..974cb97 100644 --- a/lib/bindings/langs/swift/Sources/BreezSDKLiquid/TaskProtocol.swift +++ b/lib/bindings/langs/swift/Sources/BreezSDKLiquid/TaskProtocol.swift @@ -85,12 +85,15 @@ class ReplyableTask : TaskProtocol { displayPushNotification(title: self.failNotificationTitle, logger: self.logger, threadIdentifier: Constants.NOTIFICATION_THREAD_REPLACEABLE) } - func replyServer(encodable: Encodable, replyURL: String) { + func replyServer(encodable: Encodable, replyURL: String, maxAge: Int = 0) { guard let serverReplyURL = URL(string: replyURL) else { self.displayPushNotification(title: self.failNotificationTitle, logger: self.logger, threadIdentifier: Constants.NOTIFICATION_THREAD_REPLACEABLE) return } var request = URLRequest(url: serverReplyURL) + if maxAge > 0 { + request.setValue("max-age=\(maxAge)", forHTTPHeaderField: "Cache-Control") + } request.httpMethod = "POST" let encoder = JSONEncoder() encoder.outputFormatting = .withoutEscapingSlashes