aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/archive.rs2
-rw-r--r--src/config.rs24
-rw-r--r--src/errors.rs29
-rw-r--r--src/file_upload.rs15
-rw-r--r--src/listing.rs11
-rw-r--r--src/main.rs10
6 files changed, 51 insertions, 40 deletions
diff --git a/src/archive.rs b/src/archive.rs
index ed33925..29f60c1 100644
--- a/src/archive.rs
+++ b/src/archive.rs
@@ -1,4 +1,4 @@
-use actix_web::http::ContentEncoding;
+use actix_web::http::header::ContentEncoding;
use libflate::gzip::Encoder;
use serde::Deserialize;
use std::fs::File;
diff --git a/src/config.rs b/src/config.rs
index fda2f84..ccff7e3 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -11,7 +11,7 @@ use anyhow::{Context, Result};
use http::HeaderMap;
#[cfg(feature = "tls")]
-use rustls::internal::pemfile::{certs, pkcs8_private_keys};
+use rustls_pemfile as pemfile;
use crate::{args::CliArgs, auth::RequiredAuth};
@@ -156,7 +156,6 @@ impl MiniserveConfig {
let tls_rustls_server_config = if let (Some(tls_cert), Some(tls_key)) =
(args.tls_cert, args.tls_key)
{
- let mut server_config = rustls::ServerConfig::new(rustls::NoClientAuth::new());
let cert_file = &mut BufReader::new(
File::open(&tls_cert)
.context(format!("Couldn't access TLS certificate {:?}", tls_cert))?,
@@ -164,10 +163,23 @@ impl MiniserveConfig {
let key_file = &mut BufReader::new(
File::open(&tls_key).context(format!("Couldn't access TLS key {:?}", tls_key))?,
);
- let cert_chain = certs(cert_file).map_err(|_| anyhow!("Couldn't load certificates"))?;
- let mut keys =
- pkcs8_private_keys(key_file).map_err(|_| anyhow!("Couldn't load private key"))?;
- server_config.set_single_cert(cert_chain, keys.remove(0))?;
+ let cert_chain = pemfile::certs(cert_file).context("Reading cert file")?;
+ let key = pemfile::read_all(key_file)
+ .context("Reading private key file")?
+ .into_iter()
+ .filter_map(|item| match item {
+ pemfile::Item::RSAKey(key) | pemfile::Item::PKCS8Key(key) => Some(key),
+ _ => None,
+ })
+ .next()
+ .ok_or(anyhow!("No supported private key in file"))?;
+ let server_config = rustls::ServerConfig::builder()
+ .with_safe_defaults()
+ .with_no_client_auth()
+ .with_single_cert(
+ cert_chain.into_iter().map(rustls::Certificate).collect(),
+ rustls::PrivateKey(key),
+ )?;
Some(server_config)
} else {
None
diff --git a/src/errors.rs b/src/errors.rs
index c6fcce3..5f55514 100644
--- a/src/errors.rs
+++ b/src/errors.rs
@@ -1,6 +1,6 @@
use crate::{renderer::render_error, MiniserveConfig};
use actix_web::{
- body::AnyBody,
+ body::{BoxBody, MessageBody},
dev::{ResponseHead, Service, ServiceRequest, ServiceResponse},
http::{header, StatusCode},
HttpRequest, HttpResponse, ResponseError,
@@ -109,18 +109,19 @@ impl ResponseError for ContextualError {
}
/// Middleware to convert plain-text error responses to user-friendly web pages
-pub fn error_page_middleware<S>(
+pub fn error_page_middleware<S, B>(
req: ServiceRequest,
srv: &S,
) -> impl Future<Output = actix_web::Result<ServiceResponse>> + 'static
where
- S: Service<ServiceRequest, Response = ServiceResponse, Error = actix_web::Error>,
+ S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = actix_web::Error>,
+ B: MessageBody + 'static,
S::Future: 'static,
{
let fut = srv.call(req);
async {
- let res = fut.await?;
+ let res = fut.await?.map_into_boxed_body();
if (res.status().is_client_error() || res.status().is_server_error())
&& res.headers().get(header::CONTENT_TYPE).map(AsRef::as_ref)
@@ -134,13 +135,15 @@ where
}
}
-fn map_error_page(req: &HttpRequest, head: &mut ResponseHead, body: AnyBody) -> AnyBody {
- let error_msg = match &body {
- AnyBody::Bytes(bytes) => match std::str::from_utf8(bytes) {
- Ok(msg) => msg,
- _ => return body,
- },
- _ => return body,
+fn map_error_page(req: &HttpRequest, head: &mut ResponseHead, body: BoxBody) -> BoxBody {
+ let error_msg = match body.try_into_bytes() {
+ Ok(bytes) => bytes,
+ Err(body) => return body,
+ };
+
+ let error_msg = match std::str::from_utf8(&error_msg) {
+ Ok(msg) => msg,
+ _ => return BoxBody::new(error_msg),
};
let conf = req.app_data::<MiniserveConfig>().unwrap();
@@ -155,9 +158,7 @@ fn map_error_page(req: &HttpRequest, head: &mut ResponseHead, body: AnyBody) ->
header::HeaderValue::from_static("text/html; charset=utf-8"),
);
- render_error(error_msg, head.status, conf, return_address)
- .into_string()
- .into()
+ BoxBody::new(render_error(error_msg, head.status, conf, return_address).into_string())
}
pub fn log_error_chain(description: String) {
diff --git a/src/file_upload.rs b/src/file_upload.rs
index 5009f36..0d4b8a5 100644
--- a/src/file_upload.rs
+++ b/src/file_upload.rs
@@ -43,15 +43,12 @@ async fn handle_multipart(
path: PathBuf,
overwrite_files: bool,
) -> Result<u64, ContextualError> {
- let filename = field
- .content_disposition()
- .and_then(|cd| cd.get_filename().map(String::from))
- .ok_or_else(|| {
- ContextualError::ParseError(
- "HTTP header".to_string(),
- "Failed to retrieve the name of the file to upload".to_string(),
- )
- })?;
+ let filename = field.content_disposition().get_filename().ok_or_else(|| {
+ ContextualError::ParseError(
+ "HTTP header".to_string(),
+ "Failed to retrieve the name of the file to upload".to_string(),
+ )
+ })?;
let filename = sanitize_path(Path::new(&filename), false).ok_or_else(|| {
ContextualError::InvalidPathError("Invalid file name to upload".to_string())
diff --git a/src/listing.rs b/src/listing.rs
index 9273025..9e02598 100644
--- a/src/listing.rs
+++ b/src/listing.rs
@@ -1,7 +1,6 @@
-use actix_web::body::Body;
use actix_web::dev::ServiceResponse;
use actix_web::web::Query;
-use actix_web::{HttpRequest, HttpResponse};
+use actix_web::{HttpMessage, HttpRequest, HttpResponse};
use bytesize::ByteSize;
use percent_encoding::{percent_decode_str, utf8_percent_encode};
use qrcodegen::{QrCode, QrCodeEcc};
@@ -15,7 +14,8 @@ use crate::archive::ArchiveMethod;
use crate::auth::CurrentUser;
use crate::errors::{self, ContextualError};
use crate::renderer;
-use percent_encode_sets::PATH_SEGMENT;
+
+use self::percent_encode_sets::PATH_SEGMENT;
/// "percent-encode sets" as defined by WHATWG specs:
/// https://url.spec.whatwg.org/#percent-encoded-bytes
@@ -157,7 +157,6 @@ pub fn directory_listing(
let extensions = req.extensions();
let current_user: Option<&CurrentUser> = extensions.get::<CurrentUser>();
- use actix_web::dev::BodyEncoding;
let conf = req.app_data::<crate::MiniserveConfig>().unwrap();
let serve_path = req.path();
@@ -225,7 +224,7 @@ pub fn directory_listing(
.body(qr_to_svg_string(&qr, 2)),
Err(err) => {
log::error!("URL is invalid (too long?): {:?}", err);
- HttpResponse::UriTooLong().body(Body::Empty)
+ HttpResponse::UriTooLong().finish()
}
};
return Ok(ServiceResponse::new(req.clone(), res));
@@ -358,7 +357,7 @@ pub fn directory_listing(
req.clone(),
HttpResponse::Ok()
.content_type(archive_method.content_type())
- .encoding(archive_method.content_encoding())
+ .append_header(archive_method.content_encoding())
.append_header(("Content-Transfer-Encoding", "binary"))
.append_header((
"Content-Disposition",
diff --git a/src/main.rs b/src/main.rs
index 785941a..7f1944f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -198,7 +198,9 @@ async fn run(miniserve_config: MiniserveConfig) -> Result<(), ContextualError> {
web::scope(inside_config.random_route.as_deref().unwrap_or(""))
.wrap(middleware::Condition::new(
!inside_config.auth.is_empty(),
- HttpAuthentication::basic(auth::handle_auth),
+ actix_web::middleware::Compat::new(HttpAuthentication::basic(
+ auth::handle_auth,
+ )),
))
.configure(|c| configure_app(c, &inside_config)),
)
@@ -296,7 +298,7 @@ fn create_tcp_listener(addr: SocketAddr) -> io::Result<TcpListener> {
fn configure_header(conf: &MiniserveConfig) -> middleware::DefaultHeaders {
conf.header.iter().flatten().fold(
middleware::DefaultHeaders::new(),
- |headers, (header_name, header_value)| headers.header(header_name, header_value),
+ |headers, (header_name, header_value)| headers.add((header_name, header_value)),
)
}
@@ -357,14 +359,14 @@ async fn favicon() -> impl Responder {
let logo = include_str!("../data/logo.svg");
HttpResponse::Ok()
.insert_header(ContentType(mime::IMAGE_SVG))
- .message_body(logo.into())
+ .body(logo)
}
async fn css() -> impl Responder {
let css = include_str!(concat!(env!("OUT_DIR"), "/style.css"));
HttpResponse::Ok()
.insert_header(ContentType(mime::TEXT_CSS))
- .message_body(css.into())
+ .body(css)
}
// Prints to the console two inverted QrCodes side by side.