From adc8d38138318e373e90b57abb8046a674c7f2a6 Mon Sep 17 00:00:00 2001 From: Julius de Bruijn Date: Sat, 6 Feb 2021 11:42:54 +0100 Subject: [PATCH] Update to Tokio 1.0 --- CHANGELOG.md | 4 ++ Cargo.toml | 10 ++-- rustfmt.toml | 4 +- src/client.rs | 142 +++++++++++++++----------------------------------- 4 files changed, 54 insertions(+), 106 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ef843c..b648b9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## v0.6.0 + +- Update to Tokio 1.0 + ## v0.5.2 - Fix `TooManyProviderTokenUpdates` issue [#44](https://github.com/pimeys/a2/pull/44) diff --git a/Cargo.toml b/Cargo.toml index b6be6fb..b409e05 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,17 +19,17 @@ serde = "1" erased-serde = "0.3" serde_derive = "1" serde_json = "1" -thiserror = "1.0" +thiserror = "1" openssl = "0.10" futures = "0.3" http = "0.2" base64 = "0.12" log = "0.4" -hyper = "0.13" -hyper-alpn = "0.2" +hyper = { version = "0.14", features = ["client", "http2"] } +hyper-alpn = "0.3" [dev-dependencies] argparse = "0.2" pretty_env_logger = "0.4" -indoc = "0.3" -tokio = { version = "0.2", features = ["rt-threaded", "macros"] } +indoc = "1" +tokio = { version = "1", features = ["rt-multi-thread", "macros"] } diff --git a/rustfmt.toml b/rustfmt.toml index 7bcfcb7..9328e6c 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,2 +1,2 @@ -format_strings = false -reorder_imports = true +max_width = 120 +edition = "2018" diff --git a/src/client.rs b/src/client.rs index b6c8000..45e1551 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,26 +1,20 @@ //! The client module for sending requests and parsing responses -use crate::signer::Signer; -use hyper_alpn::AlpnConnector; use crate::error::Error; use crate::error::Error::ResponseError; +use crate::signer::Signer; +use hyper_alpn::AlpnConnector; -use futures::stream::StreamExt; -use hyper::{ - self, - Client as HttpClient, - StatusCode, - Body -}; -use http::header::{AUTHORIZATION, CONTENT_LENGTH, CONTENT_TYPE}; use crate::request::payload::Payload; use crate::response::Response; -use serde_json; -use std::{fmt, str}; -use std::time::Duration; -use std::future::Future; +use http::header::{AUTHORIZATION, CONTENT_LENGTH, CONTENT_TYPE}; +use hyper::{self, Body, Client as HttpClient, StatusCode}; use openssl::pkcs12::Pkcs12; +use serde_json; +use std::future::Future; use std::io::Read; +use std::time::Duration; +use std::{fmt, str}; /// The APNs service endpoint to connect. #[derive(Debug, Clone)] @@ -57,11 +51,7 @@ pub struct Client { } impl Client { - fn new( - connector: AlpnConnector, - signer: Option, - endpoint: Endpoint, - ) -> Client { + fn new(connector: AlpnConnector, signer: Option, endpoint: Endpoint) -> Client { let mut builder = HttpClient::builder(); builder.pool_idle_timeout(Some(Duration::from_secs(600))); builder.http2_only(true); @@ -76,11 +66,7 @@ impl Client { /// Create a connection to APNs using the provider client certificate which /// you obtain from your [Apple developer /// account](https://developer.apple.com/account/). - pub fn certificate( - certificate: &mut R, - password: &str, - endpoint: Endpoint, - ) -> Result + pub fn certificate(certificate: &mut R, password: &str, endpoint: Endpoint) -> Result where R: Read, { @@ -88,10 +74,7 @@ impl Client { certificate.read_to_end(&mut cert_der)?; let pkcs = Pkcs12::from_der(&cert_der)?.parse(password)?; - let connector = AlpnConnector::with_client_cert( - &pkcs.cert.to_pem()?, - &pkcs.pkey.private_key_to_pem_pkcs8()?, - )?; + let connector = AlpnConnector::with_client_cert(&pkcs.cert.to_pem()?, &pkcs.pkey.private_key_to_pem_pkcs8()?)?; Ok(Self::new(connector, None, endpoint)) } @@ -100,12 +83,7 @@ impl Client { /// request with a signature using a private key, key id and team id /// provisioned from your [Apple developer /// account](https://developer.apple.com/account/). - pub fn token( - pkcs8_pem: R, - key_id: S, - team_id: T, - endpoint: Endpoint, - ) -> Result + pub fn token(pkcs8_pem: R, key_id: S, team_id: T, endpoint: Endpoint) -> Result where S: Into, T: Into, @@ -135,27 +113,13 @@ impl Client { .map(|id| String::from(id)); match response.status() { - StatusCode::OK => { - Ok(Response { - apns_id, - error: None, - code: response.status().as_u16(), - }) - }, + StatusCode::OK => Ok(Response { + apns_id, + error: None, + code: response.status().as_u16(), + }), status => { - let content_length: usize = response - .headers() - .get(CONTENT_LENGTH) - .and_then(|s| s.to_str().ok()) - .and_then(|s| s.parse().ok()) - .unwrap_or(0); - - let mut body: Vec = Vec::with_capacity(content_length); - let mut chunks = response.into_body(); - - while let Some(chunk) = chunks.next().await { - body.extend_from_slice(&chunk?); - } + let body = hyper::body::to_bytes(response).await?; Err(ResponseError(Response { apns_id, @@ -168,10 +132,7 @@ impl Client { } fn build_request(&self, payload: Payload<'_>) -> hyper::Request { - let path = format!( - "https://{}/3/device/{}", - self.endpoint, payload.device_token - ); + let path = format!("https://{}/3/device/{}", self.endpoint, payload.device_token); let mut builder = hyper::Request::builder() .uri(&path) @@ -194,9 +155,9 @@ impl Client { builder = builder.header("apns-topic", apns_topic.as_bytes()); } if let Some(ref signer) = self.signer { - let auth = signer.with_signature(|signature| { - format!("Bearer {}", signature) - }).unwrap(); + let auth = signer + .with_signature(|signature| format!("Bearer {}", signature)) + .unwrap(); builder = builder.header(AUTHORIZATION, auth.as_bytes()); } @@ -212,13 +173,13 @@ impl Client { #[cfg(test)] mod tests { use super::*; - use crate::request::notification::PlainNotificationBuilder; use crate::request::notification::NotificationBuilder; - use crate::request::notification::{NotificationOptions, Priority, CollapseId}; - use hyper_alpn::AlpnConnector; - use hyper::Method; - use http::header::{AUTHORIZATION, CONTENT_LENGTH, CONTENT_TYPE}; + use crate::request::notification::PlainNotificationBuilder; + use crate::request::notification::{CollapseId, NotificationOptions, Priority}; use crate::signer::Signer; + use http::header::{AUTHORIZATION, CONTENT_LENGTH, CONTENT_TYPE}; + use hyper::Method; + use hyper_alpn::AlpnConnector; const PRIVATE_KEY: &'static str = indoc!( "-----BEGIN PRIVATE KEY----- @@ -279,10 +240,7 @@ mod tests { let payload_json = payload.to_json_string().unwrap(); let content_length = request.headers().get(CONTENT_LENGTH).unwrap().to_str().unwrap(); - assert_eq!( - &format!("{}", payload_json.len()), - content_length - ); + assert_eq!(&format!("{}", payload_json.len()), content_length); } #[test] @@ -297,7 +255,13 @@ mod tests { #[test] fn test_request_authorization_with_a_signer() { - let signer = Signer::new(PRIVATE_KEY.as_bytes(), "89AFRD1X22", "ASDFQWERTY", Duration::from_secs(100)).unwrap(); + let signer = Signer::new( + PRIVATE_KEY.as_bytes(), + "89AFRD1X22", + "ASDFQWERTY", + Duration::from_secs(100), + ) + .unwrap(); let builder = PlainNotificationBuilder::new("test"); let payload = builder.build("a_test_id", Default::default()); @@ -346,7 +310,7 @@ mod tests { NotificationOptions { apns_priority: Some(Priority::High), ..Default::default() - } + }, ); let client = Client::new(AlpnConnector::new(), None, Endpoint::Production); @@ -360,10 +324,7 @@ mod tests { fn test_request_with_default_apns_id() { let builder = PlainNotificationBuilder::new("test"); - let payload = builder.build( - "a_test_id", - Default::default(), - ); + let payload = builder.build("a_test_id", Default::default()); let client = Client::new(AlpnConnector::new(), None, Endpoint::Production); let request = client.build_request(payload); @@ -395,10 +356,7 @@ mod tests { fn test_request_with_default_apns_expiration() { let builder = PlainNotificationBuilder::new("test"); - let payload = builder.build( - "a_test_id", - Default::default(), - ); + let payload = builder.build("a_test_id", Default::default()); let client = Client::new(AlpnConnector::new(), None, Endpoint::Production); let request = client.build_request(payload); @@ -430,10 +388,7 @@ mod tests { fn test_request_with_default_apns_collapse_id() { let builder = PlainNotificationBuilder::new("test"); - let payload = builder.build( - "a_test_id", - Default::default(), - ); + let payload = builder.build("a_test_id", Default::default()); let client = Client::new(AlpnConnector::new(), None, Endpoint::Production); let request = client.build_request(payload); @@ -465,10 +420,7 @@ mod tests { fn test_request_with_default_apns_topic() { let builder = PlainNotificationBuilder::new("test"); - let payload = builder.build( - "a_test_id", - Default::default(), - ); + let payload = builder.build("a_test_id", Default::default()); let client = Client::new(AlpnConnector::new(), None, Endpoint::Production); let request = client.build_request(payload); @@ -503,17 +455,9 @@ mod tests { let client = Client::new(AlpnConnector::new(), None, Endpoint::Production); let request = client.build_request(payload.clone()); - let mut body: Vec = Vec::new(); - let mut chunks = request.into_body(); + let body = hyper::body::to_bytes(request).await.unwrap(); + let body_str = String::from_utf8(body.to_vec()).unwrap(); - while let Some(chunk) = chunks.next().await { - body.extend_from_slice(&chunk.unwrap()); - } - let body_str = String::from_utf8(body).unwrap(); - - assert_eq!( - payload.to_json_string().unwrap(), - body_str, - ); + assert_eq!(payload.to_json_string().unwrap(), body_str,); } }