index : static-web-server.git

ascending towards madness

author Jose Quintana <1700322+joseluisq@users.noreply.github.com> 2022-05-24 22:14:51.0 +00:00:00
committer GitHub <noreply@github.com> 2022-05-24 22:14:51.0 +00:00:00
commit
b49395adc47afa3334fa3292964c7ddec46cf5ec [patch]
tree
61dfa0bf74973defdc4fc8487384c7a256956881
parent
f0dba0ba251bb955883ed7c33fb998e6fecbcd5e
parent
a2a2b8965310976d4dcdc44e9a19feb88b8254b6
download
b49395adc47afa3334fa3292964c7ddec46cf5ec.tar.gz

Merge pull request #112 from joseluisq/feature/remote_address_logging

feat: log request file with its remote address if available

via new `--log-remote-address` boolean option

Diff

 docs/content/configuration/config-file.md | 10 ++++++++++
 src/handler.rs                            | 18 +++++++++++++++++-
 src/server.rs                             |  5 +++++
 src/service.rs                            | 17 ++++++++++-------
 src/settings/cli.rs                       |  9 +++++++++
 src/settings/file.rs                      |  2 ++
 src/settings/mod.rs                       |  5 +++++
 tests/toml/config.toml                    | 15 ++++++++++++++-
 8 files changed, 72 insertions(+), 9 deletions(-)

diff --git a/docs/content/configuration/config-file.md b/docs/content/configuration/config-file.md
index 8346e08..9d827e7 100644
--- a/docs/content/configuration/config-file.md
+++ b/docs/content/configuration/config-file.md
@@ -60,6 +60,16 @@ grace-period = 0
#### Page fallback for 404s
# page-fallback = "some_page.html"

#### Log request Remote Address if available
log-remote-address = false


### Windows Only

#### Run the web server as a Windows Service
# windows-service = false



[advanced]

diff --git a/src/handler.rs b/src/handler.rs
index a9ab4f7..dbb7905 100644
--- a/src/handler.rs
+++ b/src/handler.rs
@@ -1,5 +1,5 @@
use hyper::{header::WWW_AUTHENTICATE, Body, Method, Request, Response, StatusCode};
use std::{future::Future, path::PathBuf, sync::Arc};
use std::{future::Future, net::SocketAddr, path::PathBuf, sync::Arc};

use crate::{
    basic_auth, compression, control_headers, cors, custom_headers, error_page, fallback_page,
@@ -20,6 +20,7 @@ pub struct RequestHandlerOpts {
    pub page50x: Vec<u8>,
    pub page_fallback: Vec<u8>,
    pub basic_auth: String,
    pub log_remote_address: bool,

    // Advanced options
    pub advanced_opts: Option<Advanced>,
@@ -35,6 +36,7 @@ impl RequestHandler {
    pub fn handle<'a>(
        &'a self,
        req: &'a mut Request<Body>,
        remote_addr: Option<SocketAddr>,
    ) -> impl Future<Output = Result<Response<Body>, Error>> + Send + 'a {
        let method = req.method();
        let headers = req.headers();
@@ -45,9 +47,23 @@ impl RequestHandler {
        let uri_query = uri.query();
        let dir_listing = self.opts.dir_listing;
        let dir_listing_order = self.opts.dir_listing_order;
        let log_remote_addr = self.opts.log_remote_address;

        let mut cors_headers: Option<http::HeaderMap> = None;

        // Log request information with its remote address if available
        let mut remote_addr_str = String::new();
        if log_remote_addr {
            remote_addr_str.push_str(" remote_addr=");
            remote_addr_str.push_str(&remote_addr.map_or("".to_owned(), |v| v.to_string()));
        }
        tracing::info!(
            "incoming request: method={} uri={}{}",
            method,
            uri,
            remote_addr_str,
        );

        async move {
            // Check for disallowed HTTP methods and reject request accordently
            if !(method == Method::GET || method == Method::HEAD || method == Method::OPTIONS) {
diff --git a/src/server.rs b/src/server.rs
index 77f469b..4b4d650 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -162,6 +162,10 @@ impl Server {
            !general.basic_auth.is_empty()
        );

        // Log remote address option
        let log_remote_address = general.log_remote_address;
        tracing::info!("log remote address: enabled={}", log_remote_address);

        // Grace period option
        let grace_period = general.grace_period;
        tracing::info!("grace period before graceful shutdown: {}s", grace_period);
@@ -180,6 +184,7 @@ impl Server {
                page50x,
                page_fallback,
                basic_auth,
                log_remote_address,
                advanced_opts,
            }),
        });
diff --git a/src/service.rs b/src/service.rs
index 7f5aa8b..315fd16 100644
--- a/src/service.rs
+++ b/src/service.rs
@@ -1,12 +1,12 @@
use hyper::{service::Service, Body, Request, Response};
use std::convert::Infallible;
use std::future::{ready, Future, Ready};
use std::net::SocketAddr;
use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll};

use crate::handler::RequestHandler;
use crate::Error;
use crate::{handler::RequestHandler, transport::Transport, Error};

/// It defines the router service which is the main entry point for Hyper Server.
pub struct RouterService {
@@ -21,7 +21,7 @@ impl RouterService {
    }
}

impl<T> Service<T> for RouterService {
impl<T: Transport + Send + 'static> Service<&T> for RouterService {
    type Response = RequestService;
    type Error = Infallible;
    type Future = Ready<Result<Self::Response, Self::Error>>;
@@ -30,14 +30,15 @@ impl<T> Service<T> for RouterService {
        Poll::Ready(Ok(()))
    }

    fn call(&mut self, _: T) -> Self::Future {
        ready(Ok(self.builder.build()))
    fn call(&mut self, conn: &T) -> Self::Future {
        ready(Ok(self.builder.build(conn.remote_addr())))
    }
}

/// It defines a Hyper service request which delegates a request handler.
pub struct RequestService {
    handler: Arc<RequestHandler>,
    remote_addr: Option<SocketAddr>,
}

impl Service<Request<Body>> for RequestService {
@@ -51,7 +52,8 @@ impl Service<Request<Body>> for RequestService {

    fn call(&mut self, mut req: Request<Body>) -> Self::Future {
        let handler = self.handler.clone();
        Box::pin(async move { handler.handle(&mut req).await })
        let remote_addr = self.remote_addr;
        Box::pin(async move { handler.handle(&mut req, remote_addr).await })
    }
}

@@ -67,9 +69,10 @@ impl RequestServiceBuilder {
        }
    }

    pub fn build(&self) -> RequestService {
    pub fn build(&self, remote_addr: Option<SocketAddr>) -> RequestService {
        RequestService {
            handler: self.handler.clone(),
            remote_addr,
        }
    }
}
diff --git a/src/settings/cli.rs b/src/settings/cli.rs
index 9f2a033..f062165 100644
--- a/src/settings/cli.rs
+++ b/src/settings/cli.rs
@@ -170,6 +170,15 @@ pub struct General {
    /// Server TOML configuration file path.
    pub config_file: Option<PathBuf>,

    #[structopt(
        long,
        parse(try_from_str),
        default_value = "false",
        env = "SERVER_LOG_REMOTE_ADDRESS"
    )]
    /// Log incoming requests information along with its remote address if available using the `info` log level.
    pub log_remote_address: bool,

    //
    // Windows specific arguments and commands
    //
diff --git a/src/settings/file.rs b/src/settings/file.rs
index d0b565c..22be141 100644
--- a/src/settings/file.rs
+++ b/src/settings/file.rs
@@ -96,6 +96,8 @@ pub struct General {
    pub grace_period: Option<u8>,

    pub page_fallback: Option<PathBuf>,

    pub log_remote_address: Option<bool>,
}

/// Full server configuration
diff --git a/src/settings/mod.rs b/src/settings/mod.rs
index dcb3707..4b793de 100644
--- a/src/settings/mod.rs
+++ b/src/settings/mod.rs
@@ -61,6 +61,7 @@ impl Settings {
        let mut threads_multiplier = opts.threads_multiplier;
        let mut grace_period = opts.grace_period;
        let mut page_fallback = opts.page_fallback;
        let mut log_remote_address = opts.log_remote_address;

        // Define the advanced file options
        let mut settings_advanced: Option<Advanced> = None;
@@ -145,6 +146,9 @@ impl Settings {
                    if let Some(v) = general.page_fallback {
                        page_fallback = Some(v)
                    }
                    if let Some(v) = general.log_remote_address {
                        log_remote_address = v
                    }
                }

                // Prepare the "advanced" options
@@ -206,6 +210,7 @@ impl Settings {
                threads_multiplier,
                grace_period,
                page_fallback,
                log_remote_address,

                // NOTE:
                // Windows-only options and commands
diff --git a/tests/toml/config.toml b/tests/toml/config.toml
index 51de796..47ff090 100644
--- a/tests/toml/config.toml
+++ b/tests/toml/config.toml
@@ -45,6 +45,19 @@ grace-period = 0
#### Page fallback for 404s
page-fallback = ""

#### Page fallback for 404s
page-fallback = ""

#### Log request Remote Address if available
log-remote-address = false


### Windows Only

#### Run the web server as a Windows Service
# windows-service = false


[advanced]

#### HTTP Headers customization
@@ -56,7 +69,7 @@ headers = { Access-Control-Allow-Origin = "*", X-XSS-PROTECTION = "1; mode=block

# #### b. Multiline version
[[advanced.headers]]
source = "index.html"
source = "/index.html"
[advanced.headers.headers]
Cache-Control = "public, max-age=36000"
Content-Security-Policy = "frame-ancestors 'self'"