init
This commit is contained in:
commit
0e5a6de323
10 changed files with 2166 additions and 0 deletions
89
src/routes.rs
Normal file
89
src/routes.rs
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
use crate::config::{AppConfig, normalize_extension};
|
||||
use content_inspector::ContentType;
|
||||
use rocket::data::{Data, ToByteUnit};
|
||||
use rocket::{State, http::Status, response::content::RawHtml};
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
use tempfile::NamedTempFile;
|
||||
use tokio::fs as async_fs;
|
||||
|
||||
#[get("/")]
|
||||
pub fn index() -> Option<RawHtml<String>> {
|
||||
let raw: &str = include_str!("assets/editor.html");
|
||||
Some(RawHtml(raw.replace("$%{defaultText}%$", "")))
|
||||
}
|
||||
|
||||
#[get("/<id>?<raw>")]
|
||||
pub async fn get_file(id: &str, raw: Option<bool>, config: &State<AppConfig>) -> Result<String, Status> {
|
||||
let file_path = Path::new(&config.upload_dir).join(id);
|
||||
|
||||
if file_path.exists() {
|
||||
if let Ok(content) = async_fs::read_to_string(file_path).await {
|
||||
let is_mozilla = std::env::var("HTTP_USER_AGENT")
|
||||
.as_deref()
|
||||
.unwrap_or("")
|
||||
.contains("Mozilla");
|
||||
|
||||
if raw.unwrap_or(false) || !is_mozilla {
|
||||
return Ok(content);
|
||||
}
|
||||
|
||||
let html: &str = include_str!("assets/editor.html");
|
||||
return Ok(html.replace("$%{defaultText}%$", &content));
|
||||
}
|
||||
}
|
||||
|
||||
Err(Status::NotFound)
|
||||
}
|
||||
|
||||
#[put("/<file_name>", data = "<data>")]
|
||||
pub async fn upload(file_name: &str, data: Data<'_>, config: &State<AppConfig>) -> Result<String, Status> {
|
||||
let extension = Path::new(file_name)
|
||||
.extension()
|
||||
.and_then(|ext| ext.to_str())
|
||||
.map(normalize_extension)
|
||||
.unwrap_or_else(|| ".txt".to_string());
|
||||
|
||||
if !config.is_extension_allowed(&extension) {
|
||||
return Err(Status::UnsupportedMediaType);
|
||||
}
|
||||
|
||||
let upload_dir = Path::new(&config.upload_dir);
|
||||
let limit = config.max_upload_size().unwrap_or(u64::MAX);
|
||||
let id = loop {
|
||||
let candidate = nanoid::format(nanoid::rngs::default, &nanoid::alphabet::SAFE[..], config.id_length);
|
||||
let save_name = format!("{}{}", candidate, extension);
|
||||
|
||||
if !upload_dir.join(save_name).exists() {
|
||||
break candidate;
|
||||
}
|
||||
};
|
||||
|
||||
if !upload_dir.exists() {
|
||||
fs::create_dir_all(upload_dir).map_err(|_| Status::InternalServerError)?;
|
||||
}
|
||||
|
||||
let mut temp = NamedTempFile::new_in(&config.upload_dir)
|
||||
.map_err(|_| Status::InternalServerError)?;
|
||||
|
||||
let stream = data.open(limit.bytes());
|
||||
let bytes = stream.into_bytes().await
|
||||
.map_err(|_| Status::InternalServerError)?;
|
||||
|
||||
if !bytes.is_complete() {
|
||||
return Err(Status::PayloadTooLarge);
|
||||
}
|
||||
|
||||
if config.should_block_binary() && matches!(content_inspector::inspect(bytes.as_ref()), ContentType::BINARY) {
|
||||
return Err(Status::UnsupportedMediaType);
|
||||
}
|
||||
|
||||
temp.write_all(&bytes)
|
||||
.map_err(|_| Status::InternalServerError)?;
|
||||
|
||||
temp.persist(Path::new(&config.upload_dir).join(format!("{}{}", id, extension)))
|
||||
.map_err(|_| Status::InternalServerError)?;
|
||||
|
||||
Ok(format!("{}/{}{}", config.base_url.trim_end_matches('/'), id, extension))
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue