Compare commits

..

No commits in common. "8c099d05860d37d55c9ee6659a65e35221694d82" and "1bb6bd78e6943989291d02d13590cf1ecb2696bc" have entirely different histories.

6 changed files with 76 additions and 226 deletions

60
Cargo.lock generated
View File

@ -622,19 +622,6 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "env_logger"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0"
dependencies = [
"humantime",
"is-terminal",
"log 0.4.20",
"regex",
"termcolor",
]
[[package]]
name = "equivalent"
version = "1.0.1"
@ -719,14 +706,12 @@ dependencies = [
"http",
"image 0.23.14",
"iron",
"log 0.4.20",
"logger",
"mime 0.3.17",
"mime_guess 2.0.4",
"mustache",
"orizentic",
"params",
"pretty_env_logger",
"router",
"serde 1.0.188",
"serde_json",
@ -1547,12 +1532,6 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "humantime"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "hyper"
version = "0.10.16"
@ -1767,17 +1746,6 @@ dependencies = [
"url 1.7.2",
]
[[package]]
name = "is-terminal"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
dependencies = [
"hermit-abi 0.3.2",
"rustix",
"windows-sys",
]
[[package]]
name = "itertools"
version = "0.10.5"
@ -2666,16 +2634,6 @@ version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "pretty_env_logger"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "865724d4dbe39d9f3dd3b52b88d859d66bcb2d6a0acfd5ea68a65fb66d4bdc1c"
dependencies = [
"env_logger",
"log 0.4.20",
]
[[package]]
name = "proc-macro-crate"
version = "1.3.1"
@ -3463,15 +3421,6 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "termcolor"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64"
dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.11.0"
@ -4130,15 +4079,6 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"

View File

@ -27,5 +27,3 @@ thiserror = "1.0.20"
tokio = { version = "1", features = [ "full" ] }
uuid = { version = "0.4", features = [ "serde", "v4" ] }
warp = { version = "0.3" }
pretty_env_logger = { version = "0.5" }
log = { version = "0.4" }

View File

@ -2,7 +2,6 @@ use build_html::{self, Html, HtmlContainer};
#[derive(Clone, Debug)]
pub struct Form {
path: String,
method: String,
encoding: Option<String>,
elements: String,
@ -11,18 +10,12 @@ pub struct Form {
impl Form {
pub fn new() -> Self {
Self {
path: "/".to_owned(),
method: "get".to_owned(),
encoding: None,
elements: "".to_owned(),
}
}
pub fn with_path(mut self, path: &str) -> Self {
self.path = path.to_owned();
self
}
pub fn with_method(mut self, method: &str) -> Self {
self.method = method.to_owned();
self
@ -37,12 +30,11 @@ impl Form {
impl Html for Form {
fn to_html_string(&self) -> String {
let encoding = match self.encoding {
Some(ref encoding) => format!("encoding=\"{encoding}\"", encoding = encoding),
Some(ref encoding) => format!("encoding={encoding}", encoding = encoding),
None => format!(""),
};
format!(
"<form action=\"{path}\" method=\"{method}\" {encoding}>\n{elements}\n</form>\n",
path = self.path,
"<form method={method} {encoding}>\n{elements}\n</form>\n",
method = self.method,
encoding = encoding,
elements = self.elements.to_html_string()
@ -60,58 +52,36 @@ impl HtmlContainer for Form {
pub struct Input {
ty: String,
name: String,
id: Option<String>,
id: String,
value: Option<String>,
content: Option<String>,
}
impl Html for Input {
fn to_html_string(&self) -> String {
let id = match self.id {
Some(ref id) => format!("id=\"{}\"", id),
None => "".to_owned(),
};
let value = match self.value {
Some(ref value) => format!("value=\"{}\"", value),
None => "".to_owned(),
};
format!(
"<input type=\"{ty}\" name=\"{name}\" {id} {value}>{content}</input>\n",
"<input type=\"{ty}\" name=\"{name}\" id=\"{id}\">{value}</input>\n",
ty = self.ty,
name = self.name,
id = id,
value = value,
content = self.content.clone().unwrap_or("".to_owned()),
id = self.id,
value = self.value.clone().unwrap_or("".to_owned()),
)
}
}
impl Input {
pub fn new(ty: &str, name: &str) -> Self {
pub fn new(ty: &str, name: &str, id: &str) -> Self {
Self {
ty: ty.to_owned(),
name: name.to_owned(),
id: None,
id: id.to_owned(),
value: None,
content: None,
}
}
pub fn with_id(mut self, val: &str) -> Self {
self.id = Some(val.to_owned());
self
}
pub fn with_value(mut self, val: &str) -> Self {
self.value = Some(val.to_owned());
self
}
pub fn with_content(mut self, val: &str) -> Self {
self.content = Some(val.to_owned());
self
}
}
#[derive(Clone, Debug)]
@ -141,29 +111,25 @@ impl Html for Label {
#[derive(Clone, Debug)]
pub struct Button {
name: Option<String>,
label: String,
name: String,
text: String,
}
impl Button {
pub fn new(label: &str) -> Self {
pub fn new(name: &str, text: &str) -> Self {
Self {
name: None,
label: label.to_owned(),
name: name.to_owned(),
text: text.to_owned(),
}
}
}
impl Html for Button {
fn to_html_string(&self) -> String {
let name = match self.name {
Some(ref name) => format!("name={}", name),
None => "".to_owned(),
};
format!(
"<button {name}>{label}</button>",
name = name,
label = self.label
"<button name={name}>{text}</button>",
name = self.name,
text = self.text
)
}
}

View File

@ -43,7 +43,7 @@ impl App {
FileInfo::open(&id, &self.files_root)
}
pub fn get_file(&self, id: &str) -> Result<(FileInfo, std::fs::File), FileError> {
pub fn get_file(&self, id: String) -> Result<(FileInfo, std::fs::File), FileError> {
let f = File::open(&id, &self.files_root)?;
let info = f.info();
let stream = f.stream()?;

View File

@ -6,15 +6,11 @@ use iron::prelude::*;
use iron::response::BodyReader;
use iron::status;
*/
#[macro_use]
extern crate log;
use http::status::StatusCode;
// use mustache::{compile_path, Template};
// use orizentic::{Permissions, ResourceName, Secret};
use build_html::Html;
use std::{
collections::HashMap,
io::Read,
net::{IpAddr, Ipv4Addr, SocketAddr},
path::Path,
@ -225,28 +221,6 @@ fn script(_: &mut Request) -> IronResult<Response> {
}
*/
fn serve_file(
info: FileInfo,
mut file: std::fs::File,
old_etags: Option<String>,
) -> http::Result<http::Response<Vec<u8>>> {
let mut content = Vec::new();
match old_etags {
Some(old_etags) if old_etags != info.hash => warp::http::Response::builder()
.header("content-type", info.file_type)
.status(StatusCode::NOT_MODIFIED)
.body(content),
_ => {
let _ = file.read_to_end(&mut content);
warp::http::Response::builder()
.header("content-type", info.file_type)
.header("etag", info.hash)
.status(StatusCode::OK)
.body(content)
}
}
}
#[tokio::main]
pub async fn main() {
/*
@ -258,6 +232,21 @@ pub async fn main() {
let mut router = Router::new();
router.get(
"/:id",
files::GetFileHandler {
app: app.clone(),
template: compile_path("templates/file.html").expect("the template to compile"),
},
"get-file-page",
);
router.get(
"/:id/raw",
files::GetHandler { app: app.clone() },
"get-file",
);
router.post("/", files::PostHandler { app: app.clone() }, "upload-file");
router.delete(
@ -290,18 +279,13 @@ pub async fn main() {
.await;
*/
pretty_env_logger::init();
let app = Arc::new(RwLock::new(App::new(Path::new(
&std::env::var("FILE_SHARE_DIR").unwrap(),
))));
let log = warp::log("file_service");
let root = warp::path!().and(warp::get()).map({
let root = warp::path!().map({
let app = app.clone();
move || {
info!("root handler");
warp::http::Response::builder()
.header("content-type", "text/html")
.status(StatusCode::OK)
@ -309,66 +293,37 @@ pub async fn main() {
}
});
let post_handler = warp::path!(String)
.and(warp::post())
.and(warp::filters::body::form())
.map(|id: String, form: HashMap<String, String>| {
info!("post_delete {}", id);
info!("form: {:?}", form);
warp::http::Response::builder()
.header("location", "/")
.status(StatusCode::SEE_OTHER)
.body(vec![])
});
let thumbnail = warp::path!(String / "tn")
.and(warp::get())
.and(warp::header::optional::<String>("if-none-match"))
.map({
let app = app.clone();
move |id: String, old_etags: Option<String>| match app
.read()
.unwrap()
.get_thumbnail(&id)
{
Ok((info, file)) => serve_file(info, file, old_etags),
move |id: String, old_etags: Option<String>| {
let mut content = Vec::new();
match app.read().unwrap().get_thumbnail(&id) {
Ok((info, mut stream)) => match old_etags {
Some(old_etags) if old_etags != info.hash => {
warp::http::Response::builder()
.header("content-type", info.file_type)
.status(StatusCode::NOT_MODIFIED)
.body(content)
}
_ => {
let _ = stream.read_to_end(&mut content);
warp::http::Response::builder()
.header("content-type", info.file_type)
.header("etag", info.hash)
.status(StatusCode::OK)
.body(content)
}
},
Err(_err) => warp::http::Response::builder()
.status(StatusCode::NOT_FOUND)
.body(vec![]),
.body(content),
}
}
});
let file = warp::path!(String)
.and(warp::get())
.and(warp::header::optional::<String>("if-none-match"))
.map({
let app = app.clone();
move |id: String, old_etags: Option<String>| match app.read().unwrap().get_file(&id) {
Ok((info, file)) => serve_file(info, file, old_etags),
Err(_err) => warp::http::Response::builder()
.status(StatusCode::NOT_FOUND)
.body(vec![]),
}
});
let upload = warp::path!().and(warp::post()).map(|| {
println!("upload");
warp::reply()
});
let delete = warp::path!(String).and(warp::delete()).map(|id: String| {
println!("delete {}", id);
warp::reply()
});
let server = warp::serve(
root.or(post_handler)
.or(file)
.or(thumbnail)
.or(upload)
.or(delete)
.with(log),
);
let server = warp::serve(root.or(thumbnail));
server
.run(SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 8002))
.await;

View File

@ -11,33 +11,17 @@ pub fn index(files: Vec<Result<File, FileError>>) -> build_html::HtmlPage {
.with_encoding("multipart/form-data")
.with_container(
Container::new(ContainerType::Div)
.with_html(Input::new("file", "file"))
.with_html(Input::new("file", "file", "file-selector-input"))
.with_html(Label::new("for-selector-input", "Select a file")),
)
.with_html(Button::new("Upload file")),
.with_html(Button::new("upload", "Upload file")),
);
for file in files {
let container = match file {
Ok(ref file) => thumbnail(file).with_html(
Form::new()
.with_path(&format!("/{}", file.info().id))
.with_method("post")
.with_html(Input::new("hidden", "_method").with_value("delete"))
.with_html(Button::new("Delete")),
),
Err(err) => Container::new(ContainerType::Div)
.with_attributes(vec![("class", "file")])
.with_paragraph(format!("{:?}", err)),
};
page.add_container(container)
}
page
}
pub fn thumbnail(file: &File) -> Container {
let mut container = Container::new(ContainerType::Div).with_attributes(vec![("class", "file")]);
let mut container =
Container::new(ContainerType::Div).with_attributes(vec![("class", "file")]);
match file {
Ok(file) => {
let tn = Container::new(ContainerType::Div)
.with_attributes(vec![("class", "thumbnail")])
.with_link(
@ -45,5 +29,12 @@ pub fn thumbnail(file: &File) -> Container {
Image::new(&format!("{}/tn", file.info().id)).to_html_string(),
);
container.add_html(tn);
container
}
Err(err) => {
container.add_paragraph(format!("{:?}", err));
}
}
page.add_container(container);
}
page
}