From 99ac6156a8eafadee09fcba978f8353f4e9829ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Orhun=20Parmaks=C4=B1z?= Date: Tue, 31 Jan 2023 20:56:04 +0300 Subject: [PATCH] feat(server): allow downloading files via `?download=true` parameter (#24) --- README.md | 1 + src/server.rs | 23 ++++++++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 5604a5a..0beecd2 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ some text - supports one shot links (can only be viewed once) - guesses MIME types - supports overriding and blacklisting + - supports forcing to download via `?download=true` - no duplicate uploads (optional) - Single binary - [binary releases](https://github.com/orhun/rustypaste/releases) diff --git a/src/server.rs b/src/server.rs index dc0ff3e..7993562 100644 --- a/src/server.rs +++ b/src/server.rs @@ -2,7 +2,7 @@ use crate::auth; use crate::config::Config; use crate::file::Directory; use crate::header::{self, ContentDisposition}; -use crate::mime; +use crate::mime as mime_util; use crate::paste::{Paste, PasteType}; use crate::util; use crate::AUTH_TOKEN_ENV; @@ -12,6 +12,7 @@ use actix_web::{error, get, post, web, Error, HttpRequest, HttpResponse}; use awc::Client; use byte_unit::Byte; use futures_util::stream::StreamExt; +use serde::Deserialize; use std::convert::TryFrom; use std::env; use std::fs; @@ -31,11 +32,20 @@ async fn index(config: web::Data>) -> Result } } +/// File serving options (i.e. query parameters). +#[derive(Debug, Deserialize)] +struct ServeOptions { + /// If set to `true`, change the MIME type to `application/octet-stream` and force downloading + /// the file. + download: bool, +} + /// Serves a file from the upload directory. #[get("/{file}")] async fn serve( request: HttpRequest, file: web::Path, + options: Option>, config: web::Data>, ) -> Result { let config = config @@ -62,12 +72,15 @@ async fn serve( } match paste_type { PasteType::File | PasteType::RemoteFile | PasteType::Oneshot => { + let mime_type = if options.map(|v| v.download).unwrap_or(false) { + mime::APPLICATION_OCTET_STREAM + } else { + mime_util::get_mime_type(&config.paste.mime_override, file.to_string()) + .map_err(error::ErrorInternalServerError)? + }; let response = NamedFile::open(&path)? .disable_content_disposition() - .set_content_type( - mime::get_mime_type(&config.paste.mime_override, file.to_string()) - .map_err(error::ErrorInternalServerError)?, - ) + .set_content_type(mime_type) .prefer_utf8(true) .into_response(&request); if paste_type.is_oneshot() {