More refactoring
This commit is contained in:
parent
d99445ab11
commit
2b62a7e1da
98
src/main.rs
98
src/main.rs
@ -32,7 +32,7 @@ use mpu::MultipartUpload;
|
||||
|
||||
const HOST: &'static str = "http://localhost:8000";
|
||||
|
||||
const UPLOAD_MAX_SIZE: u64 = 8 * 1024 * 1024;
|
||||
type Result<T> = ::std::result::Result<T, Error>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
@ -67,7 +67,7 @@ impl From<toml::de::Error> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Default, Debug)]
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
struct PasteInfo<'a> {
|
||||
// these never change
|
||||
key: Option<PasteID<'a>>, // key to update/delete paste with
|
||||
@ -79,8 +79,21 @@ struct PasteInfo<'a> {
|
||||
num_views: u32, // Only incremented if delete_after_num_views is Some, otherwise 0
|
||||
}
|
||||
|
||||
impl<'a> Default for PasteInfo<'a> {
|
||||
fn default() -> Self {
|
||||
PasteInfo {
|
||||
key: None,
|
||||
delete_after: Some(SystemTime::now() + Duration::from_secs(2592000)), // default to 30 days
|
||||
delete_after_num_views:None,
|
||||
delete_if_not_viewed_in_last_seconds: None,
|
||||
last_viewed: None,
|
||||
num_views: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PasteInfo<'a> {
|
||||
fn read<P: AsRef<Path>>(path: P) -> ::std::result::Result<PasteInfo<'static>,Error> {
|
||||
fn read<P: AsRef<Path>>(path: P) -> Result<PasteInfo<'static>> {
|
||||
let mut f = File::open(path)?;
|
||||
let mut input = String::new();
|
||||
f.read_to_string(&mut input)?;
|
||||
@ -88,7 +101,7 @@ impl<'a> PasteInfo<'a> {
|
||||
Ok(paste_info)
|
||||
}
|
||||
|
||||
fn write<P: AsRef<Path>>(&self, path: P) -> ::std::result::Result<(),Error> {
|
||||
fn write<P: AsRef<Path>>(&self, path: P) -> Result<()> {
|
||||
let toml = toml::to_string(&self)?;
|
||||
fs::write(path, toml)?;
|
||||
Ok(())
|
||||
@ -101,7 +114,7 @@ impl<'a> PasteInfo<'a> {
|
||||
|| self.delete_if_not_viewed_in_last_seconds.map(|n| (SystemTime::now() - n) > self.last_viewed.unwrap()).unwrap_or(false)
|
||||
}
|
||||
|
||||
fn mark_viewed_and_write<P: AsRef<Path>>(&mut self, path: P) -> ::std::result::Result<(),Error> {
|
||||
fn mark_viewed_and_write<P: AsRef<Path>>(&mut self, path: P) -> Result<()> {
|
||||
let mut must_write = false;
|
||||
if self.delete_after_num_views.is_some() {
|
||||
must_write = true;
|
||||
@ -178,27 +191,48 @@ impl Backend {
|
||||
(format!("upload/{id}/file", id = id), format!("upload/{id}/info", id = id), format!("upload/{id}", id = id))
|
||||
}
|
||||
|
||||
fn upload(&self, paste: Data, _key: Option<PasteID>) -> io::Result<String> {
|
||||
fn upload(&self, paste: Data, _key: Option<PasteID>) -> Result<String> {
|
||||
let (filename, info_filename, url) = self.new_paste();
|
||||
|
||||
PasteInfo::default().write(info_filename)?;
|
||||
paste.stream_to_file(Path::new(&filename))?;
|
||||
Ok(url)
|
||||
}
|
||||
|
||||
fn upload_multipart(&self, paste: MultipartUpload) -> io::Result<String> {
|
||||
fn upload_multipart(&self, paste: MultipartUpload) -> Result<String> {
|
||||
let (filename, info_filename, url) = self.new_paste();
|
||||
PasteInfo::default().write(info_filename)?;
|
||||
paste.stream_to_file(Path::new(&filename))?;
|
||||
Ok(url)
|
||||
}
|
||||
|
||||
fn upload_string(&self, paste: &PasteForm) -> ::std::result::Result<String,Error> {
|
||||
fn upload_string(&self, paste: &PasteForm) -> Result<String> {
|
||||
let (filename, info_filename, url) = self.new_paste();
|
||||
PasteInfo::from(paste).write(info_filename)?;
|
||||
fs::write(filename, &paste.content)?;
|
||||
Ok(url)
|
||||
}
|
||||
|
||||
fn get(&self, id: PasteID) -> ::std::result::Result<content::Plain<File>,Error> {
|
||||
fn upload_tcp_stream(&self, mut stream: TcpStream) -> Result<()>
|
||||
{
|
||||
let (filename, info_filename, url) = self.new_paste();
|
||||
|
||||
PasteInfo::default().write(info_filename)?;
|
||||
|
||||
let mut paste_file = File::create(&filename)?;
|
||||
|
||||
let timeout = Some(Duration::new(5, 0)); // todo: make this config store in struct
|
||||
stream.set_read_timeout(timeout)?;
|
||||
stream.set_write_timeout(timeout)?;
|
||||
|
||||
stream.write(&url.into_bytes())?;
|
||||
stream.flush()?;
|
||||
|
||||
let upload_max_size: u64 = 8 * 1024 * 1024; // todo: make this config store in struct
|
||||
copy(&mut stream, &mut paste_file, upload_max_size)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get(&self, id: PasteID) -> Result<content::Plain<File>> {
|
||||
let (filename, info_filename, foldername) = self.file_paths(id);
|
||||
let mut paste_info = PasteInfo::read(&info_filename)?;
|
||||
// first check if we should delete this
|
||||
@ -247,43 +281,43 @@ impl<'a> From<&'a PasteForm> for PasteInfo<'a> {
|
||||
|
||||
// todo: change /w to /, shouldn't conflict because of format, but it does currently
|
||||
#[post("/w", format = "application/x-www-form-urlencoded", data = "<paste>")]
|
||||
fn web_post(backend: &Backend, paste: LenientForm<PasteForm>) -> ::std::result::Result<String,Error> {
|
||||
fn web_post(backend: &Backend, paste: LenientForm<PasteForm>) -> Result<String> {
|
||||
backend.upload_string(paste.get())
|
||||
}
|
||||
|
||||
// todo: change /w to /, shouldn't conflict because of format, but it does currently
|
||||
#[post("/m", format = "multipart/form-data", data = "<paste>")]
|
||||
fn mpu_post(backend: &Backend, paste: MultipartUpload) -> io::Result<String> {
|
||||
fn mpu_post(backend: &Backend, paste: MultipartUpload) -> Result<String> {
|
||||
backend.upload_multipart(paste)
|
||||
}
|
||||
|
||||
#[put("/", data = "<paste>")]
|
||||
fn upload_put(backend: &Backend, paste: Data) -> io::Result<String> {
|
||||
fn upload_put(backend: &Backend, paste: Data) -> Result<String> {
|
||||
backend.upload(paste, None)
|
||||
}
|
||||
|
||||
#[post("/", data = "<paste>")]
|
||||
fn upload_post(backend: &Backend, paste: Data) -> io::Result<String> {
|
||||
fn upload_post(backend: &Backend, paste: Data) -> Result<String> {
|
||||
backend.upload(paste, None)
|
||||
}
|
||||
|
||||
#[patch("/", data = "<paste>")]
|
||||
fn upload_patch(backend: &Backend, paste: Data) -> io::Result<String> {
|
||||
fn upload_patch(backend: &Backend, paste: Data) -> Result<String> {
|
||||
backend.upload(paste, None)
|
||||
}
|
||||
|
||||
#[put("/<key>", data = "<paste>")]
|
||||
fn upload_put_key(backend: &Backend, paste: Data, key: PasteID) -> io::Result<String> {
|
||||
fn upload_put_key(backend: &Backend, paste: Data, key: PasteID) -> Result<String> {
|
||||
backend.upload(paste, Some(key))
|
||||
}
|
||||
|
||||
#[post("/<key>", data = "<paste>")]
|
||||
fn upload_post_key(backend: &Backend, paste: Data, key: PasteID) -> io::Result<String> {
|
||||
fn upload_post_key(backend: &Backend, paste: Data, key: PasteID) -> Result<String> {
|
||||
backend.upload(paste, Some(key))
|
||||
}
|
||||
|
||||
#[patch("/<key>", data = "<paste>")]
|
||||
fn upload_patch_key(backend: &Backend, paste: Data, key: PasteID) -> io::Result<String> {
|
||||
fn upload_patch_key(backend: &Backend, paste: Data, key: PasteID) -> Result<String> {
|
||||
backend.upload(paste, Some(key))
|
||||
}
|
||||
|
||||
@ -299,8 +333,9 @@ fn delete(id: PasteID, _key: PasteID) -> Option<content::Plain<File>> {
|
||||
}
|
||||
|
||||
#[get("/")]
|
||||
fn index() -> io::Result<NamedFile> {
|
||||
NamedFile::open("static/index.html")
|
||||
fn index() -> Result<NamedFile> {
|
||||
let index = NamedFile::open("static/index.html")?;
|
||||
Ok(index)
|
||||
}
|
||||
|
||||
#[get("/static/<file..>")]
|
||||
@ -320,7 +355,7 @@ fn rocket() -> rocket::Rocket {
|
||||
}
|
||||
|
||||
// adapted from io::copy
|
||||
fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64>
|
||||
fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W, upload_max_size: u64) -> io::Result<u64>
|
||||
where R: Read, W: Write
|
||||
{
|
||||
let mut buf : [u8; 8192] = [0; 8192];
|
||||
@ -335,40 +370,23 @@ fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64>
|
||||
};
|
||||
writer.write_all(&buf[..len])?;
|
||||
written += len as u64;
|
||||
if written > UPLOAD_MAX_SIZE {
|
||||
if written > upload_max_size {
|
||||
return Err(std::io::Error::from(std::io::ErrorKind::InvalidData))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn consume_paste(backend: &Backend, mut stream: TcpStream, timeout: Option<Duration>) -> io::Result<()>
|
||||
{
|
||||
let (filename, _info_filename, url) = backend.new_paste();
|
||||
|
||||
let mut paste_file = File::create(&filename)?;
|
||||
|
||||
stream.set_read_timeout(timeout)?;
|
||||
stream.set_write_timeout(timeout)?;
|
||||
|
||||
stream.write(&url.into_bytes())?;
|
||||
stream.flush()?;
|
||||
|
||||
copy(&mut stream, &mut paste_file)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run_tcp(){
|
||||
// Bind the server's socket
|
||||
thread::spawn(|| {
|
||||
let backend = &Backend::PlainFile;
|
||||
let timeout = Some(Duration::new(5, 0));
|
||||
let listener = TcpListener::bind("127.0.0.1:12345").unwrap();
|
||||
|
||||
loop {
|
||||
match listener.accept() {
|
||||
Ok((mut stream, _addr)) => {
|
||||
thread::spawn(move || {
|
||||
consume_paste(backend, stream, timeout).is_ok(); // again we don't care about this error
|
||||
backend.upload_tcp_stream(stream).is_ok(); // again we don't care about this error
|
||||
});
|
||||
},
|
||||
Err(_e) => {
|
||||
|
Loading…
Reference in New Issue
Block a user