From 145f7cfd4035150d1f3d0d3d6923afe99114dc5a Mon Sep 17 00:00:00 2001 From: shim_ <> Date: Sun, 4 Nov 2018 15:13:45 +0100 Subject: [PATCH] works(isch) --- .dockerignore | 5 + .gitignore | 11 ++ .idea/libraries/Cargo__brownpaper_.xml | 44 +++++++ .idea/vcs.xml | 6 + Cargo.toml | 16 +++ Dockerfile | 9 ++ brownpaper.iml | 17 +++ src/main.rs | 158 +++++++++++++++++++++++++ 8 files changed, 266 insertions(+) create mode 100644 .dockerignore create mode 100644 .gitignore create mode 100644 .idea/libraries/Cargo__brownpaper_.xml create mode 100644 .idea/vcs.xml create mode 100644 Cargo.toml create mode 100644 Dockerfile create mode 100644 brownpaper.iml create mode 100644 src/main.rs diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..b23303f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +.* +target/*/deps +target/*/build +target/*/.fingerprint +target/*/incremental diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2a58023 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +# Generated by Cargo +# will have compiled files and executables +/target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock +Cargo.lock + +#Intellj +.iml +.idea diff --git a/.idea/libraries/Cargo__brownpaper_.xml b/.idea/libraries/Cargo__brownpaper_.xml new file mode 100644 index 0000000..62dd3a4 --- /dev/null +++ b/.idea/libraries/Cargo__brownpaper_.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..b56f667 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "brownpaper" +version = "0.1.0" +authors = ["shim_ "] + +[dependencies] + +snap = "0.1" + +rustc-serialize = "0.3.19" + +iron = "0.6.0" + +rand = "0.4.2" + +chrono = { version = "0.2", features = ["rustc-serialize"] } \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..9d1951b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,9 @@ +FROM scratch + +VOLUME /snips + +EXPOSE 3000 + +COPY target/x86_64-unknown-linux-musl/release/brownpaper /bin/ + +ENTRYPOINT [ "/bin/brownpaper" ] \ No newline at end of file diff --git a/brownpaper.iml b/brownpaper.iml new file mode 100644 index 0000000..580f111 --- /dev/null +++ b/brownpaper.iml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..c4a2664 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,158 @@ +extern crate chrono; +extern crate iron; +extern crate rand; +extern crate snap; + +use chrono::*; +use iron::method::Method; +use iron::modifiers::Redirect; +use iron::prelude::*; +use iron::Url; +use rand::Rng; +use std::fs; +use std::fs::File; +use std::io; +use std::io::prelude::*; +use std::iter::Iterator; +use std::path::{Path, PathBuf}; + +struct Snippet<'a> { + id: String, + storage: &'a SnippetStorage<'a>, +} + +struct SnippetMeta { + created: DateTime, + compression: Option, +} + +struct SnippetStorage<'a> { + directory: &'a Path, +} + +impl<'a> Snippet<'a> { + pub fn random(storage: &'a SnippetStorage) -> Snippet<'a> { + Snippet::new( + &rand::thread_rng() + .gen_ascii_chars() + .take(6) + .collect::(), + storage, + ) + } + + pub fn new(id: &str, storage: &'a SnippetStorage) -> Snippet<'a> { + Snippet { + id: id.to_string(), + storage, + } + } + + pub fn path(&self) -> PathBuf { + self.storage.directory.join(&self.id) + } + + fn metadata(&self) -> Result { + unimplemented!(); + } + + fn contents(&self) -> Result { + let mut file = File::open(self.path())?; + let mut text = String::new(); + file.read_to_string(&mut text)?; + Ok(text) + } + + fn write(self, content: &str) -> Result, io::Error> { + fs::write(self.path(), content).map(|_| self) + } +} + +impl<'a> SnippetStorage<'a> { + pub fn new(directory: &'a Path) -> SnippetStorage<'a> { + SnippetStorage { + directory: directory, + } + } + + fn has(&self, id: &str) -> bool { + self.directory.join(id).exists() + } + + fn open(&self, id: &str) -> Option { + if self.has(id) { + Some(Snippet::new(id, self)) + } else { + None + } + } +} + +#[cfg(not(debug_assertions))] +const STORAGE_DIR: &str = "/snips"; + +#[cfg(debug_assertions)] +const STORAGE_DIR: &str = "/tmp"; + +fn handle(req: &mut Request) -> IronResult { + println!("{}", req.url); + let storage = SnippetStorage::new(&Path::new(STORAGE_DIR)); + match req.method { + Method::Post => { + let segments: Vec<&str> = req.url.path(); + if segments.first().iter().all(|seg| *seg == &"new") { + let snip = { + let text: String = { + let bytes = ((&mut req.body).bytes().take(1024 * 512).collect::,io::Error>>()).map_err(|err| IronError::new(err, ""))?; + String::from_utf8(bytes) + .map_err(|err| IronError::new(err, "Invalid utf8"))? + }; + Snippet::random(&storage) + .write(&*text) + .map_err(|err| IronError::new(err, "Failed to save snippet")) + }; + snip.map(|snip| { + let mut snip_url = req.url.clone().into_generic_url(); + snip_url.set_path(&*("/".to_string() + &*snip.id)); + /*Response::with(( + iron::status::TemporaryRedirect, + Redirect(Url::from_generic_url(snip_url).unwrap()), + ))*/ + Response::with(( + iron::status::Ok, + format!("", snip_url) + )) + }) + } else { + Ok(Response::with((iron::status::BadRequest, "Post to /new or die"))) + } + } + Method::Get => { + let segments: Vec<&str> = req + .url + .path() + .into_iter() + .filter(|seg| seg.len() > 0) + .collect(); + if segments.len() == 1 { + let id = &segments[0]; + let att = storage.open(&id).map(|snip| snip.contents()).map(|res| { + Response::with( + res.map(|text| (iron::status::Ok, text)) + .unwrap_or((iron::status::InternalServerError, "..".to_string())), + ) + }); + Ok(att.unwrap_or(Response::with((iron::status::NotFound, "Not here sry")))) + } else { + Ok(Response::with((iron::status::NotFound, "Wrong path pal"))) + } + } + _ => Ok(Response::with((iron::status::BadRequest, "Give or take"))), + } +} + +fn main() { + let chain = Chain::new(handle); + println!("Starting brownpaper: {}", STORAGE_DIR); + Iron::new(chain).http("0.0.0.0:3000").unwrap(); +}