| 402 | } |
| 403 | |
| 404 | func (n *Webpusher) webpushSend(ctx context.Context, msg []byte, endpoint string, keys webpush.Keys) (int, []byte, error) { |
| 405 | // Copy the message to avoid modifying the original. |
| 406 | cpy := slices.Clone(msg) |
| 407 | resp, err := webpush.SendNotificationWithContext(ctx, cpy, &webpush.Subscription{ |
| 408 | Endpoint: endpoint, |
| 409 | Keys: keys, |
| 410 | }, &webpush.Options{ |
| 411 | HTTPClient: n.httpClient, |
| 412 | Subscriber: n.vapidSub, |
| 413 | VAPIDPublicKey: n.VAPIDPublicKey, |
| 414 | VAPIDPrivateKey: n.VAPIDPrivateKey, |
| 415 | }) |
| 416 | if err != nil { |
| 417 | n.log.Error(ctx, "failed to send webpush notification", slog.Error(err), slog.F("endpoint", endpoint)) |
| 418 | return -1, nil, xerrors.Errorf("send webpush notification: %w", err) |
| 419 | } |
| 420 | defer resp.Body.Close() |
| 421 | body, err := io.ReadAll(resp.Body) |
| 422 | if err != nil { |
| 423 | return -1, nil, xerrors.Errorf("read response body: %w", err) |
| 424 | } |
| 425 | |
| 426 | return resp.StatusCode, body, nil |
| 427 | } |
| 428 | |
| 429 | func (n *Webpusher) Test(ctx context.Context, req codersdk.WebpushSubscription) error { |
| 430 | msgJSON, err := json.Marshal(codersdk.WebpushMessage{ |