webpush

package
v0.4.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 7, 2026 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Overview

Package webpush delivers push messages to a PushSubscription URL: message encryption per RFC 8291 and HTTP delivery per RFC 8030 section 5, with server-side request forgery protection required by RFC 8620 section 8.6. It is the sending half of Web Push only - the JMAP server acts as an RFC 8030 "application server"; the push service and user agent are someone else's.

Index

Constants

View Source
const (
	MaxPlaintext = maxPayload - headerLen - 1 - 16
)

Encryption constants fixed by RFC 8291 section 4 and RFC 8030 section 7.2: a push service need not accept more than 4096 octets of payload, the aes128gcm header for a P-256 key is 86 octets, the padding delimiter is 1, and the AEAD tag is 16.

Variables

View Source
var (
	// ErrKeys means the subscription's p256dh or auth values are not
	// valid RFC 8291 key material.
	ErrKeys = errors.New("webpush: invalid subscription keys")
	// ErrTooLarge means the plaintext exceeds MaxPlaintext.
	ErrTooLarge = errors.New("webpush: plaintext exceeds the RFC 8030 payload limit")
)
View Source
var ErrPrivateHost = errors.New("webpush: subscription URL resolves to a private or local address")

ErrPrivateHost means the subscription URL resolved to an address on the server's own network; RFC 8620 section 8.6 requires the URL to be externally resolvable to prevent server-side request forgery.

Functions

func DecodeKeys

func DecodeKeys(p256dh, auth string) (uaPublic *ecdh.PublicKey, authSecret []byte, err error)

DecodeKeys decodes and validates a subscription's URL-safe base64 key material (RFC 8620 section 7.2): p256dh MUST be an uncompressed P-256 public key on the curve (RFC 8291 section 7 requires the on-curve check) and auth MUST be the 16-octet authentication secret of RFC 8291 section 3.2. Both padded and unpadded encodings are accepted, as RFC 4648 allows either.

func Decrypt

func Decrypt(uaKey *ecdh.PrivateKey, authSecret, body []byte) ([]byte, error)

Decrypt is the user-agent side of Encrypt: it opens an aes128gcm body using the subscription's private key and authentication secret. It exists for JMAP clients and for tests to close the loop; a JMAP server never decrypts. Per RFC 8291 section 4, a padding delimiter other than 0x02 discards the message.

func Encrypt

func Encrypt(uaPublic *ecdh.PublicKey, authSecret, plaintext []byte) ([]byte, error)

Encrypt encrypts one push message to a subscription's keys per RFC 8291, returning the complete aes128gcm-coded body: header (salt, record size, application server public key) followed by the single encrypted record. A fresh application server key pair and salt are generated per message (RFC 8291 section 2).

Types

type Sender

type Sender struct {
	// Client overrides the default HTTP client. A custom client keeps
	// the HTTPS-only rule but does NOT get the private address blocking
	// or redirect refusal unless it provides them itself; supply one
	// only when you take on that responsibility (tests do).
	Client *http.Client
}

Sender POSTs push messages to subscription URLs. The zero value is ready to use and safe: HTTPS only, redirects refused, and connections to private, loopback, link-local, unspecified, and other non-routable reserved addresses blocked at dial time (after DNS resolution, so a rebinding name cannot dodge the check).

func (*Sender) Send

func (s *Sender) Send(ctx context.Context, rawURL string, keys *jmap.PushKeys, payload []byte, ttlSeconds int) (int, error)

Send POSTs one push message per RFC 8620 section 7.2: content type application/json, a TTL header (RFC 8030 section 5.2), and - when the subscription has keys - the body encrypted per RFC 8291 under content encoding aes128gcm. It returns the HTTP status code; a 429 obliges the caller to reduce its push frequency.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL