From 58ff9b7b3f20d7631be3b16fee4839e9fe92d5e5 Mon Sep 17 00:00:00 2001 From: Jose Quintana Date: Mon, 3 May 2021 01:39:05 +0200 Subject: [PATCH] refactor: reject requests for non head or get methods - it skips compression for HEAD requests only - it skips error page content on HEAD requests only --- src/compression.rs | 16 ++++++++++++---- src/error_page.rs | 2 +- src/handler.rs | 8 +++++--- src/static_files.rs | 10 ++++++++-- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/compression.rs b/src/compression.rs index 1d6c9e5..293b147 100644 --- a/src/compression.rs +++ b/src/compression.rs @@ -5,10 +5,9 @@ use async_compression::tokio::bufread::{BrotliEncoder, DeflateEncoder, GzipEncod use bytes::Bytes; use futures::Stream; use headers::{AcceptEncoding, ContentCoding, ContentType, HeaderMap, HeaderMapExt}; -use http::header::HeaderValue; use hyper::{ - header::{CONTENT_ENCODING, CONTENT_LENGTH}, - Body, Response, + header::{HeaderValue, CONTENT_ENCODING, CONTENT_LENGTH}, + Body, Method, Response, }; use pin_project::pin_project; use std::convert::TryFrom; @@ -42,7 +41,16 @@ pub const TEXT_MIME_TYPES: [&str; 16] = [ /// using `gzip`, `deflate` or `brotli` if is specified in the `Accept-Encoding` header, adding /// `content-encoding: ` to the Response's [`HeaderMap`](hyper::HeaderMap) /// It also provides the ability to apply compression for text-based MIME types only. -pub fn auto(headers: &HeaderMap, resp: Response) -> Result> { +pub fn auto( + method: &Method, + headers: &HeaderMap, + resp: Response, +) -> Result> { + // Skip compression for HEAD request methods + if method == Method::HEAD { + return Ok(resp); + } + // Skip compression for non-text-based MIME types if let Some(content_type) = resp.headers().typed_get::() { let content_type = content_type.to_string(); diff --git a/src/error_page.rs b/src/error_page.rs index c9088ed..2777229 100644 --- a/src/error_page.rs +++ b/src/error_page.rs @@ -74,7 +74,7 @@ pub fn get_error_response(method: &Method, status_code: &StatusCode) -> Result) -> Result> { let headers = req.headers(); - match static_files::handle_request(base, headers, req.uri().path()).await { - Ok(resp) => compression::auto(headers, resp), - Err(status) => error_page::get_error_response(req.method(), &status), + let method = req.method(); + + match static_files::handle_request(method, headers, base, req.uri().path()).await { + Ok(resp) => compression::auto(method, headers, resp), + Err(status) => error_page::get_error_response(method, &status), } } diff --git a/src/static_files.rs b/src/static_files.rs index bf38060..c628dc2 100644 --- a/src/static_files.rs +++ b/src/static_files.rs @@ -8,7 +8,7 @@ use headers::{ AcceptRanges, ContentLength, ContentRange, ContentType, HeaderMap, HeaderMapExt, HeaderValue, IfModifiedSince, IfRange, IfUnmodifiedSince, LastModified, Range, }; -use hyper::{Body, Response, StatusCode}; +use hyper::{Body, Method, Response, StatusCode}; use percent_encoding::percent_decode_str; use std::fs::Metadata; use std::future::Future; @@ -36,10 +36,16 @@ impl AsRef for ArcPath { /// Entry point to handle web server requests which map to specific files /// on file system and return a file response. pub async fn handle_request( - base: &Path, + method: &Method, headers: &HeaderMap, + base: &Path, uri_path: &str, ) -> Result, StatusCode> { + // Reject requests for non HEAD or GET methods + if !(method == Method::HEAD || method == Method::GET) { + return Err(StatusCode::METHOD_NOT_ALLOWED); + } + let base = Arc::new(base.into()); let res = path_from_tail(base, uri_path).await?; file_reply(headers, res).await -- libgit2 1.7.2