Why does my HTTPS server written in Rust fail under testing with JMeter?

The following Rust code:

use tokio::net::TcpListener;

use tokio_rustls::TlsAcceptor;

use rustls_pemfile::{certs, rsa_private_keys};
use std::fs::File;
use std::io::{self, BufReader};
use std::path::Path;
use tokio::io::{split, AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
use tokio_rustls::rustls::{Certificate, PrivateKey};

lazy_static::lazy_static! {
    static ref RESPONSE_200:&'static str = concat!(
        "HTTP/1.1 200 OK\r\n" ,
        "Content-Length: 11\r\n" ,
        "Connection: closed\r\n\r\n",
        "Are you OK?",
    );
}

pub fn load_certs(path: &Path) -> io::Result<Vec<Certificate>> {
    certs(&mut BufReader::new(File::open(path)?))
        .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid cert"))
        .map(|mut certs| certs.drain(..).map(Certificate).collect())
}

pub fn load_keys(path: &Path) -> io::Result<Vec<PrivateKey>> {
    rsa_private_keys(&mut BufReader::new(File::open(path)?))
        .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid key"))
        .map(|mut keys| keys.drain(..).map(PrivateKey).collect())
}

pub fn init(cert_path: &str, key_path: &str) -> io::Result<TlsAcceptor> {
    let certs = load_certs(Path::new(cert_path))?;
    let mut keys = load_keys(Path::new(key_path))?;

    let server_conf = tokio_rustls::rustls::ServerConfig::builder()
        .with_safe_defaults()
        .with_no_client_auth()
        .with_single_cert(certs, keys.remove(0))
        .map_err(|_err| io::Error::new(io::ErrorKind::InvalidInput, "TLS cert loading error"))?;
    Ok(TlsAcceptor::from(std::sync::Arc::new(server_conf)))
}

pub async fn handle<IO>(stream: IO) -> io::Result<()>
where
    IO: AsyncRead + AsyncWrite + Unpin + AsyncWriteExt,
{
    let (mut local_reader, mut local_writer) = split(stream);

    let mut head = [0u8; 2048];
    let n = local_reader.read(&mut head[..]).await?;
    if n == 2048 {
        return Err(io::Error::new(
            io::ErrorKind::Other,
            "Receive a unexpected big size of header!!",
        ));
    }
    let head_str = std::str::from_utf8(&head[..n])
        .map_err(|x| io::Error::new(io::ErrorKind::Interrupted, x))?;

    println!("\r\nReceived request from client: \r\n{}\r\n", head_str);

    // 回复200OK
    local_writer.write_all(RESPONSE_200.as_bytes()).await?;
    local_writer.shutdown().await?;
    Ok(()) as io::Result<()>
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let addr = "192.168.30.26:18443";
    let listener = TcpListener::bind(addr).await.unwrap();
    println!("Server running on port 18443");

    let acceptor = init("server.crt", "server.key")?;

    loop {
        match listener.accept().await {
            Ok((stream, _peer_addr)) => {
                let acceptor = acceptor.clone();
                match acceptor.accept(stream).await {
                    Ok(stream) => {
                        tokio::spawn(async move {
                            if let Err(_err) = handle(stream).await {
                                eprintln!("TLS Handler err: {:?}", _err);
                            }
                        });
                    }
                    Err(_err) => {
                        eprintln!("Tls err: {:?}", _err);
                    }
                }
            }
            Err(_err) => {
                eprintln!("Tcp err: {:?}", _err);
            }
        }
    }
}
[package]
name = "https_server"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
tokio = {version = "1", features = ["full"]}
tokio-rustls = { version = "0.23.4", features = ["dangerous_configuration"] }
tokio-native-tls = "0.3"
rustls-pemfile = "0.2"
lazy_static = "1.4.0"


What errors do you see in the .jtl file that test produced?


the jtl file like this

At a guess, since this is wrong

Side note: I believe that putting a &'static str behind a lazy_static is unneccessary and probably reducing performance for no reason.

1 Like

You are right.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.