use std::env; use axum::{ extract::{Json}, }; use web_push::{ SubscriptionInfo, VapidSignatureBuilder, WebPushMessageBuilder, ContentEncoding, WebPushClient, IsahcWebPushClient, }; pub async fn vapid() -> String { let vapid_public_key = env::var("VAPID_PUBLIC_KEY").unwrap_or_default(); String::from(vapid_public_key) } pub async fn register() -> String { String::from("OK") } pub async fn unregister() -> String { String::from("OK") } #[axum::debug_handler] pub async fn echo( Json(echo): Json, ) -> Result<(), crate::error::Internal> { // Look this up from a subscription record? Or get it from the client and trust? let endpoint = echo.endpoint; // Get these from client: let p256dh = echo.keys.p256dh; let auth = echo.keys.auth; println!("endpoint: {:?}", endpoint); println!("p256dh: {:?}", p256dh); println!("auth: {:?}", auth); // You would likely get this by deserializing a browser `pushSubscription` object. let subscription_info = SubscriptionInfo::new(endpoint, p256dh, auth); // This will need to come from the DB eventually. let private_key = String::from(env::var("VAPID_PRIVATE_KEY").unwrap_or_default()); let sig_builder = VapidSignatureBuilder::from_base64(&private_key, &subscription_info)?.build()?; // Now add payload and encrypt. let mut builder = WebPushMessageBuilder::new(&subscription_info); // Eventually, this message will be something other than an echo: let content = echo.msg.as_bytes(); builder.set_payload(ContentEncoding::Aes128Gcm, content); builder.set_vapid_signature(sig_builder); let client = IsahcWebPushClient::new()?; // Finally, send the notification! client.send(builder.build()?).await?; // Fix up return type? Ok(()) } #[derive(serde::Deserialize)] pub struct Keys { pub p256dh: String, pub auth: String, } #[derive(serde::Deserialize)] pub struct Echo { pub msg: String, pub endpoint: String, pub expirationTime: Option, pub keys: Keys, }