Update to Tokio 1.0

This commit is contained in:
Julius de Bruijn
2021-02-06 11:42:54 +01:00
committed by Julius de Bruijn
parent 21da69d029
commit adc8d38138
4 changed files with 54 additions and 106 deletions
+4
View File
@@ -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)
+5 -5
View File
@@ -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"] }
+2 -2
View File
@@ -1,2 +1,2 @@
format_strings = false
reorder_imports = true
max_width = 120
edition = "2018"
+43 -99
View File
@@ -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<Signer>,
endpoint: Endpoint,
) -> Client {
fn new(connector: AlpnConnector, signer: Option<Signer>, 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<R>(
certificate: &mut R,
password: &str,
endpoint: Endpoint,
) -> Result<Client, Error>
pub fn certificate<R>(certificate: &mut R, password: &str, endpoint: Endpoint) -> Result<Client, Error>
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<S, T, R>(
pkcs8_pem: R,
key_id: S,
team_id: T,
endpoint: Endpoint,
) -> Result<Client, Error>
pub fn token<S, T, R>(pkcs8_pem: R, key_id: S, team_id: T, endpoint: Endpoint) -> Result<Client, Error>
where
S: Into<String>,
T: Into<String>,
@@ -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<u8> = 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<Body> {
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<u8> = 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,);
}
}