melib/jmap: put JmapSession behind mutex
And deserialize API urls to Arc<String>.jmap-eventsource
parent
1c25ae12eb
commit
62db7d7f32
|
@ -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?;
|
||||||
|
|
|
@ -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?;
|
||||||
|
|
|
@ -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,
|
||||||
))
|
))
|
||||||
|
|
|
@ -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?;
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue