Giter VIP home page Giter VIP logo

a2's Introduction

WalletConnect Specs

This repo runs specs.walletconnect.com.

Source can be viewed in docs directory.

Running Locally

  1. yarn install
  2. yarn start
  3. Open http://localhost:3000/

Adding a New Page

  1. Create a new file in docs/
  2. Configure sidebars.js to create the sidebar link.

Editing a Page

  1. Open the file in docs/

Older versions are available in versioned_docs/.

Customize Settings & Theme

  1. Open docusaurus.config.js

More

For more options, check the Docusaurus docs.

Archived v1.0 docs can be viewed in the v1.0 branch.

a2's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

a2's Issues

Experiment with a referring API

The builders allocate new strings too much due to the Service trait and infernal lifetime problems. One idea would be to have service to take String in and make the Client#send to convert a Payload<'a> to a JSON String; builders and payload would then only hold references to the input data and we'd have only one allocation.

This is a place for experimentation and other ideas how to do this are also appreciated.

Connection errors

I'm having connection errors when trying to connect to APNS:

TRACE 2018-04-03T08:46:05Z: apns2::signer: Signer::with_signature found signature for """""" APNS valid for 2700s
TRACE 2018-04-03T08:46:05Z: apns2::alpn: AlpnConnector::call ("https://api.push.apple.com/3/device/******")
TRACE 2018-04-03T08:46:05Z: apns2::client: Client::call requesting ("https://api.push.apple.com/3/device/******")
TRACE 2018-04-03T08:46:06Z: apns2::alpn: AlpnConnector::call got TCP, trying TLS
TRACE 2018-04-03T08:46:06Z: apns2::client: Request error: an operation was canceled internally before starting
 WARN 2018-04-03T08:46:06Z: push_relay::server: Error: Push message could not be processed: Push was unsuccessful: Error connecting to APNs

Any idea what the reason for this could be?

Handling connection errors

In the README you write:

The connection is meant to kept up when having constant traffic and should stop Apple's DDOS blocks. Sometimes one might experience TimeoutErrors or ConnectionErrors, so keeping track of connections and when having errors, restarting them is a good idea.

Is there a way to get notified about connection errors (e.g. when the HTTP2 connection gets severed) without sending a push?

Is there another way of restarting the connection than re-creating a Client?

Would be great if these things could be explained in the README.

Detach repo from unmaintained original

Can you please detach this repo from the not maintained fork?

You can this either do it manually or – which I recommend – just contact the GitHub support to do it for you.

This…

  1. shows that this is a real maintained project and not just a repo of someone who (once) made a pull request
  2. linking to the original repo on every page does not make sense anymore as it has been discontinued/is not maintained anymore and you…
  3. can (and IMHO should) still link to the original repo/website/author/… for crediting them, but you can do so in better ways (in the Readme, wiki or so)
  4. allows searching in this repo on GitHub and
  5. it just looks much nicer

Refactor client to use 'impl Trait`

The conservative impl Trait is landing to stable Rust later this year. Refactoring the client so we don't allocate and box for the returned future would make this lib's footprint smaller and even better, the code would look much better.

It might require a new version of Tokio, we'll see.

async-std support?

Using a2 crate with async-std executor crashes the application.
(this is my first impression because I run the same code in the examples/ but in an async-std environment, example works, mine doesn't)

client.send().await gives this error:

thread 'async-std/runtime' panicked at 'called `Option::unwrap()` on a `None` value', /home/user/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-alpn-0.4.0/src/lib.rs:263:29

Is there a "really important" reason depending on tokio runtime? I think if this library become executor agnostic it would be more useful.

Maybe this crate can use surf instead of hyper which can be used both with tokio & async-std: https://crates.io/crates/surf

Thanks for this crate!

changed lifetimes

First of all nice work and thanks for the quick release of version 0.5!

I am currently porting an actix-web(v0.7) application that uses a2(v0.4) to the new versions with std::futures(async/await) "support". Currently i am having some lifetime issues but i am not really sure why. Maybe its just me not seeing the obvious but i have the feeling that some lifetimes changed significantly from 0.4 -> 0.5

I have made some minimal examples.

old one (a2 0.4, futures 0.1, actix-web 0.7) this one compiles
Cargo.toml

#...
[dependencies]
actix-web = "0.7.19"
a2 = "0.4.0"
futures = "0.1.25"

main.rs

use actix_web::{client, http, server, App, Json, HttpRequest};
use futures::future::Future;

fn push_apns(_req: HttpRequest) -> impl actix_web::Responder {
    use a2::{Client, Endpoint, NotificationOptions, LocalizedNotificationBuilder, NotificationBuilder};

    let title = String::from("title1");
    let message = String::from("message1");
    let token = String::from("token1");
    let bundle_identifier = String::from("bundle1");

    let client = Client::token(
        String::from("certificate").as_bytes(),
        String::from("keyid"),
        String::from("teamid"),
        Endpoint::Sandbox,
    ).unwrap();

    let topic: Option<String> = Some(bundle_identifier);
    let options = NotificationOptions {
        apns_topic: topic.as_ref().map(|s| &**s),
        ..Default::default()
    };

    let mut builder = LocalizedNotificationBuilder::new(&title, &message);
    builder.set_sound("default");
    builder.set_badge(1u32);

    let payload = builder.build(&token, options.clone());
    let sending = client.send(payload);
    let sending = sending.map_err(|_| ()).map(|_| ());

    actix_web::actix::Arbiter::spawn(sending);

    "thanks for using our service"
}

fn main() {
    let server = server::new(|| {
        App::new()
            .resource("/push_apns", |r| {
                r.method(http::Method::POST).with(push_apns)
            })
    });
    server.bind("0.0.0.0:8080").unwrap().run();
}

new one (a2 0.5, futures 0.3, actix-web 2.0-alpha) this one does not compile
Cargo.toml

#...
[dependencies]
actix-web = "2.0.0-alpha.4"
actix-rt = "1.0.0"
futures = "0.3.1"
a2 = "0.5.0"

main.rs

use actix_web::{web::scope, middleware, web, App, HttpRequest, HttpServer, HttpResponse};
use futures::future::FutureExt;

pub async fn push_apns(_req: HttpRequest) -> HttpResponse {
    use a2::{NotificationOptions, LocalizedNotificationBuilder, Client, Endpoint, NotificationBuilder};

    let title = String::from("title1");
    let message = String::from("message1");
    let token = String::from("token1");
    let bundle_identifier = String::from("bundle1");

    let client = Client::token(
        String::from("certificate").as_bytes(),
        String::from("keyid"),
        String::from("teamid"),
        Endpoint::Sandbox,
    ).unwrap();

    let topic: Option<String> = Some(bundle_identifier);
    let options = NotificationOptions {
        apns_topic: topic.as_ref().map(|s| &**s),
        ..Default::default()
    };

    let mut builder = LocalizedNotificationBuilder::new(&title, &message);
    builder.set_sound("default");
    builder.set_badge(1u32);

    let payload = builder.build(&token, options.clone());
    let sending = client.send(payload);
    let sending = sending.map(|_| ());

    actix_rt::Arbiter::spawn(sending);

    HttpResponse::from("thanks for using our service")
}

#[actix_rt::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .service(scope("/push")
                .route("apns", web::post().to(push_apns))
            )
    })
        .bind("127.0.0.1:8080")?
        .start()
        .await
}

having this compile errors:

error[E0597]: `topic` does not live long enough
  --> src/main.rs:21:21
   |
21 |         apns_topic: topic.as_ref().map(|s| &**s),
   |                     ^^^^^                  ---- returning this value requires that `topic` is borrowed for `'static`
   |                     |
   |                     borrowed value does not live long enough
...
36 | }
   | - `topic` dropped here while still borrowed

error[E0597]: `title` does not live long enough
  --> src/main.rs:25:57
   |
25 |     let mut builder = LocalizedNotificationBuilder::new(&title, &message);
   |                       ----------------------------------^^^^^^-----------
   |                       |                                 |
   |                       |                                 borrowed value does not live long enough
   |                       argument requires that `title` is borrowed for `'static`
...
36 | }
   | - `title` dropped here while still borrowed

error[E0597]: `message` does not live long enough
  --> src/main.rs:25:65
   |
25 |     let mut builder = LocalizedNotificationBuilder::new(&title, &message);
   |                       ------------------------------------------^^^^^^^^-
   |                       |                                         |
   |                       |                                         borrowed value does not live long enough
   |                       argument requires that `message` is borrowed for `'static`
...
36 | }
   | - `message` dropped here while still borrowed

error[E0597]: `token` does not live long enough
  --> src/main.rs:29:33
   |
29 |     let payload = builder.build(&token, options.clone());
   |                   --------------^^^^^^------------------
   |                   |             |
   |                   |             borrowed value does not live long enough
   |                   argument requires that `token` is borrowed for `'static`
...
36 | }
   | - `token` dropped here while still borrowed

error[E0597]: `client` does not live long enough
  --> src/main.rs:30:19
   |
30 |     let sending = client.send(payload);
   |                   ^^^^^^--------------
   |                   |
   |                   borrowed value does not live long enough
   |                   argument requires that `client` is borrowed for `'static`
...
36 | }
   | - `client` dropped here while still borrowed

Unfortunately i am not very familiar with the new futures 0.3 or maybe missing something obvious here. But from what i understand is that in version 0.4 the public send function and e.g. the private build_request have a lifetime 'a from the Payload<'a> and thus to the &title, &message and &token stored in that Payload<'a> that is NOT bound to the return value FutureResponse because it looks like you are copying the values before "moving" them into futures like

        let path = format!(
            "https://{}/3/device/{}",
            self.endpoint, payload.device_token
        );

and thus "guarding" FutureResponse from being bound to e.g. payload.device_token

I think this is not the case in version 0.5
Because send is anotated with async the return type Result<Response, Error> is auto wrapped with (i think) impl Future<Output = Result<Response, Error>> + 'a binding the future onto the lifetime of its input parameters that result in my compilation errors? Because the hole function is now a Future and the copying

        let path = format!(
            "https://{}/3/device/{}",
            self.endpoint, payload.device_token
        );

is just to late because we are already inside the future before copying?

EDIT
I think this is roughly what happened

use std::future::Future;

// this is the "old" way writing this
fn lib_fn_old(data: &str) -> impl Future<Output = String> {
    let new_data = format!("new {}", data);
    futures::future::ready(new_data)
}

// this is the new way with async
async fn lib_fn_new(data: &str) -> String {
    format!("new {}", data)
}

// but it "silently" changes the lifetime bounds of the return value, binding
// it to the lifetime of the input!
fn lib_fn_new_desugar<'a>(data: &'a str) -> impl Future<Output = String> + 'a {
    async move {
        let new_data = format!("new {}", data);
        new_data
    }
}

// this would be the desugared function that have the same lifetime bounds 
fn lib_fn_new_same_lifetime(data: &str) -> impl Future<Output = String> {
    let new_data = format!("new {}", data);
    async move {
        new_data
    }
}

fn create_future() -> impl Future<Output = String> {
    let input_data = String::from("data");
    
    lib_fn_old(&input_data) // could do this with the old one
    
    // cannot do this with the new one
    // lib_fn_new(&input_data)
    // lib_fn_new_desugar(&input_data)
}

fn main() {
    let _future = create_future();
}

EDIT2
This is explicitly mentioned in the RFC 2394. My lib_fn_new_same_lifetime is mentioned as "Initialization pattern"

Sending a payload with invalid uri chars panics

If the device token get's set with invalid uri characters the call to send panics with:

thread 'tokio-runtime-worker' panicked at 'called `Result::unwrap()` on an `Err` value: http::Error(InvalidUri(InvalidUriChar))', /home/soeren/.cargo/registry/src/index.crates.io-6f17d22bba15001f/a2-0.7.0/src/client.rs:169:36

usage in rocket / actix-web is "hard"

i tried to use the lib on rocket and actix-web and on both i have the problem with dependency resolution.

you're using tokio-rustls v0.5.0 which depends on ring v0.13.0-alpha5 and that collides with the current version of cookie which depends on ring v.0.11.0

here is the error from rocket

error: multiple packages link to native library `ring-asm`, but a native library can be linked only once

package `ring v0.13.0-alpha5`
    ... which is depended on by `rustls v0.12.0`
    ... which is depended on by `tokio-rustls v0.5.0`
    ... which is depended on by `a2 v0.2.3`
    ... which is depended on by `depend_test v0.1.0 (file:///home/dustin/Documents/dev/rust/depend_test)`
links to native library `ring-asm`

package `ring v0.11.0`
    ... which is depended on by `cookie v0.9.2`
    ... which is depended on by `rocket v0.3.13`
    ... which is depended on by `depend_test v0.1.0 (file:///home/dustin/Documents/dev/rust/depend_test)`
also links to native library `ring-asm`

and from actix

error: multiple packages link to native library `ring-asm`, but a native library can be linked only once

package `ring v0.13.0-alpha5`
    ... which is depended on by `rustls v0.12.0`
    ... which is depended on by `tokio-rustls v0.5.0`
    ... which is depended on by `a2 v0.3.2`
    ... which is depended on by `herold v0.1.0 (file:///home/dustin/Documents/dev/rust/herold)`
links to native library `ring-asm`

package `ring v0.12.1`
    ... which is depended on by `cookie v0.10.1`
    ... which is depended on by `actix-web v0.7.0-dev (https://github.com/actix/actix-web.git#5c42b090)`
    ... which is depended on by `herold v0.1.0 (file:///home/dustin/Documents/dev/rust/herold)`
also links to native library `ring-asm`

and i can't think of an easy way to resolve this currently. Any suggestions?

Release a2 to the crates.io

Opening an issue for this. We're pending on Hyper's version 0.12, that should contain the h2 support. @seanmonstar was talking about a release on next week, so this is sooner I expected already.

We need some changes in this crate before it compiles against hyper 0.12, but nothing too serious now when hyper will still be in futures 0.1.

I would start versioning here from 0.2, because 0.1 was basically the now completely rewritten solicit-based apns2.

More type safety

This is part of the NotificationOptions:

    /// If you are using a provider token instead of a certificate, you must
    /// specify a value for this request header. The topic you provide should be
    /// provisioned for the your team named in your developer account.
    pub apns_topic: Option<String>,

It would be great if it were impossible to pass this to a client initialized with a provider token. Maybe two types of notification options could be provided?

For ergonomics, both could implement a common trait that converts the checked option types to an unchecked version.

Getting an issue with 'executor must be set'

Hi I am new to Rust and still do not know about tokio. I am trying to run an example with certificates, but get this issue below:

thread 'main' panicked at 'executor must be set', /Users/rajesh/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-0.14.5/src/common/exec.rs:52:21
note: run with RUST_BACKTRACE=1 environment variable to display a backtrace.

Can you please help me with this?

Renewing tokens

In the README you write:

If using a token connection, the connection should handle renewal of the signature before it's too late and for now I haven't seen any errors related to invalid tokens.

Is the lifetime of the JWT token tracked somehow? Is it the responsibility of the user to renew the signature? If yes, is there a way to renew the signature without recreating a client instance?

If this isn't being done yet, could this crate register a timer to auto-renew the signature, so that the user doesn't have to deal with it anymore?

Support For Using Rocket And a2

I Have A Project I Am Working on Where I Have A Rocket Webserver And I Would Also Like To Be Able To Send Push Notifications. Is There A Way For This Module Conflict (In The Code Below) To Be Fixed Here or Would I Have To Contact The Developers Of Rocket.

error: multiple packages link to native library `ring-asm`, but a native library can be linked only once

package `ring v0.13.0-alpha`
    ... which is depended on by `webpki v0.18.0-alpha`
    ... which is depended on by `rustls v0.12.0`
    ... which is depended on by `a2 v0.2.0-pre.0 (https://github.com/pimeys/a2/#48b6d746)`
    ... which is depended on by `[REMOVED PROJECT NAME] v1.0.0 ([REMOVED DIRECTORY])`
links to native library `ring-asm`

package `ring v0.11.0`
    ... which is depended on by `webpki v0.14.0`
    ... which is depended on by `webpki-roots v0.11.0`
    ... which is depended on by `hyper-sync-rustls v0.1.0`
    ... which is depended on by `rocket v0.3.8`
    ... which is depended on by `rocket_codegen v0.3.8`
    ... which is depended on by `[REMOVED PROJECT NAME] v1.0.0 ([REMOVED DIRECTORY])`
also links to native library `ring-asm`

Panic: 'executor must be set' from hyper-0.14.15 when running examples.

When running examples with the current cargo.toml (hyper 0.14), I'm getting the following error from hyper:

thread 'main' panicked at 'executor must be set', /root/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-0.14.15/src/common/exec.rs:54:21

Happening here in hyper:

                #[cfg(feature = "tcp")]
                {
                    tokio::task::spawn(fut);
                }
                #[cfg(not(feature = "tcp"))]
                {
                    // If no runtime, we need an executor!
                    panic!("executor must be set")
                }

Looking at the above and just adding the "tcp" feature to hyper dependencies fixes the problem:

hyper = { version = "0.14", features = ["client", "http2", "tcp"] }

Does it work for you without the "tcp" feature?

Connection pooling

In the README you write:

For one app, six connections is more than enough. One gets along well with less connections if fail-safety is not an issue.

Since you recommend using multiple connections, could this library maybe add support for connection pools? Alternatively this could also be done as a separate crate.

Do you have any recommendation on how to implement such a pool? A thread per connection with its own reactor core, with channels to trigger pushes?

I also thought about writing a r2d2 backend: https://github.com/sfackler/r2d2 But r2d2 is targeted at databases, I'm not sure if the trait is suited for APNs connections.

fix: add `tracing` feature back

The tracing feature is missing, it should be added back and the tracing dependency should only be added when this feature is enabled

Improve project marketing

When releasing 0.2, we should announce the project existence in certain medium, such as Reddit and Rust forums.

The README should gather bullet points of the goals of this crate.

  • announce project release
  • write about project goals in README

Client: Generic type arguments

Edit: Sorry, submitted too early due to a new keyboard :)

The Client::token signature currently looks like this:

    pub fn token<S, R>(
        pkcs8_pem: R,
        key_id: S,
        team_id: S,
        handle: &Handle,
        endpoint: Endpoint,
    ) -> Result<Client, Error>
    where
        S: Into<String>,
        R: Read,
{

This requires that key_id and team_id have the same type that implements Into.

What you want is probably this:

    pub fn token<S, R>(
        pkcs8_pem: R,
        key_id: S,
        team_id: T,
        handle: &Handle,
        endpoint: Endpoint,
    ) -> Result<Client, Error>
    where
        S: Into<String>,
        T: Into<String>,
        R: Read,
{

This way, the two types can differ, as long as they both impl Into.

http2 error: protocol error: not a result of an error

Hi,

Need help with error. Need some pointers to debug this issue .

`
[2019-07-22T07:37:38Z TRACE hyper_alpn] AlpnConnector::with_client_cert error reading private key
[2019-07-22T07:37:38Z TRACE hyper_alpn] AlpnConnector::with_client_cert error reading certificate
[2019-07-22T07:37:38Z TRACE hyper::client::pool] checkout waiting for idle connection: "https://api.push.apple.com"
[2019-07-22T07:37:38Z TRACE hyper_alpn] AlpnConnector::call (Destination { uri: https://api.push.apple.com/3/device/ })
[2019-07-22T07:37:38Z TRACE hyper_alpn] AlpnConnector::call got TCP, trying TLS
[2019-07-22T07:37:38Z DEBUG rustls::client::hs] No cached session for DNSNameRef("api.push.apple.com")
[2019-07-22T07:37:38Z DEBUG rustls::client::hs] Not resuming any session
[2019-07-22T07:37:38Z TRACE rustls::client::hs] Sending ClientHello Message {
typ: Handshake,
version: TLSv1_0,
payload: Handshake(
HandshakeMessagePayload {
.....

[2019-07-22T07:37:40Z TRACE rustls::client::hs] We got ServerHello ServerHelloPayload {
legacy_version: TLSv1_2,
random: Random(
[..]
),
session_id: SessionID([...]
),
....

[2019-07-22T07:37:40Z DEBUG rustls::client::hs] ALPN protocol is Some("h2")
[2019-07-22T07:37:40Z DEBUG rustls::client::hs] Using ciphersuite ....SHA256
[2019-07-22T07:37:40Z DEBUG rustls::client::hs] ECDHE curve is ECParameters { curve_type: NamedCurve, named_group: ... }
[2019-07-22T07:37:40Z DEBUG rustls::client::hs] Got CertificateRequest CertificateRequestPayload }
[2019-07-22T07:37:40Z DEBUG rustls::client::hs] Attempting client auth
[2019-07-22T07:37:40Z DEBUG rustls::client::hs] Server cert is [Certificate([........])]
[2019-07-22T07:37:40Z DEBUG rustls::client::hs] Server DNS name is DNSName("api.push.apple.com")
[2019-07-22T07:37:41Z DEBUG rustls::client::hs] Session not saved
[2019-07-22T07:37:41Z TRACE hyper::client::conn] client handshake HTTP/2
[2019-07-22T07:37:41Z TRACE hyper::client] handshake complete, spawning background dispatcher task
[2019-07-22T07:37:41Z TRACE hyper::client::pool] put; add idle connection for "https://api.push.apple.com"
[2019-07-22T07:37:41Z DEBUG hyper::client::pool] pooling idle connection for "https://api.push.apple.com"
[2019-07-22T07:37:41Z TRACE hyper::client::pool] checkout dropped for "https://api.push.apple.com"
[2019-07-22T07:37:41Z TRACE hyper::proto::h2] send body chunk: 58 bytes, eos=true
[2019-07-22T07:37:41Z TRACE hyper::proto::h2::client] connection gracefully shutdown
[2019-07-22T07:37:41Z DEBUG hyper::proto::h2::client] client response error: protocol error: not a result of an error
got error : http2 error: protocol error: not a result of an error,
Error: ConnectionError
[2019-07-22T07:37:41Z TRACE hyper::client::pool] pool closed, canceling idle interval
[2019-07-22T07:37:41Z DEBUG hyper::proto::h2::client] connection error: Connection reset by peer (os error 54)`

Automate publish ops

Setup CD so that when creating a release the crate will automatically be published.

`a2::response::Response` is confusing.

a2::client::FutureResponse is a future whose Item type is a2::response::Response and Error type is a2::error::Error. Which gives me the impression that a2::response::Response will be a struct that carries the successful response of APNS. BUT a2::response::Response has the error property and it's code property could be failure codes (e.g. 410), and it's used in an error case a2::error:Error::ResponseError(a2::response::Response).

🤔️ So a2::response::Response is used in both successful cases and failure cases?

When I tried to handle errors, I were confused: if the APNS's reponse is 410, I should receive an a2::response::Response object whose code is 410.
But am I receiving it in Ok(a2::response::Response)?
Or am I receiving it in Err(a2::error:Error::ResponseError(a2::response::Response))?
(I assumed I'm gonna receive it in the latter, please remind me if I were wrong)

What makes more sense to me is that we split a2::response::Response into two structs (just a quick thought, can use better naming):

  1. a2::response::SuccessResponse: a success response struct that only carries apns_id, and the success code (since 200 is the only one AFAIK, we might not need this property).
  2. a2::response::FailureResponse: a failure response struct that carries the error code, apns_id, and error_body.

When APNS returns 200, future resolves to Ok(a2::response::SuccessResponse).
When APNS returns failure status codes, future resolves to Err(a2::error:Error::ResponseError(a2::response:: FailureResponse)).

Upgrade to tokio 1.0

tokio-1.0.0 was released on 23 Dec 2020 - can you please upgrade this create. Also can we use tokio-compat-02 = "0.2.0"?

Possible renaming of this project

I've been digging and there's a couple of different apns2 implementations for Rust using the same name. In crates.io the name's been taken by a curl-based implementation and then we have the library I forked this implementation from and which I rewrote, that is pretty high on Google results when you search for apns2 rust.

I think this project might need to be renamed, but into what? tokio-apns2 is kind of meh, and then there's the possibility to go grand and after some Greek gods such as Zeus or Zeus of Tokio...

Any ideas?

Client panicked inside hyper-alpn library

I've created a project with the simplest code:

[package]
name = "push_test"
version = "0.1.0"
edition = "2021"

[dependencies]
a2 = "0.7.0"
tokio = { version = "1", features = ["full"] }
use a2::{Client, DefaultNotificationBuilder, Endpoint, NotificationBuilder, NotificationOptions};
use std::fs::File;

#[tokio::main]
async fn main() {
    let client = Client::token(
        &mut File::open("apns_authkey.p8").unwrap(),
        "my_key_id",
        "my_team_id",
        Endpoint::Sandbox,
    )
    .unwrap();

    let options = NotificationOptions {
        apns_topic: Some("com.my.app.dev"),
        ..Default::default()
    };

    let builder = DefaultNotificationBuilder::new()
        .set_title("Title")
        .set_body("Body")
        .set_sound("default");

    let payload = builder.build(
        "my_device_token",
        options,
    );

    _ = client.send(payload).await.unwrap();
}

The last line client.send() triggers the following issue when I run the build: thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', /.../.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-alpn-0.4.0/src/lib.rs:263:29

All the informations provided (.p8, key_id, team_id, bundle_app_id, device_token) are working when I send a notification using external tool like PushNotifications.

Any idea how to solve this?

'tokio-runtime-worker' has overflowed its stack fatal runtime error: stack overflow

Hi,

Upgrading to 0.5.3 is causing stack overflow error. After investigation, I found that in fmt::Display , it is calling self.

https://github.com/pimeys/a2/blob/master/src/error.rs

impl<'a> fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Error::ResponseError(Response {
                error: Some(ErrorBody { ref reason, .. }),
                ..
            }) => write!(fmt, "{} (reason: {:?})", self, reason),
            _ => write!(fmt, "{}", self),
        }
    }
}

Here are other references :

https://users.rust-lang.org/t/tokio-runtime-worker-stack-overflow/39421
https://users.rust-lang.org/t/thread-tokio-runtime-worker-has-overflowed-its-stack/43211

Breaking a2 into separate crates

To make it more modular, we could brake a2 into smaller crates:

  • a2-types: request/response builders and errors
  • a2-client: futures-based client using hyper/h2 behind the scenes
  • a2-actix: an alternative, actix based client
  • hyper-alpn: the alpn connector
  • jwt-signer: generates a JWT token and caches it for a given amount of time

Upgrade to futures 0.3, tokio 0.2 (or 0.3)

These will contain major breaking changes, but will help a lot when dealing with futures in your code. The upcoming pinning feature in Rust should help using futures in methods which reference self. More of an issue for the next autumn.

Default apns_priority doesn't match expectation

First of all, thanks for this awesome library!

The default value for apns_priority in NotificationOptions is Normal (5), which is usually not delivered if the app is on background (I was actually unable to see it being delivered). Apple specifies in https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns that the default value for the header is 10, if omitted, which makes it the expected behaviour, also making most notification tutorials omit the priority header.

I propose to make a breaking change and make apns_priority an Option inside NotificationOptions, just like every other header there.

Alternatives:

  • Change the default value to High, potentially breaking silently users that rely on the default behaviour.
  • Change the plain notification example to include specifying a custom apns_priority.

I'm willing send a PR to help.

What do you think?

(unrelated: I've got access to apple devices if you need any help)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.