Add cache-busting and server headers with a wrapper.

In order to support custom headers for various response types,
  this commit adds a wrapper type, ResponseWrapper, which can service
  all types of response in `bin`.

For paste objects, the preferred `Last-Modified` is used, so that caches
  can compare their exact timings with the HEAD response when
  revalidating.

For static objects, an `ETag` is used instead, based on the Cargo version
  and git hash of the codebase at compilation time; a `build.rs` is used
  for this.
This commit is contained in:
Leonora Tindall 2022-02-04 13:47:30 -06:00 committed by Gunwant Jain
parent 55ed495b83
commit 2ab7ddb9c8
12 changed files with 292 additions and 153 deletions

146
Cargo.lock generated
View File

@ -101,11 +101,14 @@ name = "bin"
version = "2.0.0"
dependencies = [
"clap",
"once_cell",
"rand",
"rocket",
"rocket_dyn_templates",
"rust-embed",
"sha256",
"syntect",
"time 0.3.7",
"tree_magic",
]
@ -247,9 +250,9 @@ dependencies = [
[[package]]
name = "clap"
version = "3.0.9"
version = "3.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c506244a13c87262f84bf16369740d0b7c3850901b6a642aa41b031a710c473"
checksum = "b63edc3f163b3c71ec8aa23f9bd6070f77edbf3d1d198b164afa90ff00e4ec62"
dependencies = [
"atty",
"bitflags",
@ -264,9 +267,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "3.0.6"
version = "3.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "517358c28fcef6607bf6f76108e02afad7e82297d132a6b846dcc1fc3efcd153"
checksum = "9a1132dc3944b31c20dd8b906b3a9f0a5d0243e092d59171414969657ac6aa85"
dependencies = [
"heck",
"proc-macro-error",
@ -312,9 +315,9 @@ dependencies = [
[[package]]
name = "crc32fast"
version = "1.3.0"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "738c290dfaea84fc1ca15ad9c168d083b05a714e1efddd8edaab678dc28d2836"
checksum = "a2209c310e29876f7f0b2721e7e26b84aff178aa3da5d091f9bfbf47669e60e3"
dependencies = [
"cfg-if 1.0.0",
]
@ -415,9 +418,9 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
[[package]]
name = "fastrand"
version = "1.6.0"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "779d043b6a0b90cc4c0ed7ee380a6504394cee7efd7db050e3774eee387324b2"
checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
dependencies = [
"instant",
]
@ -671,9 +674,9 @@ dependencies = [
[[package]]
name = "h2"
version = "0.3.10"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c9de88456263e249e241fcd211d3954e2c9b0ef7ccfc235a444eb367cae3689"
checksum = "d9f1f717ddc7b2ba36df7e871fd88db79326551d3d6f1fc406fbfd28b582ff8e"
dependencies = [
"bytes",
"fnv",
@ -709,6 +712,12 @@ dependencies = [
"libc",
]
[[package]]
name = "hex"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "http"
version = "0.2.6"
@ -882,9 +891,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.112"
version = "0.2.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c"
[[package]]
name = "line-wrap"
@ -912,9 +921,9 @@ dependencies = [
[[package]]
name = "lock_api"
version = "0.4.5"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109"
checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b"
dependencies = [
"scopeguard",
]
@ -1159,6 +1168,15 @@ dependencies = [
"libc",
]
[[package]]
name = "num_threads"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97ba99ba6393e2c3734791401b66902d981cb03bf190af674ca69949b6d5fb15"
dependencies = [
"libc",
]
[[package]]
name = "once_cell"
version = "1.9.0"
@ -1225,7 +1243,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
dependencies = [
"instant",
"lock_api 0.4.5",
"lock_api 0.4.6",
"parking_lot_core 0.8.5",
]
@ -1415,7 +1433,7 @@ dependencies = [
"indexmap",
"line-wrap",
"serde",
"time 0.3.5",
"time 0.3.7",
"xml-rs",
]
@ -1479,9 +1497,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.14"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d"
checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
dependencies = [
"proc-macro2",
]
@ -1792,18 +1810,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "serde"
version = "1.0.133"
version = "1.0.136"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a"
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.133"
version = "1.0.136"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed201699328568d8d08208fdd080e3ff594e6c422e438b6705905da01005d537"
checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
dependencies = [
"proc-macro2",
"quote",
@ -1812,9 +1830,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.75"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c059c05b48c5c0067d4b4b2b4f0732dd65feb52daf7e0ea09cd87e7dadc1af79"
checksum = "d23c1ba4cf0efd44be32017709280b32d1cea5c3f1275c3b6d9e8bc54f758085"
dependencies = [
"itoa 1.0.1",
"ryu",
@ -1861,6 +1879,16 @@ dependencies = [
"opaque-debug 0.3.0",
]
[[package]]
name = "sha256"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e84a7f596c081d359de5e06a83877138bc3c4483591e1af1916e1472e6e146e"
dependencies = [
"hex",
"sha2",
]
[[package]]
name = "sharded-slab"
version = "0.1.4"
@ -1881,9 +1909,9 @@ dependencies = [
[[package]]
name = "siphasher"
version = "0.3.8"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba1eead9e94aa5a2e02de9e7839f96a007f686ae7a1d57c7797774810d24908a"
checksum = "a86232ab60fa71287d7f2ddae4a7073f6b7aac33631c3015abb556f08c6d0a3e"
[[package]]
name = "slab"
@ -1908,9 +1936,9 @@ checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
[[package]]
name = "socket2"
version = "0.4.2"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516"
checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
dependencies = [
"libc",
"winapi 0.3.9",
@ -2006,9 +2034,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.85"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7"
checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
dependencies = [
"proc-macro2",
"quote",
@ -2090,9 +2118,9 @@ checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
[[package]]
name = "thread_local"
version = "1.1.3"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd"
checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
dependencies = [
"once_cell",
]
@ -2114,12 +2142,13 @@ dependencies = [
[[package]]
name = "time"
version = "0.3.5"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41effe7cfa8af36f439fac33861b66b049edc6f9a32331e2312660529c1c24ad"
checksum = "004cbc98f30fa233c61a38bc77e96a9106e65c88f2d3bef182ae952027e5753d"
dependencies = [
"itoa 0.4.8",
"itoa 1.0.1",
"libc",
"num_threads",
]
[[package]]
@ -2147,9 +2176,9 @@ dependencies = [
[[package]]
name = "tokio"
version = "1.15.0"
version = "1.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838"
checksum = "0c27a64b625de6d309e8c57716ba93021dccf1b3b5c97edd6d3dd2d2135afc0a"
dependencies = [
"bytes",
"libc",
@ -2216,9 +2245,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
[[package]]
name = "tracing"
version = "0.1.29"
version = "0.1.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105"
checksum = "2d8d93354fe2a8e50d5953f5ae2e47a3fc2ef03292e7ea46e3cc38f549525fb9"
dependencies = [
"cfg-if 1.0.0",
"pin-project-lite",
@ -2228,9 +2257,9 @@ dependencies = [
[[package]]
name = "tracing-attributes"
version = "0.1.18"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e"
checksum = "8276d9a4a3a558d7b7ad5303ad50b53d58264641b82914b7ada36bd762e7a716"
dependencies = [
"proc-macro2",
"quote",
@ -2239,11 +2268,12 @@ dependencies = [
[[package]]
name = "tracing-core"
version = "0.1.21"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4"
checksum = "03cfcb51380632a72d3111cb8d3447a8d908e577d31beeac006f836383d29a23"
dependencies = [
"lazy_static",
"valuable",
]
[[package]]
@ -2259,9 +2289,9 @@ dependencies = [
[[package]]
name = "tracing-subscriber"
version = "0.3.6"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77be66445c4eeebb934a7340f227bfe7b338173d3f8c00a60a5a58005c9faecf"
checksum = "5312f325fe3588e277415f5a6cca1f4ccad0f248c4cd5a4bd33032d7286abc22"
dependencies = [
"ansi_term",
"lazy_static",
@ -2381,6 +2411,12 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "valuable"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]]
name = "version_check"
version = "0.9.4"
@ -2416,9 +2452,9 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
[[package]]
name = "wasm-bindgen"
version = "0.2.78"
version = "0.2.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce"
checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06"
dependencies = [
"cfg-if 1.0.0",
"wasm-bindgen-macro",
@ -2426,9 +2462,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.78"
version = "0.2.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b"
checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca"
dependencies = [
"bumpalo",
"lazy_static",
@ -2441,9 +2477,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.78"
version = "0.2.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9"
checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@ -2451,9 +2487,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.78"
version = "0.2.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab"
checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc"
dependencies = [
"proc-macro2",
"quote",
@ -2464,9 +2500,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.78"
version = "0.2.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc"
checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2"
[[package]]
name = "winapi"

View File

@ -3,6 +3,7 @@ name = "bin"
version = "2.0.0"
authors = ["Gunwant Jain <mail@wantguns.dev>"]
edition = "2021"
build = "build.rs"
[dependencies]
rand = "0.8.4"
@ -11,6 +12,9 @@ tree_magic = "0.2.3"
syntect = "4.6.0"
rust-embed="6.3.0"
clap = { version = "3.0.9", features = ["derive"] }
once_cell = "1"
sha256 = "1"
time = { version = "0.3", features = ["formatting"] }
[dependencies.rocket_dyn_templates]
version = "0.1.0-rc.1"

9
build.rs Normal file
View File

@ -0,0 +1,9 @@
use std::process::Command;
fn main() {
let output = Command::new("git")
.args(&["rev-parse", "HEAD"])
.output()
.unwrap();
let git_hash = String::from_utf8(output.stdout).unwrap();
println!("cargo:rustc-env=GIT_HASH={}", git_hash);
}

View File

@ -3,6 +3,7 @@ extern crate rocket;
use std::{fs, net::IpAddr, path::PathBuf};
use clap::Parser;
use once_cell::sync::Lazy;
use rocket::{
figment::{providers::Env, Figment},
shield::{NoSniff, Shield},
@ -13,6 +14,18 @@ use rust_embed::RustEmbed;
mod models;
mod routes;
const BINARY_VERSION: &str =
concat!(env!("CARGO_PKG_VERSION"), env!("GIT_HASH"));
const SERVER_VERSION: &str = concat!(
"bin v.",
env!("CARGO_PKG_VERSION"),
" (",
env!("GIT_HASH"),
") (Rocket)"
);
static BINARY_ETAG: Lazy<String> =
Lazy::new(|| sha256::digest(BINARY_VERSION));
#[derive(RustEmbed)]
#[folder = "templates/"]
struct EmbeddedTemplates;
@ -91,7 +104,7 @@ fn rocket() -> _ {
routes::retrieve::retrieve,
routes::retrieve::retrieve_ext,
routes::pretty_retrieve::pretty_retrieve,
routes::pretty_retrieve_ext::pretty_retrieve_ext
routes::pretty_retrieve::pretty_retrieve_ext
],
)
.attach(shield)

View File

@ -1,31 +0,0 @@
use rocket::{
request::Request,
response::{Redirect, Responder, Result},
};
use rocket_dyn_templates::Template;
pub enum MaybeRedirect {
Redirect(Box<Redirect>),
Template(Box<Template>),
}
impl From<Redirect> for MaybeRedirect {
fn from(other: Redirect) -> Self {
Self::Redirect(Box::new(other))
}
}
impl From<Template> for MaybeRedirect {
fn from(other: Template) -> Self {
Self::Template(Box::new(other))
}
}
impl<'r, 'o: 'r> Responder<'r, 'o> for MaybeRedirect {
fn respond_to(self, req: &'r Request<'_>) -> Result<'o> {
match self {
Self::Template(t) => t.respond_to(req),
Self::Redirect(r) => r.respond_to(req),
}
}
}

View File

@ -1,4 +1,4 @@
pub mod maybe_redirect;
pub mod paste_id;
pub mod pretty;
pub mod pretty_syntax;
pub mod response_wrapper;

View File

@ -0,0 +1,84 @@
use rocket::{
http::Status,
request::Request,
response::{Redirect, Responder, Response, Result},
};
use std::io::Cursor;
use std::time::SystemTime;
pub enum ResponseWrapper<R> {
MetaInterfaceResponse(R),
PasteContentResponse(R, SystemTime),
Redirect(Box<Redirect>),
NotFound(String),
ServerError(String),
}
impl<'r, 'o: 'r, R: Responder<'r, 'o>> ResponseWrapper<R> {
pub fn meta_response(responder: R) -> Self {
Self::MetaInterfaceResponse(responder)
}
pub fn paste_response(responder: R, modified: SystemTime) -> Self {
Self::PasteContentResponse(responder, modified)
}
pub fn redirect(redirect: Redirect) -> Self {
Self::Redirect(Box::new(redirect))
}
pub fn not_found(id: &str) -> Self {
Self::NotFound(id.to_string())
}
pub fn server_error<S: Into<String>>(message: S) -> Self {
Self::ServerError(message.into())
}
}
impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o>
for ResponseWrapper<R>
{
fn respond_to(self, request: &'r Request<'_>) -> Result<'o> {
use ResponseWrapper::*;
// Add global headers.
let mut response = Response::build();
response.raw_header("Server", crate::SERVER_VERSION);
// Handle individual request types.
match self {
MetaInterfaceResponse(sup) => response
.join(sup.respond_to(request)?)
.raw_header("ETag", &*crate::BINARY_ETAG)
.ok(),
PasteContentResponse(sup, modified) => response
.join(sup.respond_to(request)?)
.raw_header("Last-Modified", http_strftime(modified))
.ok(),
Redirect(sup) => response.join(sup.respond_to(request)?).ok(),
NotFound(s) => {
let body = format!("Unable to find entity '{}'", s);
response
.sized_body(body.len(), Cursor::new(body))
.status(Status::NotFound)
.ok()
}
ServerError(s) => {
let body = format!("Server error: '{}'", s);
response
.sized_body(body.len(), Cursor::new(body))
.status(Status::InternalServerError)
.ok()
}
}
}
}
fn http_strftime<T: Into<time::OffsetDateTime>>(time: T) -> String {
time.into()
.format(&time::format_description::well_known::Rfc2822)
.unwrap_or_else(|_| "datetime unknown".into())
}

View File

@ -1,6 +1,5 @@
pub mod index;
pub mod pretty_retrieve;
pub mod pretty_retrieve_ext;
pub mod retrieve;
pub mod static_files;
pub mod submit;

View File

@ -1,26 +1,62 @@
use rocket::response::Redirect;
use rocket_dyn_templates::Template;
use std::fs;
use std::collections::HashMap;
use std::io::ErrorKind::InvalidData;
use std::io::ErrorKind::{InvalidData, NotFound};
use std::path::Path;
use crate::get_upload_dir;
use crate::models::maybe_redirect::MaybeRedirect;
use crate::models::paste_id::PasteId;
use crate::models::pretty::get_pretty_body;
use crate::models::pretty_syntax::PasteIdSyntax;
use crate::models::response_wrapper::ResponseWrapper;
#[get("/p/<id>", rank = 2)]
pub async fn pretty_retrieve(id: PasteId<'_>) -> Option<MaybeRedirect> {
let filepath = Path::new(&get_upload_dir()).join(format!("{id}", id = id));
pub async fn pretty_retrieve(id: PasteId<'_>) -> ResponseWrapper<Template> {
pretter_retrieve_inner(&id.to_string(), "txt").await
}
let contents = match get_pretty_body(&filepath, &String::from("txt")) {
#[get("/p/<id_ext>", rank = 1)]
pub async fn pretty_retrieve_ext(
id_ext: PasteIdSyntax<'_>,
) -> ResponseWrapper<Template> {
let id = id_ext.get_fname();
let ext = id_ext.get_ext();
pretter_retrieve_inner(id, ext).await
}
pub async fn pretter_retrieve_inner(
id: &str,
ext: &str,
) -> ResponseWrapper<Template> {
let filepath = Path::new(&get_upload_dir()).join(id.to_string());
let modified_date =
match fs::metadata(&filepath).and_then(|m| m.modified()) {
Ok(v) => v,
Err(e) if e.kind() == NotFound => {
return ResponseWrapper::not_found(id);
}
Err(e) => {
return ResponseWrapper::server_error(e.to_string());
}
};
let contents = match get_pretty_body(&filepath, ext) {
Ok(v) => v,
Err(e) if e.kind() == InvalidData => {
return Some(Redirect::to(format!("/{}", id)).into());
return ResponseWrapper::redirect(Redirect::permanent(format!(
"/{}",
id
)));
}
_ => {
return None;
Err(e) if e.kind() == NotFound => {
return ResponseWrapper::not_found(id)
}
Err(e) => {
return ResponseWrapper::server_error(e.to_string());
}
};
@ -30,7 +66,7 @@ pub async fn pretty_retrieve(id: PasteId<'_>) -> Option<MaybeRedirect> {
let rendered = Template::render("pretty.html", &map);
match tree_magic::match_filepath("text/plain", &filepath) {
true => Some(rendered.into()),
false => None,
true => ResponseWrapper::paste_response(rendered, modified_date),
false => ResponseWrapper::server_error("media type unacceptable"),
}
}

View File

@ -1,41 +0,0 @@
use rocket::response::Redirect;
use rocket_dyn_templates::Template;
use std::collections::HashMap;
use std::io::ErrorKind::InvalidData;
use std::path::Path;
use crate::get_upload_dir;
use crate::models::maybe_redirect::MaybeRedirect;
use crate::models::pretty::get_pretty_body;
use crate::models::pretty_syntax::PasteIdSyntax;
#[get("/p/<id_ext>", rank = 1)]
pub async fn pretty_retrieve_ext(
id_ext: PasteIdSyntax<'_>,
) -> Option<MaybeRedirect> {
let id = id_ext.get_fname();
let ext = id_ext.get_ext();
let filepath = Path::new(&get_upload_dir()).join(id.to_string());
let contents = match get_pretty_body(&filepath, &ext.to_string()) {
Ok(v) => v,
Err(e) if e.kind() == InvalidData => {
return Some(Redirect::to(format!("/{}", id)).into());
}
_ => {
return None;
}
};
let mut map = HashMap::new();
map.insert("title", id.to_string());
map.insert("body", contents);
let rendered = Template::render("pretty.html", &map);
match tree_magic::match_filepath("text/plain", &filepath) {
true => Some(rendered.into()),
false => None,
}
}

View File

@ -1,20 +1,46 @@
use std::fs::File;
use std::io::ErrorKind::NotFound;
use std::path::Path;
use crate::get_upload_dir;
use crate::models::paste_id::PasteId;
use crate::models::pretty_syntax::PasteIdSyntax;
use crate::models::response_wrapper::ResponseWrapper;
#[get("/<id>", rank = 2)]
pub async fn retrieve(id: PasteId<'_>) -> Option<File> {
// let filename = format!("upload/{id}", id = id);
File::open(get_upload_dir().join(format!("{id}", id = id))).ok()
#[get("/r/<id>", rank = 2)]
pub async fn retrieve(id: PasteId<'_>) -> ResponseWrapper<File> {
retrieve_inner(&id.to_string()).await
}
// rank 1 here because this would be more oftenly used
#[get("/<id_ext>", rank = 1)]
pub async fn retrieve_ext(id_ext: PasteIdSyntax<'_>) -> Option<File> {
// let filename = format!("upload/{id}", id = id_ext.get_fname());
File::open(get_upload_dir().join(id_ext.get_fname().to_string())).ok()
#[get("/r/<id_ext>", rank = 1)]
pub async fn retrieve_ext(id_ext: PasteIdSyntax<'_>) -> ResponseWrapper<File> {
retrieve_inner(&id_ext.get_fname().to_string()).await
}
pub async fn retrieve_inner(id: &str) -> ResponseWrapper<File> {
let filepath = Path::new(&get_upload_dir()).join(id.to_string());
let modified_date =
match std::fs::metadata(&filepath).and_then(|m| m.modified()) {
Ok(v) => v,
Err(e) if e.kind() == NotFound => {
return ResponseWrapper::not_found(id);
}
Err(e) => {
return ResponseWrapper::server_error(e.to_string());
}
};
let file = match File::open(&filepath) {
Ok(v) => v,
Err(e) if e.kind() == NotFound => {
return ResponseWrapper::not_found(id)
}
Err(e) => {
return ResponseWrapper::server_error(e.to_string());
}
};
ResponseWrapper::paste_response(file, modified_date)
}

View File

@ -1,3 +1,4 @@
use crate::models::response_wrapper::ResponseWrapper;
use rocket::http::ContentType;
use rust_embed::RustEmbed;
use std::{borrow::Cow, ffi::OsStr, path::PathBuf};
@ -9,9 +10,12 @@ struct Static;
#[get("/static/<file..>")]
pub fn static_files(
file: PathBuf,
) -> Option<(ContentType, Cow<'static, [u8]>)> {
) -> ResponseWrapper<(ContentType, Cow<'static, [u8]>)> {
let filename = file.display().to_string();
let asset = Static::get(&filename)?;
let asset = match Static::get(&filename) {
Some(v) => v,
None => return ResponseWrapper::not_found(&file.to_string_lossy()),
};
let content_type = file
.extension()
@ -19,5 +23,5 @@ pub fn static_files(
.and_then(ContentType::from_extension)
.unwrap_or(ContentType::Bytes);
Some((content_type, asset.data))
ResponseWrapper::meta_response((content_type, asset.data))
}