index : static-web-server.git

ascending towards madness

author Jose Quintana <joseluisquintana20@gmail.com> 2021-05-02 23:39:05.0 +00:00:00
committer Jose Quintana <joseluisquintana20@gmail.com> 2021-05-02 23:39:05.0 +00:00:00
commit
58ff9b7b3f20d7631be3b16fee4839e9fe92d5e5 [patch]
tree
fec4d3ef8de4e951de2b01e724c30211c1bd41bb
parent
a8a529cbdb8c7cffec8a84c2d5d753687b9c2e91
download
58ff9b7b3f20d7631be3b16fee4839e9fe92d5e5.tar.gz

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

Diff

 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: <coding>` 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<HeaderValue>, resp: Response<Body>) -> Result<Response<Body>> {
pub fn auto(
    method: &Method,
    headers: &HeaderMap<HeaderValue>,
    resp: Response<Body>,
) -> Result<Response<Body>> {
    // 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::<ContentType>() {
        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<R
    let mut body = Body::empty();
    let len = error_page_content.len() as u64;

    if method == Method::GET {
    if method != Method::HEAD {
        body = Body::from(error_page_content)
    }

diff --git a/src/handler.rs b/src/handler.rs
index e7a7f0b..3e0c15c 100644
--- a/src/handler.rs
+++ b/src/handler.rs
@@ -7,8 +7,10 @@ use crate::{error::Result, error_page};
/// Main server request handler.
pub async fn handle_request(base: &Path, req: Request<Body>) -> Result<Response<Body>> {
    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<Path> 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<HeaderValue>,
    base: &Path,
    uri_path: &str,
) -> Result<Response<Body>, 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