forked from KokaKiwi/boitalettres
More flexible responses
This commit is contained in:
parent
fc5f093564
commit
2c43b7686a
4 changed files with 21 additions and 115 deletions
|
@ -1,18 +1,22 @@
|
|||
use miette::{IntoDiagnostic, Result};
|
||||
|
||||
use boitalettres::proto::{Request, Response};
|
||||
use boitalettres::proto::{Request, Response as BalResponse};
|
||||
use boitalettres::server::accept::addr::{AddrIncoming, AddrStream};
|
||||
use boitalettres::server::Server;
|
||||
|
||||
async fn handle_req(req: Request) -> Result<Response> {
|
||||
use imap_codec::types::response::{Capability, Data};
|
||||
use imap_codec::types::response::{Response, Data, Status, Capability};
|
||||
|
||||
async fn handle_req(req: Request) -> Result<BalResponse> {
|
||||
|
||||
tracing::debug!("Got request: {:#?}", req);
|
||||
|
||||
let capabilities = vec![Capability::Imap4Rev1, Capability::Idle];
|
||||
let body = vec![Data::Capability(capabilities)];
|
||||
let res = vec![
|
||||
Response::Data(Data::Capability(capabilities)),
|
||||
Response::Status(Status::ok(Some(req.tag), None, "Done").unwrap()),
|
||||
];
|
||||
|
||||
Ok(Response::ok("Done")?.with_body(body))
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
|
|
105
src/proto/res.rs
105
src/proto/res.rs
|
@ -1,104 +1,3 @@
|
|||
use imap_codec::types::{
|
||||
core::{Tag, Text},
|
||||
response::{Code as ImapCode, Status as ImapStatus},
|
||||
};
|
||||
use imap_codec::types::response::Response as ImapResponse;
|
||||
pub type Response = Vec<ImapResponse>;
|
||||
|
||||
use super::body::Body;
|
||||
use crate::errors::{Error, Result};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Response {
|
||||
pub(crate) status: Status,
|
||||
pub(crate) body: Option<Body>,
|
||||
}
|
||||
|
||||
impl Response {
|
||||
pub fn status(code: StatusCode, msg: &str) -> Result<Response> {
|
||||
Ok(Response {
|
||||
status: Status::new(code, msg)?,
|
||||
body: None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ok(msg: &str) -> Result<Response> {
|
||||
Self::status(StatusCode::Ok, msg)
|
||||
}
|
||||
|
||||
pub fn no(msg: &str) -> Result<Response> {
|
||||
Self::status(StatusCode::No, msg)
|
||||
}
|
||||
|
||||
pub fn bad(msg: &str) -> Result<Response> {
|
||||
Self::status(StatusCode::Bad, msg)
|
||||
}
|
||||
|
||||
pub fn bye(msg: &str) -> Result<Response> {
|
||||
Self::status(StatusCode::Bye, msg)
|
||||
}
|
||||
}
|
||||
|
||||
impl Response {
|
||||
pub fn with_extra_code(mut self, extra: ImapCode) -> Self {
|
||||
self.status.extra = Some(extra);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_body(mut self, body: impl Into<Body>) -> Self {
|
||||
self.body = Some(body.into());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Status {
|
||||
pub(crate) code: StatusCode,
|
||||
pub(crate) extra: Option<ImapCode>,
|
||||
pub(crate) text: Text,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum StatusCode {
|
||||
Ok,
|
||||
No,
|
||||
Bad,
|
||||
PreAuth,
|
||||
Bye,
|
||||
}
|
||||
|
||||
impl Status {
|
||||
fn new(code: StatusCode, msg: &str) -> Result<Status> {
|
||||
Ok(Status {
|
||||
code,
|
||||
extra: None,
|
||||
text: msg.try_into().map_err(Error::text)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn into_imap(self, tag: Option<Tag>) -> ImapStatus {
|
||||
match self.code {
|
||||
StatusCode::Ok => ImapStatus::Ok {
|
||||
tag,
|
||||
code: self.extra,
|
||||
text: self.text,
|
||||
},
|
||||
StatusCode::No => ImapStatus::No {
|
||||
tag,
|
||||
code: self.extra,
|
||||
text: self.text,
|
||||
},
|
||||
StatusCode::Bad => ImapStatus::Bad {
|
||||
tag,
|
||||
code: self.extra,
|
||||
text: self.text,
|
||||
},
|
||||
StatusCode::PreAuth => ImapStatus::PreAuth {
|
||||
code: self.extra,
|
||||
text: self.text,
|
||||
},
|
||||
StatusCode::Bye => ImapStatus::Bye {
|
||||
code: self.extra,
|
||||
text: self.text,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ use super::pipeline::Connection;
|
|||
use super::Imap;
|
||||
use crate::proto::{Request, Response};
|
||||
|
||||
use imap_codec::types::response::{Response as ImapResponse, Status};
|
||||
|
||||
pub struct Connecting<C, F, S>
|
||||
where
|
||||
C: AsyncRead + AsyncWrite + Unpin,
|
||||
|
@ -79,8 +81,7 @@ where
|
|||
{
|
||||
use futures::SinkExt;
|
||||
|
||||
let greeting = Response::ok("Hello").unwrap(); // "Hello" is a valid
|
||||
// greeting
|
||||
let greeting = vec![ImapResponse::Status(Status::greeting(None, "Hello").unwrap())]; // "Hello" is a valid greeting
|
||||
conn.start_send_unpin((None, greeting)).unwrap();
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ use futures::io::{AsyncRead, AsyncWrite};
|
|||
use futures::sink::Sink;
|
||||
use futures::stream::Stream;
|
||||
use imap_codec::types::core::Tag;
|
||||
use imap_codec::types::response::Response as ImapResponse;
|
||||
|
||||
use crate::proto::{Request, Response};
|
||||
|
||||
|
@ -118,12 +119,13 @@ where
|
|||
let write_buf = &mut self.get_mut().write_buf;
|
||||
let mut writer = write_buf.writer();
|
||||
|
||||
let body = res.body.into_iter().flat_map(|body| body.into_data());
|
||||
for data in body {
|
||||
data.encode(&mut writer)?;
|
||||
for elem in res {
|
||||
match elem {
|
||||
ImapResponse::Status(status) => status.encode(&mut writer)?,
|
||||
ImapResponse::Data(data) => data.encode(&mut writer)?,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
res.status.into_imap(tag).encode(&mut writer)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue