~garritfra/taurus

This thread contains a patchset. You're looking at the original emails, but you may wish to use the patch review UI. Review patch
2 2

[PATCH taurus v2] Extract I/O related functions to "io" module

Details
Message ID
<20201123073644.2643-1-yerinalexey98fd@gmail.com>
DKIM signature
pass
Download raw message
Patch: +84 -45
Signed-off-by: Alexey Yerin <yerinalexey98fd@gmail.com>
---
Fixed build issues

 src/gemini.rs | 25 ++++++++++++++++++++++++
 src/io.rs     | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/main.rs   | 50 +++++------------------------------------------
 3 files changed, 84 insertions(+), 45 deletions(-)
 create mode 100644 src/io.rs

diff --git a/src/gemini.rs b/src/gemini.rs
index 8e4e8ec..11586ba 100644
--- a/src/gemini.rs
+++ b/src/gemini.rs
@@ -1,5 +1,7 @@
use crate::error::{TaurusError, TaurusResult};
use crate::logger;
use native_tls::TlsStream;
use std::path;
use std::{io::Write, net::TcpStream, str::FromStr};
use url::Url;

@@ -83,6 +85,29 @@ impl GeminiResponse {
        }
    }

    pub fn from_file(path: &str) -> TaurusResult<GeminiResponse> {
        let extension = path::Path::new(path)
            .extension()
            .unwrap_or_else(|| std::ffi::OsStr::new(""));

        let mime_type = match &*extension.to_string_lossy() {
            "gmi" => "text/gemini; charset=utf-8",
            ext => mime_guess::from_ext(ext)
                .first_raw()
                .unwrap_or("text/plain"),
        };

        match crate::io::read_file(path) {
            Ok(buf) => Ok(GeminiResponse::success(buf, mime_type)),
            Err(err) => {
                // Cannot read file or it doesn't exist
                logger::error(format!("{}: {}", path, err));

                Ok(GeminiResponse::not_found())
            }
        }
    }

    pub fn send(&self, mut stream: TlsStream<TcpStream>) -> TaurusResult<usize> {
        let mut buf: Vec<u8> = Vec::new();

diff --git a/src/io.rs b/src/io.rs
new file mode 100644
index 0000000..560c5b2
--- /dev/null
+++ b/src/io.rs
@@ -0,0 +1,54 @@
use crate::error::{TaurusError, TaurusResult};
use native_tls::Identity;
use std::fs::File;
use std::io::{self, Read};
use std::path::Path;

/// Read a file into Vec
pub fn read_file(file_path: &str) -> Result<Vec<u8>, io::Error> {
    let mut file = File::open(file_path)?;
    let mut buf = Vec::new();

    file.read_to_end(&mut buf)?;

    Ok(buf)
}

/// Read certificate file
pub fn load_cert(cert_file: &str, password: &str) -> TaurusResult<Identity> {
    let identity = read_file(&cert_file).map_err(TaurusError::NoIdentity)?;
    let identity = Identity::from_pkcs12(&identity, &password)?;

    Ok(identity)
}

/// Resolve path to a file, returning index.gmi if a subdirectory is encountered
///
/// If path points to a file, it is returned.
/// If path points to a directory, `./index.gmi` is returned
pub fn resolve_path(path: &Path) -> String {
    if path.is_dir() {
        path.join("index.gmi").to_string_lossy().into_owned()
    } else {
        path.to_string_lossy().into_owned()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn resolve_path_file() {
        let path = Path::new("./file.gmi");

        assert_eq!(resolve_path(&path), String::from("./file.gmi"));
    }

    #[test]
    fn resolve_path_dir() {
        let path = Path::new("./");

        assert_eq!(resolve_path(&path), String::from("./index.gmi"));
    }
}
diff --git a/src/main.rs b/src/main.rs
index 90de12e..4a48340 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,14 +4,14 @@ extern crate url;
mod config;
mod error;
mod gemini;
mod io;
mod logger;

use error::{TaurusError, TaurusResult};
use gemini::{GeminiRequest, GeminiResponse};
use native_tls::{Identity, TlsAcceptor, TlsStream};
use native_tls::{TlsAcceptor, TlsStream};
use std::{
    fs::File,
    io::{self, Read},
    io::Read,
    net::{TcpListener, TcpStream},
    path,
    sync::Arc,
@@ -58,9 +58,7 @@ fn run() -> TaurusResult<()> {
        .unwrap_or_else(|| "/var/www/gemini".to_owned());

    // Read certificate
    let identity = read_file(&cert_file).map_err(TaurusError::NoIdentity)?;

    let identity = Identity::from_pkcs12(&identity, &config.certificate_password)?;
    let identity = crate::io::load_cert(&cert_file, &config.certificate_password)?;

    let address = format!("0.0.0.0:{}", port);
    let listener = TcpListener::bind(address).map_err(TaurusError::BindFailed)?;
@@ -93,40 +91,7 @@ fn run() -> TaurusResult<()> {
    Ok(())
}

/// Helper function to read a file into Vec
fn read_file(file_path: &str) -> Result<Vec<u8>, io::Error> {
    let mut file = File::open(file_path)?;
    let mut buf = Vec::new();

    file.read_to_end(&mut buf)?;

    Ok(buf)
}

/// Send file as a response
fn write_file(path: &str) -> TaurusResult<GeminiResponse> {
    let extension = path::Path::new(path)
        .extension()
        .unwrap_or_else(|| std::ffi::OsStr::new(""));

    let mime_type = match &*extension.to_string_lossy() {
        "gmi" => "text/gemini; charset=utf-8",
        ext => mime_guess::from_ext(ext)
            .first_raw()
            .unwrap_or("text/plain"),
    };

    match read_file(path) {
        Ok(buf) => Ok(GeminiResponse::success(buf, mime_type)),
        Err(err) => {
            // Cannot read file or it doesn't exist
            logger::error(format!("{}: {}", path, err));

            Ok(GeminiResponse::not_found())
        }
    }
}

fn handle_client(mut stream: TlsStream<TcpStream>, static_root: &str) -> TaurusResult<usize> {
    let mut buffer = [0; 1024];

@@ -151,12 +116,7 @@ fn handle_client(mut stream: TlsStream<TcpStream>, static_root: &str) -> TaurusR

        // Check if file/dir exists
        if path.exists() {
            // If it's a directory, try to find index.gmi
            if path.is_dir() {
                write_file(&path.join("index.gmi").to_string_lossy())?.send(stream)
            } else {
                write_file(&path.to_string_lossy())?.send(stream)
            }
            GeminiResponse::from_file(&crate::io::resolve_path(&path))?.send(stream)
        } else {
            GeminiResponse::not_found().send(stream)
        }
-- 
2.29.2

[taurus/patches/ci.yml] build success

builds.sr.ht
Details
Message ID
<C7AGZU7WELNL.2JGOE2AFBCOM@cirno2>
In-Reply-To
<20201123073644.2643-1-yerinalexey98fd@gmail.com> (view parent)
DKIM signature
missing
Download raw message
taurus/patches/ci.yml: SUCCESS in 1m26s

[Extract I/O related functions to "io" module][0] v2 from [Alexey Yerin][1]

[0]: https://lists.sr.ht/~garritfra/taurus/patches/15244
[1]: yerinalexey98fd@gmail.com

✓ #349791 SUCCESS taurus/patches/ci.yml https://builds.sr.ht/~garritfra/job/349791
Details
Message ID
<CAD16O85vGOND-2OyUqNkoqZ=f3tXsQeEJZdD+q1HdRGbON1FZA@mail.gmail.com>
In-Reply-To
<20201123073644.2643-1-yerinalexey98fd@gmail.com> (view parent)
DKIM signature
pass
Download raw message
Applied. The other patches are superseded.
Reply to thread Export thread (mbox)