Expand description
This crate provides the tools necessary for your application to send Web Push messages
in accordance with RFC 8030.
In addition to sending Push messages, this crate also handles:
- the generation of valid Voluntary Application Server Identification (VAPID) tokens,
as required, in accordance with
RFC 8292for any messages you send; and, - the proper encryption of message content you send, using AES128GCM, in accordance with
RFC 8291.
§Setup a Push Service
Before your application can accept subscriptions from web browsers and send messages, you must
first initialize a PushService with an ECDSA private key and metadata that will be used to
generate VAPID tokens. The ECDSA private key and metadata you use represents your
application’s “identity” to servers that deliver your push message: this means you should use
the same private key across restarts of your application and across multiple running
instances of your application.
The OpenSSL suite can be used to generate an ECDSA private key for use with this library as follows:
openssl ecparam -name secp256r1 -genkey -noout -out vapid.pemThis should have created a file called vapid.pem containing the private key. Keep it secret:
losing it could allow an attacker to send push messages as if they were coming from your
application.
Then, create a PushService as follows:
use pushicino::{PushService, Vapid, Subject, VapidKey};
let service = PushService::new(Vapid::new(
Subject::parse("mailto:vapid@yourapplication.com")?,
VapidKey::load_from_file("vapid.pem")?,
));
// If you're using Axum, you should put the PushService into your application's state objectIf you’re using a web framework, like Axum, you should put the PushService that we created
here into your application’s state and that can be accessed by your application’s route
handlers.
§VAPID Endpoint
Frontend applications running on the browser will require your PushService’s public key.
You should create an endpoint that serves this public key, in Base64 encoding, to the frontend.
For example, in Axum, you could do:
use std::sync::Arc;
use axum::http::StatusCode;
use axum::extract::State;
use axum::Json;
use serde::Serialize;
use pushicino::PushService;
struct ApplicationState {
push_service: PushService,
}
#[derive(Serialize)]
struct ApplicationConfiguration {
vapid_public_key: String,
}
// Create a request handler that will serve the push service's public key in Base64 encoding
pub async fn application_configuration(State(state): State<Arc<ApplicationState>>)
-> Result<Json<ApplicationConfiguration>, StatusCode> {
Ok(Json(ApplicationConfiguration {
vapid_public_key: state.push_service.vapid_public_key_base64(),
}))
}
// Don't forget to register the `application_configuration` handler with your Axum router!Feel free to use any other method, instead of the one suggested above, to transfer the public key to the frontend.
§Subscriptions Endpoints
When the user’s browser confirms they would like to receive push messages from your application, they will need to send the subscription details to your application. You can receive this information by setting up an endpoint to receive this information.
Subscription implements the serde::Deserialize trait (from the serde crate) and it matches
the exact object returned by the PushSubscription.toJSON() method of the user agent. This
allows you to accept a Subscription directly from your request handler.
For example, in Axum, you could do:
use std::sync::Arc;
use axum::http::StatusCode;
use axum::extract::State;
use axum::Json;
use serde::Serialize;
use pushicino::{PushService, Subscription};
struct ApplicationState {
push_service: PushService,
}
async fn subscribe(
State(application): State<Arc<ApplicationState>>,
Json(request): Json<Subscription>,
) -> Result<(), StatusCode> {
// At this point, you should persist the Subscription into a database or some other storage
// Send a Web Push message immediately to the user, thanking them for subscribing!
application.push_service.send(&request, "Hello, thanks for subscribing!".as_bytes())
.await.unwrap();
Ok(())
}
// Don't forget to register the `subscribe` handler with your Axum router!It is your responsibility to persist the Subscription into storage (Subscription
implements the serde::Serialize trait). It is highly recommended that you associate the user’s
identity alongside the Subscription in case you wish to send Web Push messages to specific
users.
Structs§
- Authentication
Secret - A sequence of 16 octets generated by the user agent to act as a symmetric key and will be mixed into the key generation process as described in [https://datatracker.ietf.org/doc/html/rfc8291#section-3.2](RFC 8291 Section 3.2).
- Push
Service - The main entrypoint for sending Web Push messages.
- Subject
- An
Urlwhich uses themailto:scheme and is suitable for use as thesubclaim in VAPID-generated tokens. - Subscription
- An object containing all the information needed to send a Web Push message.
- Vapid
- Establishes your server application’s identity when sending Web Push messages.
- Vapid
Key - The secret key used to sign generated VAPID tokens.