mirror of
https://github.com/stoatchat/rust-a2.git
synced 2026-06-30 21:47:56 -04:00
Update to Tokio 1.0
This commit is contained in:
committed by
Julius de Bruijn
parent
21da69d029
commit
adc8d38138
@@ -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
@@ -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
@@ -1,2 +1,2 @@
|
||||
format_strings = false
|
||||
reorder_imports = true
|
||||
max_width = 120
|
||||
edition = "2018"
|
||||
|
||||
+43
-99
@@ -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,);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user