diff --git a/server/src/main.rs b/server/src/main.rs index 7523b5f..88dca04 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,16 +1,18 @@ #[macro_use] extern crate rocket; -use std::{error::Error, process::Command, str::FromStr}; +use std::{error::Error, io::Cursor, str::FromStr}; use rocket::{ - response::{content::Plain, Debug}, + http::{ContentType, Header}, + request::Request, + response::{content::Plain, Debug, Responder}, serde::json::Json, - State, + Response, State, }; use rocket_cors::{AllowedHeaders, AllowedOrigins}; -use notmuch::{MessageId, Notmuch, NotmuchError, SearchSummary, ThreadSet}; +use notmuch::{Notmuch, NotmuchError, SearchSummary, ThreadSet}; #[get("/")] fn hello() -> &'static str { @@ -32,19 +34,44 @@ async fn show(nm: &State, query: &str) -> Result, Debug Ok(Json(res)) } +struct PartResponder { + bytes: Vec, + filename: Option, +} + +impl<'r, 'o: 'r> Responder<'r, 'o> for PartResponder { + fn respond_to(self, _: &'r Request<'_>) -> rocket::response::Result<'o> { + let mut resp = Response::build(); + if let Some(filename) = self.filename { + info!("filename {:?}", filename); + resp.header(Header::new( + "Content-Disposition", + format!(r#"attachment; filename="{}""#, filename), + )) + .header(ContentType::Binary); + } + resp.sized_body(self.bytes.len(), Cursor::new(self.bytes)) + .ok() + } +} + #[get("/original//part/")] async fn original_part( nm: &State, id: &str, part: usize, -) -> Result, Debug> { +) -> Result> { let mid = if id.starts_with("id:") { id.to_string() } else { format!("id:{}", id) }; + let meta = nm.show_part(&mid, part)?; let res = nm.show_original_part(&mid, part)?; - Ok(res) + Ok(PartResponder { + bytes: res, + filename: meta.filename, + }) } #[get("/original/")]