Rust Web Push
=============
[](https://github.com/pimeys/rust-web-push/actions/workflows/test.yml)
[](https://crates.io/crates/web_push)
[](https://docs.rs/web-push)
This crate implements the server half of the web push API, in Rust!
For more background on the web push framework itself, please
reference [this excellent document.](https://web.dev/notifications/)
## Requirements
- Clients require an async executor.
- OpenSSL is required for compilation. You must install it on your host or use the `vendored` feature of the [openssl](https://docs.rs/openssl/) crate.
## Migration notes
This library is still in active development, and will have breaking changes in accordance with semver. Please view the
GitHub release notes for detailed notes.
Example
--------
```rust
use web_push::*;
use std::fs::File;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
let endpoint = "https://updates.push.services.mozilla.com/wpush/v1/...";
let p256dh = "key_from_browser_as_base64";
let auth = "auth_from_browser_as_base64";
//You would likely get this by deserializing a browser `pushSubscription` object via serde.
let subscription_info = SubscriptionInfo::new(
endpoint,
p256dh,
auth
);
//Read signing material for payload.
let file = File::open("private_key.pem").unwrap();
let mut sig_builder = VapidSignatureBuilder::from_pem(file, &subscription_info)?.build()?;
//Now add payload and encrypt.
let mut builder = WebPushMessageBuilder::new(&subscription_info);
let content = "Encrypted payload to be sent in the notification".as_bytes();
builder.set_payload(ContentEncoding::Aes128Gcm, content);
builder.set_vapid_signature(sig_builder);
let client = IsahcWebPushClient::new()?;
//Finally, send the notification!
client.send(builder.build()?).await?;
Ok(())
}
```
VAPID
-----
VAPID authentication prevents unknown sources sending notifications to the client and is required by all current
browsers when sending a payload.
The private key to be used by the server can be generated with OpenSSL:
```
openssl ecparam -genkey -name prime256v1 -out private_key.pem
```
To derive a public key from the just-generated private key, to be used in the JavaScript client:
```
[good instructions](https://developers.google.com/web/fundamentals/push-notifications/subscribing-a-user) for building a
frontend to receive notifications.
Store the subscription info to `test.json` and send a notification with
`cd examples/simple-send && cargo run -- -v ../../private_key.pem -f ../../test.json -p "It works!"`.
Overview
--------
Currently, the crate implements
[RFC8188](https://datatracker.ietf.org/doc/html/rfc8188) content encryption for notification payloads. This is done by
delegating encryption to mozilla's [ece crate](https://crates.io/crates/ece). Our security is thus tied
to [theirs](https://github.com/mozilla/rust-ece/issues/18). The default client is built
on [isahc](https://crates.io/crates/isahc), but can be swapped out with a hyper based client using the
`hyper-client` feature. Custom clients can be made using the `request_builder` module.
Library tested with Google's and Mozilla's push notification services. Also verified to work on Edge.
Openssl is needed to build. Install `openssl-dev` or equivalent on *nix, or `openssl` using `vcpkg` on Windows. A nix
script is also available.
If installing on Windows, this is the exact command:
```shell
vcpkg integrate install
vcpkg install openssl:x64-windows-static-md
```
Debugging
--------
If you get an error or the push notification doesn't work you can try to debug using the following instructions:
Add the following to your Cargo.toml:
```cargo
log = "0.4"
pretty_env_logger = "0.3"
```
Add the following to your main.rs:
```rust
extern crate pretty_env_logger;
// ...
fn main() {
pretty_env_logger::init();
// ...
}
```
Or use any other logging library compatible with https://docs.rs/log/
Then run your program with the following environment variables:
```bash
RUST_LOG="web_push::client=trace" cargo run
```
This should print some more information about the requests to the push service which may aid you or somebody else in
finding the error.