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 ¶
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 ¶
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") )
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 ¶
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 ¶
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.