Remove warp

axum-login-upgrade
Manos Pitsidianakis 2023-05-08 10:43:22 +03:00
parent 5698cb2bcb
commit 4644349ebb
Signed by: Manos Pitsidianakis
GPG Key ID: 7729C7707F7E09D0
6 changed files with 149 additions and 317 deletions

118
Cargo.lock generated
View File

@ -547,12 +547,6 @@ version = "3.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "bytes"
version = "1.4.0"
@ -1798,8 +1792,6 @@ dependencies = [
"percent-encoding",
"serde",
"serde_json",
"tokio",
"warp",
]
[[package]]
@ -1823,7 +1815,6 @@ version = "0.1.1"
dependencies = [
"mailpot",
"tokio",
"warp",
]
[[package]]
@ -1930,16 +1921,6 @@ version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "mime_guess"
version = "2.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef"
dependencies = [
"mime",
"unicase",
]
[[package]]
name = "minijinja"
version = "0.31.0"
@ -2012,20 +1993,6 @@ dependencies = [
"ws2_32-sys",
]
[[package]]
name = "multiparty"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed1ec6589a6d4a1e0b33b4c0a3f6ee96dfba88ebdb3da51403fd7cf0a24a4b04"
dependencies = [
"bytes",
"futures-core",
"httparse",
"memchr",
"pin-project-lite",
"try-lock",
]
[[package]]
name = "native-tls"
version = "0.2.11"
@ -2613,12 +2580,6 @@ dependencies = [
"windows-sys 0.42.0",
]
[[package]]
name = "scoped-tls"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
[[package]]
name = "scoped_threadpool"
version = "0.1.9"
@ -3080,29 +3041,6 @@ dependencies = [
"syn 2.0.14",
]
[[package]]
name = "tokio-stream"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313"
dependencies = [
"futures-core",
"pin-project-lite",
"tokio",
]
[[package]]
name = "tokio-tungstenite"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd"
dependencies = [
"futures-util",
"log",
"tokio",
"tungstenite",
]
[[package]]
name = "tokio-util"
version = "0.7.7"
@ -3230,25 +3168,6 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
[[package]]
name = "tungstenite"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788"
dependencies = [
"base64 0.13.1",
"byteorder",
"bytes",
"http",
"httparse",
"log",
"rand",
"sha1",
"thiserror",
"url",
"utf-8",
]
[[package]]
name = "typenum"
version = "1.16.0"
@ -3314,12 +3233,6 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "utf-8"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]]
name = "uuid"
version = "1.3.1"
@ -3378,37 +3291,6 @@ dependencies = [
"try-lock",
]
[[package]]
name = "warp"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27e1a710288f0f91a98dd8a74f05b76a10768db245ce183edf64dc1afdc3016c"
dependencies = [
"bytes",
"futures-channel",
"futures-util",
"headers",
"http",
"hyper",
"log",
"mime",
"mime_guess",
"multiparty",
"percent-encoding",
"pin-project",
"rustls-pemfile",
"scoped-tls",
"serde",
"serde_json",
"serde_urlencoded",
"tokio",
"tokio-stream",
"tokio-tungstenite",
"tokio-util",
"tower-service",
"tracing",
]
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"

View File

@ -14,11 +14,6 @@ default-run = "mpot-archives"
[[bin]]
name = "mpot-archives"
path = "src/main.rs"
required-features = ["warp"]
[[bin]]
name = "mpot-gen"
path = "src/gen.rs"
[dependencies]
chrono = { version = "^0.4" }
@ -28,10 +23,3 @@ minijinja = { version = "0.31.0", features = ["source", ] }
percent-encoding = { version = "^2.1", optional = true }
serde = { version = "^1", features = ["derive", ] }
serde_json = "^1"
tokio = { version = "1", features = ["full"], optional = true }
warp = { version = "^0.3", optional = true }
[features]
default = ["gen"]
gen = []
warp = ["dep:percent-encoding", "dep:tokio", "dep:warp"]

View File

@ -17,26 +17,89 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use std::{fs::OpenOptions, io::Write};
use mailpot::*;
use mailpot_archives::utils::*;
use minijinja::value::Value;
use percent_encoding::percent_decode_str;
use warp::Filter;
#[tokio::main]
async fn main() {
let config_path = std::env::args()
.nth(1)
.expect("Expected configuration file path as first argument.");
let conf = Configuration::from_file(config_path).unwrap();
fn run_app() -> std::result::Result<(), Box<dyn std::error::Error>> {
let args = std::env::args().collect::<Vec<_>>();
let Some(config_path) = args.get(1) else {
return Err("Expected configuration file path as first argument.".into());
};
let Some(output_path) = args.get(2) else {
return Err("Expected output dir path as second argument.".into());
};
let root_url_prefix = args.get(3).cloned().unwrap_or_default();
let conf1 = conf.clone();
let list_handler = warp::path!("lists" / i64).map(move |list_pk: i64| {
let db = Connection::open_db(conf1.clone()).unwrap();
let list = db.list(list_pk).unwrap().unwrap();
let post_policy = db.list_post_policy(list.pk).unwrap();
let months = db.months(list.pk).unwrap();
let posts = db.list_posts(list.pk, None).unwrap();
let output_path = std::path::Path::new(&output_path);
if output_path.exists() && !output_path.is_dir() {
return Err("Output path is not a directory.".into());
}
std::fs::create_dir_all(&output_path.join("lists"))?;
std::fs::create_dir_all(&output_path.join("list"))?;
let conf = Configuration::from_file(config_path)
.map_err(|err| format!("Could not load config {config_path}: {err}"))?;
let db = Connection::open_db(conf).map_err(|err| format!("Couldn't open db: {err}"))?;
let lists_values = db.lists()?;
{
//index.html
let lists = lists_values
.iter()
.map(|list| {
let months = db.months(list.pk).unwrap();
let posts = db.list_posts(list.pk, None).unwrap();
minijinja::context! {
title => &list.name,
posts => &posts,
months => &months,
body => &list.description.as_deref().unwrap_or_default(),
root_prefix => &root_url_prefix,
list => Value::from_object(MailingList::from(list.clone())),
}
})
.collect::<Vec<_>>();
let mut file = OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(&output_path.join("index.html"))?;
let crumbs = vec![Crumb {
label: "Lists".into(),
url: format!("{root_url_prefix}/").into(),
}];
let context = minijinja::context! {
title => "mailing list archive",
description => "",
lists => &lists,
root_prefix => &root_url_prefix,
crumbs => crumbs,
};
file.write_all(
TEMPLATES
.get_template("lists.html")?
.render(context)?
.as_bytes(),
)?;
}
let mut lists_path = output_path.to_path_buf();
for list in &lists_values {
lists_path.push("lists");
lists_path.push(list.pk.to_string());
std::fs::create_dir_all(&lists_path)?;
lists_path.push("index.html");
let list = db.list(list.pk)?.unwrap();
let post_policy = db.list_post_policy(list.pk)?;
let months = db.months(list.pk)?;
let posts = db.list_posts(list.pk, None)?;
let mut hist = months
.iter()
.map(|m| (m.to_string(), [0usize; 31]))
@ -61,26 +124,26 @@ async fn main() {
subject_ref = subject_ref[2 + list.id.len()..].trim();
}
minijinja::context! {
pk => post.pk,
list => post.list,
subject => subject_ref,
address=> post.address,
message_id => msg_id,
message => post.message,
timestamp => post.timestamp,
datetime => post.datetime,
root_prefix => "",
pk => post.pk,
list => post.list,
subject => subject_ref,
address=> post.address,
message_id => msg_id,
message => post.message,
timestamp => post.timestamp,
datetime => post.datetime,
root_prefix => &root_url_prefix,
}
})
.collect::<Vec<_>>();
let crumbs = vec![
Crumb {
label: "Lists".into(),
url: "/".into(),
url: format!("{root_url_prefix}/").into(),
},
Crumb {
label: list.name.clone().into(),
url: format!("/lists/{}/", list.pk).into(),
url: format!("{root_url_prefix}/lists/{}/", list.pk).into(),
},
];
let context = minijinja::context! {
@ -92,34 +155,36 @@ async fn main() {
hists => &hist,
posts=> posts_ctx,
body=>&list.description.clone().unwrap_or_default(),
root_prefix => "",
list => Value::from_object(MailingList::from(list)),
root_prefix => &root_url_prefix,
list => Value::from_object(MailingList::from(list.clone())),
crumbs => crumbs,
};
Ok(warp::reply::html(
let mut file = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.truncate(true)
.open(&lists_path)
.map_err(|err| format!("could not open {lists_path:?}: {err}"))?;
file.write_all(
TEMPLATES
.get_template("list.html")
.unwrap()
.render(context)
.unwrap_or_else(|err| err.to_string()),
))
});
let conf2 = conf.clone();
let post_handler =
warp::path!("list" / i64 / String).map(move |list_pk: i64, message_id: String| {
let message_id = percent_decode_str(&message_id).decode_utf8().unwrap();
dbg!(&message_id);
let db = Connection::open_db(conf2.clone()).unwrap();
let list = db.list(list_pk).unwrap().unwrap();
let posts = db.list_posts(list_pk, None).unwrap();
let post = posts
.iter()
.find(|p| message_id.contains(p.message_id.as_str().strip_carets()))
.unwrap();
//let mut msg_id = &post.message_id[1..];
//msg_id = &msg_id[..msg_id.len().saturating_sub(1)];
.get_template("list.html")?
.render(context)?
.as_bytes(),
)?;
lists_path.pop();
lists_path.pop();
lists_path.pop();
lists_path.push("list");
lists_path.push(list.pk.to_string());
std::fs::create_dir_all(&lists_path)?;
for post in posts {
let mut msg_id = &post.message_id[1..];
msg_id = &msg_id[..msg_id.len().saturating_sub(1)];
lists_path.push(format!("{msg_id}.html"));
let envelope = melib::Envelope::from_bytes(post.message.as_slice(), None)
.map_err(|err| format!("Could not parse mail {}: {err}", post.message_id)).unwrap();
.map_err(|err| format!("Could not parse mail {}: {err}", post.message_id))?;
let body = envelope.body_bytes(post.message.as_slice());
let body_text = body.text();
let subject = envelope.subject();
@ -135,21 +200,22 @@ async fn main() {
let crumbs = vec![
Crumb {
label: "Lists".into(),
url: "/".into(),
url: format!("{root_url_prefix}/").into(),
},
Crumb {
label: list.name.clone().into(),
url: format!("/lists/{}/", list.pk).into(),
url: format!("{root_url_prefix}/lists/{}/", list.pk).into(),
},
Crumb {
label: subject_ref.to_string().into(),
url: format!("/lists/{}/{message_id}.html/", list.pk).into(),
url: format!("{root_url_prefix}/lists/{}/{message_id}.html/", list.pk).into(),
},
];
let context = minijinja::context! {
title => &list.name,
list => &list,
post => &post,
posts => &posts_ctx,
body => &body_text,
from => &envelope.field_from_to_string(),
date => &envelope.date_as_str(),
@ -158,66 +224,34 @@ async fn main() {
trimmed_subject => subject_ref,
in_reply_to => &envelope.in_reply_to_display().map(|r| r.to_string().as_str().strip_carets().to_string()),
references => &envelope .references() .into_iter() .map(|m| m.to_string().as_str().strip_carets().to_string()) .collect::<Vec<String>>(),
root_prefix => "",
root_prefix => &root_url_prefix,
crumbs => crumbs,
};
Ok(warp::reply::html(
TEMPLATES
.get_template("post.html")
.unwrap()
.render(context)
.unwrap_or_else(|err| err.to_string()),
))
});
let conf3 = conf.clone();
let index_handler = warp::path::end().map(move || {
let db = Connection::open_db(conf3.clone()).unwrap();
let lists_values = db.lists().unwrap();
let lists = lists_values
.iter()
.map(|list| {
let months = db.months(list.pk).unwrap();
let posts = db.list_posts(list.pk, None).unwrap();
minijinja::context! {
title => &list.name,
posts => &posts,
months => &months,
body => &list.description.as_deref().unwrap_or_default(),
root_prefix => "",
list => Value::from_object(MailingList::from(list.clone())),
}
})
.collect::<Vec<_>>();
let crumbs = vec![Crumb {
label: "Lists".into(),
url: "/".into(),
}];
let context = minijinja::context! {
title => "mailing list archive",
description => "",
lists => &lists,
root_prefix => "",
crumbs => crumbs,
};
Ok(warp::reply::html(
TEMPLATES
.get_template("lists.html")
.unwrap()
.render(context)
.unwrap_or_else(|err| err.to_string()),
))
});
let routes = warp::get()
.and(index_handler)
.or(list_handler)
.or(post_handler);
// Note that composing filters for many routes may increase compile times
// (because it uses a lot of generics). If you wish to use dynamic dispatch
// instead and speed up compile times while making it slightly slower at
// runtime, you can use Filter::boxed().
eprintln!("Running at http://127.0.0.1:3030");
warp::serve(routes).run(([127, 0, 0, 1], 3030)).await;
let mut file = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.truncate(true)
.open(&lists_path)
.map_err(|err| format!("could not open {lists_path:?}: {err}"))?;
file.write_all(
TEMPLATES
.get_template("post.html")?
.render(context)?
.as_bytes(),
)?;
lists_path.pop();
}
lists_path.pop();
lists_path.pop();
}
Ok(())
}
fn main() -> std::result::Result<(), i64> {
if let Err(err) = run_app() {
eprintln!("{err}");
return Err(-1);
}
Ok(())
}

View File

@ -18,4 +18,3 @@ path = "src/main.rs"
[dependencies]
mailpot = { version = "^0.1", path = "../core" }
tokio = { version = "^1", features = ["full"] }
warp = "^0.3"

View File

@ -1,5 +1,3 @@
# mailpot REST http server
```shell
cargo run --bin mpot-http
```
Not implemented.

View File

@ -17,73 +17,4 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use mailpot::*;
use warp::Filter;
#[tokio::main]
async fn main() {
let config_path = std::env::args()
.nth(1)
.expect("Expected configuration file path as first argument.");
let conf = Configuration::from_file(config_path).unwrap();
let conf1 = conf.clone();
// GET /lists/:i64/policy
let policy = warp::path!("lists" / i64 / "policy").map(move |list_pk| {
let db = Connection::open_db(conf1.clone()).unwrap();
db.list_post_policy(list_pk)
.ok()
.map(|l| warp::reply::json(&l.unwrap()))
.unwrap()
});
let conf2 = conf.clone();
//get("/lists")]
let lists = warp::path!("lists").map(move || {
let db = Connection::open_db(conf2.clone()).unwrap();
let lists = db.lists().unwrap();
warp::reply::json(&lists)
});
let conf3 = conf.clone();
//get("/lists/<num>")]
let lists_num = warp::path!("lists" / i64).map(move |list_pk| {
let db = Connection::open_db(conf3.clone()).unwrap();
let list = db.list(list_pk).unwrap();
warp::reply::json(&list)
});
let conf4 = conf.clone();
//get("/lists/<num>/subscriptions")]
let lists_subscriptions = warp::path!("lists" / i64 / "subscriptions").map(move |list_pk| {
let db = Connection::open_db(conf4.clone()).unwrap();
db.list_subscriptions(list_pk)
.ok()
.map(|l| warp::reply::json(&l))
.unwrap()
});
//get("/lists/<num>/owners")]
let lists_owners = warp::path!("lists" / i64 / "owners").map(move |list_pk| {
let db = Connection::open_db(conf.clone()).unwrap();
db.list_owners(list_pk)
.ok()
.map(|l| warp::reply::json(&l))
.unwrap()
});
//post("/lists/<num>/owners/add", data = "<new_owner>")]
let lists_owner_add =
warp::post().and(warp::path!("lists" / i64 / "owners" / "add").map(|_list_pk| "todo"));
let routes = warp::get().and(
lists
.or(policy)
.or(lists_num)
.or(lists_subscriptions)
.or(lists_owners)
.or(lists_owner_add),
);
warp::serve(routes).run(([127, 0, 0, 1], 3030)).await;
}
fn main() {}