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

View File

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

View File

@ -86,10 +86,11 @@ pub struct JsonResponse<'a> {
pub async fn get_mailboxes(conn: &JmapConnection) -> Result<HashMap<MailboxHash, JmapMailbox>> { pub async fn get_mailboxes(conn: &JmapConnection) -> Result<HashMap<MailboxHash, JmapMailbox>> {
let seq = get_request_no!(conn.request_no); let seq = get_request_no!(conn.request_no);
let api_url = conn.session.lock().unwrap().api_url.clone();
let mut res = conn let mut res = conn
.client .client
.post_async( .post_async(
&conn.session.api_url, api_url.as_str(),
serde_json::to_string(&json!({ serde_json::to_string(&json!({
"using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
"methodCalls": [["Mailbox/get", { "methodCalls": [["Mailbox/get", {
@ -178,9 +179,10 @@ pub async fn get_message_list(
let mut req = Request::new(conn.request_no.clone()); let mut req = Request::new(conn.request_no.clone());
req.add_call(&email_call); req.add_call(&email_call);
let api_url = conn.session.lock().unwrap().api_url.clone();
let mut res = conn let mut res = conn
.client .client
.post_async(&conn.session.api_url, serde_json::to_string(&req)?) .post_async(api_url.as_str(), serde_json::to_string(&req)?)
.await?; .await?;
let res_text = res.text_async().await?; let res_text = res.text_async().await?;
@ -249,9 +251,10 @@ pub async fn fetch(
req.add_call(&email_call); req.add_call(&email_call);
let api_url = conn.session.lock().unwrap().api_url.clone();
let mut res = conn let mut res = conn
.client .client
.post_async(&conn.session.api_url, serde_json::to_string(&req)?) .post_async(api_url.as_str(), serde_json::to_string(&req)?)
.await?; .await?;
let res_text = res.text_async().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::ser::{Serialize, SerializeStruct, Serializer};
use serde_json::{value::RawValue, Value}; use serde_json::{value::RawValue, Value};
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::sync::Arc;
mod filters; mod filters;
pub use filters::*; pub use filters::*;
@ -208,11 +209,11 @@ pub struct JmapSession {
pub accounts: HashMap<Id<Account>, Account>, pub accounts: HashMap<Id<Account>, Account>,
pub primary_accounts: HashMap<String, Id<Account>>, pub primary_accounts: HashMap<String, Id<Account>>,
pub username: String, pub username: String,
pub api_url: String, pub api_url: Arc<String>,
pub download_url: String, pub download_url: Arc<String>,
pub upload_url: String, pub upload_url: Arc<String>,
pub event_source_url: String, pub event_source_url: Arc<String>,
pub state: State<JmapSession>, pub state: State<JmapSession>,
#[serde(flatten)] #[serde(flatten)]
pub extra_properties: HashMap<String, Value>, pub extra_properties: HashMap<String, Value>,
@ -930,49 +931,49 @@ impl core::fmt::Display for SetError {
} }
pub fn download_request_format( pub fn download_request_format(
session: &JmapSession, download_url: &str,
account_id: &Id<Account>, account_id: &Id<Account>,
blob_id: &Id<BlobObject>, blob_id: &Id<BlobObject>,
name: Option<String>, name: Option<String>,
) -> String { ) -> String {
// https://jmap.fastmail.com/download/{accountId}/{blobId}/{name} // https://jmap.fastmail.com/download/{accountId}/{blobId}/{name}
let mut ret = String::with_capacity( let mut ret = String::with_capacity(
session.download_url.len() download_url.len()
+ blob_id.len() + blob_id.len()
+ name.as_ref().map(|n| n.len()).unwrap_or(0) + name.as_ref().map(|n| n.len()).unwrap_or(0)
+ account_id.len(), + account_id.len(),
); );
let mut prev_pos = 0; let mut prev_pos = 0;
while let Some(pos) = session.download_url.as_bytes()[prev_pos..].find(b"{") { while let Some(pos) = download_url.as_bytes()[prev_pos..].find(b"{") {
ret.push_str(&session.download_url[prev_pos..prev_pos + pos]); ret.push_str(&download_url[prev_pos..prev_pos + 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()); ret.push_str(account_id.as_str());
prev_pos += "{accountId}".len(); 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()); ret.push_str(blob_id.as_str());
prev_pos += "{blobId}".len(); 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("")); ret.push_str(name.as_ref().map(String::as_str).unwrap_or(""));
prev_pos += "{name}".len(); prev_pos += "{name}".len();
} }
} }
if prev_pos != session.download_url.len() { if prev_pos != download_url.len() {
ret.push_str(&session.download_url[prev_pos..]); ret.push_str(&download_url[prev_pos..]);
} }
ret 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}/", //"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; let mut prev_pos = 0;
while let Some(pos) = session.upload_url.as_bytes()[prev_pos..].find(b"{") { while let Some(pos) = upload_url.as_bytes()[prev_pos..].find(b"{") {
ret.push_str(&session.upload_url[prev_pos..prev_pos + pos]); ret.push_str(&upload_url[prev_pos..prev_pos + 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()); ret.push_str(account_id.as_str());
prev_pos += "{accountId}".len(); prev_pos += "{accountId}".len();
break; break;
@ -981,8 +982,8 @@ pub fn upload_request_format(session: &JmapSession, account_id: &Id<Account>) ->
prev_pos += 1; prev_pos += 1;
} }
} }
if prev_pos != session.upload_url.len() { if prev_pos != upload_url.len() {
ret.push_str(&session.upload_url[prev_pos..]); ret.push_str(&upload_url[prev_pos..]);
} }
ret ret
} }