melib/jmap: put JmapSession behind mutex

And deserialize API urls to Arc<String>.
jmap-eventsource
Manos Pitsidianakis 2021-01-05 17:05:56 +02:00
parent 1c25ae12eb
commit 62db7d7f32
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
5 changed files with 49 additions and 37 deletions

View File

@ -391,10 +391,14 @@ impl MailBackend for JmapType {
* 1. upload binary blob, get blobId
* 2. Email/import
*/
let (api_url, upload_url) = {
let lck = conn.session.lock().unwrap();
(lck.api_url.clone(), lck.upload_url.clone())
};
let mut res = conn
.client
.post_async(
&upload_request_format(&conn.session, conn.mail_account_id()),
&upload_request_format(upload_url.as_str(), &conn.mail_account_id()),
bytes,
)
.await?;
@ -432,7 +436,7 @@ impl MailBackend for JmapType {
req.add_call(&import_call);
let mut res = conn
.client
.post_async(&conn.session.api_url, serde_json::to_string(&req)?)
.post_async(api_url.as_str(), serde_json::to_string(&req)?)
.await?;
let res_text = res.text_async().await?;
@ -502,10 +506,11 @@ impl MailBackend for JmapType {
let mut req = Request::new(conn.request_no.clone());
req.add_call(&email_call);
let api_url = conn.session.lock().unwrap().api_url.clone();
let mut res = conn
.client
.post_async(&conn.session.api_url, serde_json::to_string(&req)?)
.post_async(api_url.as_str(), serde_json::to_string(&req)?)
.await?;
let res_text = res.text_async().await?;
@ -587,6 +592,7 @@ impl MailBackend for JmapType {
}
}
let conn = connection.lock().await;
let api_url = conn.session.lock().unwrap().api_url.clone();
let email_set_call: EmailSet = EmailSet::new(
Set::<EmailObject>::new()
@ -599,7 +605,7 @@ impl MailBackend for JmapType {
let mut res = conn
.client
.post_async(&conn.session.api_url, serde_json::to_string(&req)?)
.post_async(api_url.as_str(), serde_json::to_string(&req)?)
.await?;
let res_text = res.text_async().await?;
@ -697,10 +703,11 @@ impl MailBackend for JmapType {
);
req.add_call(&email_call);
let api_url = conn.session.lock().unwrap().api_url.clone();
//debug!(serde_json::to_string(&req)?);
let mut res = conn
.client
.post_async(&conn.session.api_url, serde_json::to_string(&req)?)
.post_async(api_url.as_str(), serde_json::to_string(&req)?)
.await?;
let res_text = res.text_async().await?;

View File

@ -24,7 +24,7 @@ use isahc::config::Configurable;
#[derive(Debug)]
pub struct JmapConnection {
pub session: JmapSession,
pub session: Arc<Mutex<JmapSession>>,
pub request_no: Arc<Mutex<usize>>,
pub client: Arc<HttpClient>,
pub server_conf: JmapServerConf,
@ -44,7 +44,7 @@ impl JmapConnection {
.build()?;
let server_conf = server_conf.clone();
Ok(JmapConnection {
session: Default::default(),
session: Arc::new(Mutex::new(Default::default())),
request_no: Arc::new(Mutex::new(0)),
client: Arc::new(client),
server_conf,
@ -97,12 +97,12 @@ impl JmapConnection {
}
*self.store.online_status.lock().await = (Instant::now(), Ok(()));
self.session = session;
*self.session.lock().unwrap() = session;
Ok(())
}
pub fn mail_account_id(&self) -> &Id<Account> {
&self.session.primary_accounts["urn:ietf:params:jmap:mail"]
pub fn mail_account_id(&self) -> Id<Account> {
self.session.lock().unwrap().primary_accounts["urn:ietf:params:jmap:mail"].clone()
}
pub fn add_refresh_event(&self, event: RefreshEvent) {
@ -123,7 +123,6 @@ impl JmapConnection {
return Ok(());
};
loop {
let email_changes_call: EmailChanges = EmailChanges::new(
Changes::<EmailObject>::new()
.account_id(self.mail_account_id().clone())
@ -172,9 +171,10 @@ impl JmapConnection {
} else {
return Ok(());
}
let api_url = self.session.lock().unwrap().api_url.clone();
let mut res = self
.client
.post_async(&self.session.api_url, serde_json::to_string(&req)?)
.post_async(api_url.as_str(), serde_json::to_string(&req)?)
.await?;
let res_text = res.text_async().await?;

View File

@ -60,11 +60,12 @@ impl BackendOp for JmapOp {
let blob_id = store.blob_id_store.lock().unwrap()[&hash].clone();
let mut conn = connection.lock().await;
conn.connect().await?;
let download_url = conn.session.lock().unwrap().download_url.clone();
let mut res = conn
.client
.get_async(&download_request_format(
&conn.session,
conn.mail_account_id(),
download_url.as_str(),
&conn.mail_account_id(),
&blob_id,
None,
))

View File

@ -86,10 +86,11 @@ pub struct JsonResponse<'a> {
pub async fn get_mailboxes(conn: &JmapConnection) -> Result<HashMap<MailboxHash, JmapMailbox>> {
let seq = get_request_no!(conn.request_no);
let api_url = conn.session.lock().unwrap().api_url.clone();
let mut res = conn
.client
.post_async(
&conn.session.api_url,
api_url.as_str(),
serde_json::to_string(&json!({
"using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
"methodCalls": [["Mailbox/get", {
@ -178,9 +179,10 @@ pub async fn get_message_list(
let mut req = Request::new(conn.request_no.clone());
req.add_call(&email_call);
let api_url = conn.session.lock().unwrap().api_url.clone();
let mut res = conn
.client
.post_async(&conn.session.api_url, serde_json::to_string(&req)?)
.post_async(api_url.as_str(), serde_json::to_string(&req)?)
.await?;
let res_text = res.text_async().await?;
@ -249,9 +251,10 @@ pub async fn fetch(
req.add_call(&email_call);
let api_url = conn.session.lock().unwrap().api_url.clone();
let mut res = conn
.client
.post_async(&conn.session.api_url, serde_json::to_string(&req)?)
.post_async(api_url.as_str(), serde_json::to_string(&req)?)
.await?;
let res_text = res.text_async().await?;

View File

@ -25,6 +25,7 @@ use serde::de::DeserializeOwned;
use serde::ser::{Serialize, SerializeStruct, Serializer};
use serde_json::{value::RawValue, Value};
use std::hash::{Hash, Hasher};
use std::sync::Arc;
mod filters;
pub use filters::*;
@ -208,11 +209,11 @@ pub struct JmapSession {
pub accounts: HashMap<Id<Account>, Account>,
pub primary_accounts: HashMap<String, Id<Account>>,
pub username: String,
pub api_url: String,
pub download_url: String,
pub api_url: Arc<String>,
pub download_url: Arc<String>,
pub upload_url: String,
pub event_source_url: String,
pub upload_url: Arc<String>,
pub event_source_url: Arc<String>,
pub state: State<JmapSession>,
#[serde(flatten)]
pub extra_properties: HashMap<String, Value>,
@ -930,49 +931,49 @@ impl core::fmt::Display for SetError {
}
pub fn download_request_format(
session: &JmapSession,
download_url: &str,
account_id: &Id<Account>,
blob_id: &Id<BlobObject>,
name: Option<String>,
) -> String {
// https://jmap.fastmail.com/download/{accountId}/{blobId}/{name}
let mut ret = String::with_capacity(
session.download_url.len()
download_url.len()
+ blob_id.len()
+ name.as_ref().map(|n| n.len()).unwrap_or(0)
+ account_id.len(),
);
let mut prev_pos = 0;
while let Some(pos) = session.download_url.as_bytes()[prev_pos..].find(b"{") {
ret.push_str(&session.download_url[prev_pos..prev_pos + pos]);
while let Some(pos) = download_url.as_bytes()[prev_pos..].find(b"{") {
ret.push_str(&download_url[prev_pos..prev_pos + pos]);
prev_pos += pos;
if session.download_url[prev_pos..].starts_with("{accountId}") {
if download_url[prev_pos..].starts_with("{accountId}") {
ret.push_str(account_id.as_str());
prev_pos += "{accountId}".len();
} else if session.download_url[prev_pos..].starts_with("{blobId}") {
} else if download_url[prev_pos..].starts_with("{blobId}") {
ret.push_str(blob_id.as_str());
prev_pos += "{blobId}".len();
} else if session.download_url[prev_pos..].starts_with("{name}") {
} else if download_url[prev_pos..].starts_with("{name}") {
ret.push_str(name.as_ref().map(String::as_str).unwrap_or(""));
prev_pos += "{name}".len();
}
}
if prev_pos != session.download_url.len() {
ret.push_str(&session.download_url[prev_pos..]);
if prev_pos != download_url.len() {
ret.push_str(&download_url[prev_pos..]);
}
ret
}
pub fn upload_request_format(session: &JmapSession, account_id: &Id<Account>) -> String {
pub fn upload_request_format(upload_url: &str, account_id: &Id<Account>) -> String {
//"uploadUrl": "https://jmap.fastmail.com/upload/{accountId}/",
let mut ret = String::with_capacity(session.upload_url.len() + account_id.len());
let mut ret = String::with_capacity(upload_url.len() + account_id.len());
let mut prev_pos = 0;
while let Some(pos) = session.upload_url.as_bytes()[prev_pos..].find(b"{") {
ret.push_str(&session.upload_url[prev_pos..prev_pos + pos]);
while let Some(pos) = upload_url.as_bytes()[prev_pos..].find(b"{") {
ret.push_str(&upload_url[prev_pos..prev_pos + pos]);
prev_pos += pos;
if session.upload_url[prev_pos..].starts_with("{accountId}") {
if upload_url[prev_pos..].starts_with("{accountId}") {
ret.push_str(account_id.as_str());
prev_pos += "{accountId}".len();
break;
@ -981,8 +982,8 @@ pub fn upload_request_format(session: &JmapSession, account_id: &Id<Account>) ->
prev_pos += 1;
}
}
if prev_pos != session.upload_url.len() {
ret.push_str(&session.upload_url[prev_pos..]);
if prev_pos != upload_url.len() {
ret.push_str(&upload_url[prev_pos..]);
}
ret
}