webpush
Sending notifications to browsers from a server, with VAPID keys and the standard encryption.
import webpush
A web push notification is a message a server sends to a user's browser even when the site is not open. The flow: make a key pair once with GenerateKeys, use the public key in the page JavaScript to subscribe, store the subscription the browser makes on your server, and send messages with Send.
The message is encrypted under RFC 8291 before it is sent, so the browser push service never sees its contents. When the result says gone, the user has cancelled the subscription.
Types
Keys
struct Keys| Name | Type | Description |
|---|---|---|
public_key | str = "" | The public key as url safe base64; this is what you give to applicationServerKey in the page JavaScript. |
private_key | str = "" | The private key; keep it secret. |
ok | bool = false | The keys are valid. |
import webpush
import str
func main:
fresh := webpush.GenerateKeys()
println fresh.ok, fresh.public_key.len(), fresh.private_key.len()
k := webpush.KeysFrom("BLmOwafYGSjiuCX_1RSCO_n0YmacxYMDqitMydKE4A1Wp2qmUuMXg2IM_hzcrmZLun4jEu_lKfVdtnAp0LMK4NE", "Nhh4m4Va4yhL-53i302044iqeAeMtnOEYlIT2KWRJmg")
println k.ok, webpush.KeysFrom("", "").ok
at := webpush.VapidHeaderAt(k, "https://fcm.googleapis.com", "mailto:ali@example.com", 1700000000)
println at
now := webpush.VapidHeader(k, "https://fcm.googleapis.com", "mailto:ali@example.com")
println str.StartsWith(now, "vapid t="), str.Contains(now, ", k=" + k.public_key)
mut o := webpush.NewOptions("mailto:ali@example.com")
println o.subject, o.ttl == webpush.DEFAULT_TTL, o.ttl / 86400
o.urgency = "high"
o.topic = "news"
o.ttl = 3600
println o.urgency, o.topic, o.ttl
endSubscription
struct SubscriptionpushManager.subscribe and sends to your server.| Name | Type | Description |
|---|---|---|
endpoint | str = "" | The address of the browser push service. |
p256dh | str = "" | The public key of the browser, from the keys part of the subscription. |
auth | str = "" | The authentication secret, from the same part. |
import webpush
func main:
sub := webpush.Subscription {
endpoint = "https://push.example.net/x",
p256dh = "BCVxsr7N_eNgVRqvHtD0zTZsEc6-VV-JvLexhqUzORcxaOzi6-AYWXvTBHm4bjyPjs7Vd8pZGH6SRpkNtoIAiw4",
auth = "BTBZMqHH6r4Tts7J_aSIgg"
}
mut good := false
body := webpush.EncryptWith(sub, "When I grow up, I want to be a watermelon", "yfWPiYE-n46HLnH0KqZOF1fJJU3MYrct3AELtAQ-oRw", "DGv6ra1nlYgDCS1FRnbzlw", good)
println good
println body
one := webpush.Encrypt(sub, "hello", good)
two := webpush.Encrypt(sub, "hello", good)
println good, one != two, one.len() == two.len()
endOptions
struct Options| Name | Type | Description |
|---|---|---|
subject | str = "" | Your contact address, as a mailto: or a web address; the services require it. |
ttl | int = 2419200 | How many seconds the service should hold the message for a browser that is off. |
urgency | str = "" | The urgency: very-low, low, normal or high. |
topic | str = "" | The topic; a new message with the same topic replaces an earlier undelivered one. |
The example for this item is shown with the ones above: webpush-Keys.salam
Result
struct Result| Name | Type | Description |
|---|---|---|
ok | bool = false | The service accepted the message. |
status | int = 0 | The HTTP status code of the service. |
gone | bool = false | The subscription is no longer valid (404 or 410); delete it from your database. |
error | str = "" | The error message. |
import webpush
func main:
k := webpush.KeysFrom("BLmOwafYGSjiuCX_1RSCO_n0YmacxYMDqitMydKE4A1Wp2qmUuMXg2IM_hzcrmZLun4jEu_lKfVdtnAp0LMK4NE", "Nhh4m4Va4yhL-53i302044iqeAeMtnOEYlIT2KWRJmg")
sub := webpush.Subscription {
endpoint = "https://fcm.googleapis.com/fcm/send/abc",
p256dh = "BCVxsr7N_eNgVRqvHtD0zTZsEc6-VV-JvLexhqUzORcxaOzi6-AYWXvTBHm4bjyPjs7Vd8pZGH6SRpkNtoIAiw4",
auth = "BTBZMqHH6r4Tts7J_aSIgg"
}
o := webpush.NewOptions("mailto:ali@example.com")
r := webpush.Send(k, sub, `{"title":"hello","body":"you have a new message"}`, o)
if r.ok:
println "sent", r.status
else r.gone:
println "the subscription has expired; delete it"
else:
println "error:", r.status, r.error
end
endConstants and variables
DEFAULT_TTL
const DEFAULT_TTL: i32 = 2419200The example for this item is shown with the ones above: webpush-Keys.salam
Functions
GenerateKeys
func GenerateKeys(): KeysThe example for this item is shown with the ones above: webpush-Keys.salam
VapidHeaderAt
func VapidHeaderAt(keys: Keys, audience: str, subject: str, epoch_seconds: i64): strAuthorization header for the service at the given address, at the given time in Unix seconds. The signature is deterministic, so the same input gives the same output.The example for this item is shown with the ones above: webpush-Keys.salam
VapidHeader
func VapidHeader(keys: Keys, audience: str, subject: str): strThe example for this item is shown with the ones above: webpush-Keys.salam
EncryptWith
func EncryptWith(sub: Subscription, payload: str, as_private: str, salt: str, ok &: bool): strEncrypt.The example for this item is shown with the ones above: webpush-Encrypt.salam
Encrypt
func Encrypt(sub: Subscription, payload: str, ok &: bool): strThe example for this item is shown with the ones above: webpush-Encrypt.salam
Send
func Send(keys: Keys, sub: Subscription, payload: str, opts: Options): ResultThe example for this item is shown with the ones above: webpush-Send.salam
NewOptions
func NewOptions(subject: str): OptionsThe example for this item is shown with the ones above: webpush-Keys.salam
KeysFrom
func KeysFrom(public_key: str, private_key: str): Keysok is false when either one is empty.The example for this item is shown with the ones above: webpush-Keys.salam