Skip to content

marknefedov/go-webpush

Repository files navigation

go-webpush

Go Reference Ask DeepWiki GitHub release (latest SemVer) GitHub Workflow Status

Web Push API encryption and sending library for Go with VAPID support.

The client-based API sends encrypted Web Push notifications from a Go server to Push API subscriptions. It covers RFC 8188 / RFC 8291 payload encryption, RFC 8292 VAPID authentication, RFC 8030 delivery headers, multi-record payloads, send-side receipt metadata, and batch sending.

The library does not implement live receipt monitoring. It only supports requesting receipts and reusing returned receipt-subscription metadata.

Installation

go get github.com/marknefedov/go-webpush/v2

Quick start

  1. Generate VAPID keys once and store them securely.
package main

import (
	"os"

	webpush "github.com/marknefedov/go-webpush/v2"
)

func main() {
	keys, err := webpush.GenerateVAPIDKeys()
	if err != nil {
		panic(err)
	}
	pem, err := keys.ExportVAPIDPrivateKeyPEM()
	if err != nil {
		panic(err)
	}
	_ = os.WriteFile("vapid_private.pem", pem, 0o600)
}
  1. Create a reusable client and send a notification.
package main

import (
	"context"
	"encoding/json"
	"log"
	"net/http"
	"os"
	"time"

	webpush "github.com/marknefedov/go-webpush/v2"
)

func main() {
	var sub webpush.Subscription
	if err := json.Unmarshal([]byte(`{...}`), &sub); err != nil {
		log.Fatal(err)
	}

	keys, err := webpush.LoadVAPIDPrivateKeyPEM(mustRead("vapid_private.pem"))
	if err != nil {
		log.Fatal(err)
	}

	client := webpush.NewClient(webpush.Config{
		HTTPClient: &http.Client{Timeout: 10 * time.Second},
	})

	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	result, err := client.Send(ctx, []byte("Hello from Go!"), &sub, webpush.SendOptions{
		Subject:        "user@example.com",
		VAPIDKeys:      keys,
		TTL:            60,
		RequestReceipt: true,
	})
	if err != nil {
		log.Fatal(err)
	}
	defer result.Response.Body.Close()
	log.Println("push status:", result.StatusCode, "records:", result.RecordCount, "receipt:", result.ReceiptSubscription)
}

func mustRead(p string) []byte {
	b, _ := os.ReadFile(p)
	return b
}
  1. Send a no-payload notification when you only need a wake-up or receipt request.
result, err := client.Send(ctx, nil, &sub, webpush.SendOptions{
	Subject:             "user@example.com",
	VAPIDKeys:           keys,
	RequestReceipt:      true,
	ReceiptSubscription: "https://app.example/receipts",
})
if err != nil {
	log.Fatal(err)
}
log.Println("no payload:", result.NoPayload)
  1. Send the same payload to many subscriptions with batch helpers.
attempts := client.SendBatch(ctx, []byte("Hello everyone!"), subs, webpush.SendOptions{
	Subject:   "user@example.com",
	VAPIDKeys: keys,
	TTL:       60,
})
for _, attempt := range attempts {
	if attempt.Err != nil {
		log.Println("failed:", attempt.Subscription.Endpoint, attempt.Err)
		continue
	}
	log.Println("ok:", attempt.Subscription.Endpoint, attempt.Result.StatusCode)
}

Notes

  • SendNotification remains available as a thin compatibility wrapper, but the client API is the recommended entry point.
  • Topic, Urgency, and TTL are validated before a request is sent.
  • RequestReceipt and ReceiptSubscription only request and propagate receipt metadata. They do not enable live receipt monitoring.

Examples

The example/ directory contains a small CLI sender and service worker for the client API.

About

Web Push API Encryption with VAPID support.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors