From 2a001ee2ef7be16b13d7229002a7d1e7b04b1a90 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Fri, 3 Apr 2020 08:27:00 +0300 Subject: [PATCH] JMAP eventsource WIP --- melib/src/backends/jmap.rs | 36 +++++++++++++++- melib/src/backends/jmap/eventsource/client.rs | 41 +++++++++++++++---- 2 files changed, 66 insertions(+), 11 deletions(-) diff --git a/melib/src/backends/jmap.rs b/melib/src/backends/jmap.rs index 6d4a1082..5d1a8230 100644 --- a/melib/src/backends/jmap.rs +++ b/melib/src/backends/jmap.rs @@ -28,6 +28,7 @@ use crate::email::*; use crate::error::{MeliError, Result}; use fnv::FnvHashMap; use reqwest::blocking::Client; +use reqwest::Url; use std::collections::BTreeMap; use std::str::FromStr; use std::sync::{Arc, Mutex, RwLock}; @@ -75,6 +76,7 @@ pub mod mailbox; use mailbox::*; pub mod eventsource; +use eventsource::client::EventSourceClient; #[derive(Debug, Default)] pub struct EnvelopeCache { @@ -236,9 +238,39 @@ impl MailBackend for JmapType { fn watch( &self, _sender: RefreshEventConsumer, - _work_context: WorkContext, + work_context: WorkContext, ) -> Result { - Err(MeliError::from("JMAP watch for updates is unimplemented")) + let connection = JmapConnection::new(&self.server_conf, self.online.clone())?; + + let handle = std::thread::Builder::new() + .name(format!("{} jmap connection", self.account_name.as_str(),)) + .spawn(move || { + let thread = std::thread::current(); + work_context + .set_status + .send((thread.id(), "watching".to_string())) + .unwrap(); + + let event_source_url = connection.session.event_source_url.clone(); + debug!(&event_source_url); + let client = EventSourceClient::new( + Url::parse(&event_source_url).unwrap(), + vec![ + ( + "types".to_string(), + "Email,EmailDelivery,Mailbox".to_string(), + ), + ("closeafter".to_string(), "no".to_string()), + ("ping".to_string(), "1".to_string()), + ], + connection, + ); + for event in client { + debug!(&event); + println!("{}", event.unwrap()); + } + })?; + Ok(handle.thread().id()) } fn mailboxes(&self) -> Result> { diff --git a/melib/src/backends/jmap/eventsource/client.rs b/melib/src/backends/jmap/eventsource/client.rs index 9644430e..8b47b8ce 100644 --- a/melib/src/backends/jmap/eventsource/client.rs +++ b/melib/src/backends/jmap/eventsource/client.rs @@ -23,6 +23,7 @@ //! # Reqwest-based EventSource client use super::event::{parse_event_line, Event, ParseResult}; +use crate::backends::jmap::JmapConnection; use crate::error::*; use reqwest; use reqwest::header::{HeaderMap, HeaderValue, ACCEPT, CONTENT_TYPE}; @@ -56,10 +57,11 @@ impl MeliError { /// A client for a Server-Sent Events endpoint. /// /// Read events by iterating over the client. -pub struct Client { - client: reqwest::blocking::Client, +pub struct EventSourceClient { + connection: JmapConnection, response: Option>, url: reqwest::Url, + query: Vec<(String, String)>, last_event_id: Option, last_try: Option, @@ -68,15 +70,23 @@ pub struct Client { pub retry: Duration, } -impl Client { +impl EventSourceClient { /// Constructs a new EventSource client for the given URL. /// /// This does not start an HTTP request. - pub fn new(url: reqwest::Url) -> Client { - Client { - client: reqwest::blocking::Client::new(), + pub fn new( + url: reqwest::Url, + query: Vec<(String, String)>, + connection: JmapConnection, + ) -> EventSourceClient { + debug!("&url = {:#?}", &url); + debug!("&connection.session = {:#?}", &connection.session); + debug!("&connection.server_conf = {:#?}", &connection.server_conf); + EventSourceClient { + connection, response: None, - url: url, + url, + query, last_event_id: None, last_try: None, retry: Duration::from_millis(DEFAULT_RETRY), @@ -90,7 +100,20 @@ impl Client { headers.insert("Last-Event-ID", HeaderValue::from_str(id).unwrap()); } - let res = self.client.get(self.url.clone()).headers(headers).send()?; + let res = debug!(self + .connection + .client + .lock() + .unwrap() + .get(self.url.clone()) + .basic_auth( + &self.connection.server_conf.server_username, + Some(&self.connection.server_conf.server_password), + ) + .query(&self.query) + .headers(headers)) + .send()?; + debug!(&res); // Check status code and Content-Type. { @@ -128,7 +151,7 @@ macro_rules! try_option { /// Iterate over the client to get events. /// /// HTTP requests are made transparently while iterating. -impl Iterator for Client { +impl Iterator for EventSourceClient { type Item = Result; fn next(&mut self) -> Option> {