refactor: initial implementation of separeted lib and bin

This commit is contained in:
Jun Kurihara 2023-07-21 18:48:40 +09:00
commit 13e82035a8
No known key found for this signature in database
GPG key ID: 6D3FEE70E498C15B
37 changed files with 225 additions and 157 deletions

View file

@ -1,88 +1,7 @@
[package]
name = "rpxy"
version = "0.3.0"
authors = ["Jun Kurihara"]
homepage = "https://github.com/junkurihara/rust-rpxy"
repository = "https://github.com/junkurihara/rust-rpxy"
license = "MIT"
readme = "README.md"
edition = "2021"
publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
default = ["http3", "sticky-cookie"]
http3 = ["quinn", "h3", "h3-quinn"]
sticky-cookie = ["base64", "sha2", "chrono"]
[dependencies]
anyhow = "1.0.72"
clap = { version = "4.3.17", features = ["std", "cargo", "wrap_help"] }
rand = "0.8.5"
toml = { version = "0.7.6", default-features = false, features = ["parse"] }
rustc-hash = "1.1.0"
serde = { version = "1.0.174", default-features = false, features = ["derive"] }
bytes = "1.4.0"
thiserror = "1.0.44"
x509-parser = "0.15.0"
derive_builder = "0.12.0"
futures = { version = "0.3.28", features = ["alloc", "async-await"] }
tokio = { version = "1.29.1", default-features = false, features = [
"net",
"rt-multi-thread",
"time",
"sync",
"macros",
] }
async-trait = "0.1.72"
hot_reload = "0.1.2" # reloading certs
# http and tls
hyper = { version = "0.14.27", default-features = false, features = [
"server",
"http1",
"http2",
"stream",
] }
hyper-rustls = { version = "0.24.1", default-features = false, features = [
"tokio-runtime",
"webpki-tokio",
"http1",
"http2",
] }
tokio-rustls = { version = "0.24.1", features = ["early-data"] }
rustls-pemfile = "1.0.3"
rustls = { version = "0.21.5", default-features = false }
webpki = "0.22.0"
# logging
tracing = { version = "0.1.37" }
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
# http/3
# quinn = { version = "0.9.3", optional = true }
quinn = { path = "./quinn/quinn", optional = true } # Tentative to support rustls-0.21
h3 = { path = "./h3/h3/", optional = true }
# h3-quinn = { path = "./h3/h3-quinn/", optional = true }
h3-quinn = { path = "./h3-quinn/", optional = true } # Tentative to support rustls-0.21
# cookie handling for sticky cookie
chrono = { version = "0.4.26", default-features = false, features = [
"unstable-locales",
"alloc",
"clock",
], optional = true }
base64 = { version = "0.21.2", optional = true }
sha2 = { version = "0.10.7", default-features = false, optional = true }
[target.'cfg(not(target_env = "msvc"))'.dependencies]
tikv-jemallocator = "0.5.0"
[dev-dependencies]
[workspace]
members = ["rpxy-bin", "rpxy-lib"]
exclude = ["quinn", "h3-quinn", "h3"]
[profile.release]
codegen-units = 1

49
rpxy-bin/Cargo.toml Normal file
View file

@ -0,0 +1,49 @@
[package]
name = "rpxy"
version = "0.4.0"
authors = ["Jun Kurihara"]
homepage = "https://github.com/junkurihara/rust-rpxy"
repository = "https://github.com/junkurihara/rust-rpxy"
license = "MIT"
readme = "README.md"
edition = "2021"
publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
[dependencies]
rpxy-lib = { path = "../rpxy-lib/", features = ["http3", "sticky-cookie"] }
anyhow = "1.0.72"
rustc-hash = "1.1.0"
serde = { version = "1.0.174", default-features = false, features = ["derive"] }
derive_builder = "0.12.0"
tokio = { version = "1.29.1", default-features = false, features = [
"net",
"rt-multi-thread",
"time",
"sync",
"macros",
] }
async-trait = "0.1.72"
# config
clap = { version = "4.3.17", features = ["std", "cargo", "wrap_help"] }
toml = { version = "0.7.6", default-features = false, features = ["parse"] }
# reloading certs
hot_reload = "0.1.2"
rustls-pemfile = "1.0.3"
# logging
tracing = { version = "0.1.37" }
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
[target.'cfg(not(target_env = "msvc"))'.dependencies]
tikv-jemallocator = "0.5.0"
[dev-dependencies]

View file

@ -1,10 +1,10 @@
use crate::{
certs::{CertsAndKeys, CryptoSource},
log::*,
};
use crate::log::*;
use async_trait::async_trait;
use derive_builder::Builder;
use rustls::{Certificate, PrivateKey};
use rpxy_lib::{
reexports::{Certificate, PrivateKey},
CertsAndKeys, CryptoSource,
};
use std::{
fs::File,
io::{self, BufReader, Cursor, Read},

View file

@ -1,13 +1,11 @@
use super::toml::ConfigToml;
use crate::{
backend::Backends,
cert_file_reader::CryptoFileSource,
error::{anyhow, ensure},
globals::*,
log::*,
utils::BytesName,
};
use clap::Arg;
use rpxy_lib::{Backends, BytesName, Globals, ProxyConfig};
use tokio::runtime::Handle;
pub fn build_globals(runtime_handle: Handle) -> std::result::Result<Globals<CryptoFileSource>, anyhow::Error> {

View file

@ -1,10 +1,11 @@
use crate::{
backend::{Backend, BackendBuilder, ReverseProxy, Upstream, UpstreamGroup, UpstreamGroupBuilder, UpstreamOption},
cert_file_reader::{CryptoFileSource, CryptoFileSourceBuilder},
constants::*,
error::{anyhow, ensure},
globals::ProxyConfig,
utils::PathNameBytesExp,
};
use rpxy_lib::{
reexports::Uri, Backend, BackendBuilder, PathNameBytesExp, ProxyConfig, ReverseProxy, Upstream, UpstreamGroup,
UpstreamGroupBuilder, UpstreamOption,
};
use rustc_hash::FxHashMap as HashMap;
use serde::Deserialize;
@ -265,7 +266,7 @@ impl TryInto<Upstream> for &UpstreamParams {
};
let location = format!("{}://{}", scheme, self.location);
Ok(Upstream {
uri: location.parse::<hyper::Uri>().map_err(|e| anyhow!("{}", e))?,
uri: location.parse::<Uri>().map_err(|e| anyhow!("{}", e))?,
})
}
}

View file

@ -0,0 +1,2 @@
pub const LISTEN_ADDRESSES_V4: &[&str] = &["0.0.0.0"];
pub const LISTEN_ADDRESSES_V6: &[&str] = &["[::]"];

1
rpxy-bin/src/error.rs Normal file
View file

@ -0,0 +1 @@
pub use anyhow::{anyhow, bail, ensure, Context};

24
rpxy-bin/src/log.rs Normal file
View file

@ -0,0 +1,24 @@
pub use tracing::{debug, error, info, warn};
pub fn init_logger() {
use tracing_subscriber::{fmt, prelude::*, EnvFilter};
let format_layer = fmt::layer()
.with_line_number(false)
.with_thread_ids(false)
.with_target(false)
.with_thread_names(true)
.with_target(true)
.with_level(true)
.compact();
// This limits the logger to emits only rpxy crate
let level_string = std::env::var(EnvFilter::DEFAULT_ENV).unwrap_or_else(|_| "info".to_string());
let filter_layer = EnvFilter::new(format!("{}={}", env!("CARGO_PKG_NAME"), level_string));
// let filter_layer = EnvFilter::from_default_env();
tracing_subscriber::registry()
.with(format_layer)
.with(filter_layer)
.init();
}

38
rpxy-bin/src/main.rs Normal file
View file

@ -0,0 +1,38 @@
#[cfg(not(target_env = "msvc"))]
use tikv_jemallocator::Jemalloc;
#[cfg(not(target_env = "msvc"))]
#[global_allocator]
static GLOBAL: Jemalloc = Jemalloc;
mod cert_file_reader;
mod config;
mod constants;
mod error;
mod log;
use crate::{cert_file_reader::CryptoFileSource, config::build_globals, log::*};
use rpxy_lib::{entrypoint, Globals};
use std::sync::Arc;
fn main() {
init_logger();
let mut runtime_builder = tokio::runtime::Builder::new_multi_thread();
runtime_builder.enable_all();
runtime_builder.thread_name("rpxy");
let runtime = runtime_builder.build().unwrap();
runtime.block_on(async {
let globals: Globals<CryptoFileSource> = match build_globals(runtime.handle().clone()) {
Ok(g) => g,
Err(e) => {
error!("Invalid configuration: {}", e);
std::process::exit(1);
}
};
entrypoint(Arc::new(globals)).await.unwrap()
});
warn!("rpxy exited!");
}

77
rpxy-lib/Cargo.toml Normal file
View file

@ -0,0 +1,77 @@
[package]
name = "rpxy-lib"
version = "0.4.0"
authors = ["Jun Kurihara"]
homepage = "https://github.com/junkurihara/rust-rpxy"
repository = "https://github.com/junkurihara/rust-rpxy"
license = "MIT"
readme = "README.md"
edition = "2021"
publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
default = ["http3", "sticky-cookie"]
http3 = ["quinn", "h3", "h3-quinn"]
sticky-cookie = ["base64", "sha2", "chrono"]
[dependencies]
rand = "0.8.5"
rustc-hash = "1.1.0"
bytes = "1.4.0"
derive_builder = "0.12.0"
futures = { version = "0.3.28", features = ["alloc", "async-await"] }
tokio = { version = "1.29.1", default-features = false, features = [
"net",
"rt-multi-thread",
"time",
"sync",
"macros",
] }
async-trait = "0.1.72"
hot_reload = "0.1.2" # reloading certs
# Error handling
anyhow = "1.0.72"
thiserror = "1.0.44"
# http and tls
hyper = { version = "0.14.27", default-features = false, features = [
"server",
"http1",
"http2",
"stream",
] }
hyper-rustls = { version = "0.24.1", default-features = false, features = [
"tokio-runtime",
"webpki-tokio",
"http1",
"http2",
] }
tokio-rustls = { version = "0.24.1", features = ["early-data"] }
rustls = { version = "0.21.5", default-features = false }
webpki = "0.22.0"
x509-parser = "0.15.0"
# logging
tracing = { version = "0.1.37" }
# http/3
# quinn = { version = "0.9.3", optional = true }
quinn = { path = "../quinn/quinn", optional = true } # Tentative to support rustls-0.21
h3 = { path = "../h3/h3/", optional = true }
# h3-quinn = { path = "./h3/h3-quinn/", optional = true }
h3-quinn = { path = "../h3-quinn/", optional = true } # Tentative to support rustls-0.21
# cookie handling for sticky cookie
chrono = { version = "0.4.26", default-features = false, features = [
"unstable-locales",
"alloc",
"clock",
], optional = true }
base64 = { version = "0.21.2", optional = true }
sha2 = { version = "0.10.7", default-features = false, optional = true }
[dev-dependencies]

View file

@ -67,6 +67,7 @@ impl<T> Backends<T>
where
T: CryptoSource,
{
#[allow(clippy::new_without_default)]
pub fn new() -> Self {
Backends {
apps: HashMap::<ServerNameBytesExp, Backend<T>>::default(),

View file

@ -1,5 +1,5 @@
pub const LISTEN_ADDRESSES_V4: &[&str] = &["0.0.0.0"];
pub const LISTEN_ADDRESSES_V6: &[&str] = &["[::]"];
// pub const LISTEN_ADDRESSES_V4: &[&str] = &["0.0.0.0"];
// pub const LISTEN_ADDRESSES_V6: &[&str] = &["[::]"];
// pub const HTTP_LISTEN_PORT: u16 = 8080;
// pub const HTTPS_LISTEN_PORT: u16 = 8443;
pub const PROXY_TIMEOUT_SEC: u64 = 60;

View file

@ -1,15 +1,5 @@
use certs::CryptoSource;
#[cfg(not(target_env = "msvc"))]
use tikv_jemallocator::Jemalloc;
#[cfg(not(target_env = "msvc"))]
#[global_allocator]
static GLOBAL: Jemalloc = Jemalloc;
mod backend;
mod cert_file_reader;
mod certs;
mod config;
mod constants;
mod error;
mod globals;
@ -18,39 +8,27 @@ mod log;
mod proxy;
mod utils;
use crate::{
cert_file_reader::CryptoFileSource, config::build_globals, error::*, globals::*, handler::HttpMessageHandlerBuilder,
log::*, proxy::ProxyBuilder,
};
use crate::{error::*, handler::HttpMessageHandlerBuilder, log::*, proxy::ProxyBuilder};
use futures::future::select_all;
use hyper::Client;
// use hyper_trust_dns::TrustDnsResolver;
use std::sync::Arc;
fn main() {
init_logger();
let mut runtime_builder = tokio::runtime::Builder::new_multi_thread();
runtime_builder.enable_all();
runtime_builder.thread_name("rpxy");
let runtime = runtime_builder.build().unwrap();
runtime.block_on(async {
let globals: Globals<CryptoFileSource> = match build_globals(runtime.handle().clone()) {
Ok(g) => g,
Err(e) => {
error!("Invalid configuration: {}", e);
std::process::exit(1);
}
pub use crate::{
backend::{
Backend, BackendBuilder, Backends, ReverseProxy, Upstream, UpstreamGroup, UpstreamGroupBuilder, UpstreamOption,
},
certs::{CertsAndKeys, CryptoSource},
globals::{Globals, ProxyConfig}, // TODO: BackendConfigに変える
utils::{BytesName, PathNameBytesExp},
};
entrypoint(Arc::new(globals)).await.unwrap()
});
warn!("rpxy exited!");
pub mod reexports {
pub use hyper::Uri;
pub use rustls::{Certificate, PrivateKey};
}
// entrypoint creates and spawns tasks of proxy services
async fn entrypoint<T>(globals: Arc<Globals<T>>) -> Result<()>
/// Entrypoint that creates and spawns tasks of reverse proxy services
pub async fn entrypoint<T>(globals: Arc<Globals<T>>) -> Result<()>
where
T: CryptoSource + Clone + Send + Sync + 'static,
{

View file

@ -95,26 +95,3 @@ impl MessageLog {
);
}
}
pub fn init_logger() {
use tracing_subscriber::{fmt, prelude::*, EnvFilter};
let format_layer = fmt::layer()
.with_line_number(false)
.with_thread_ids(false)
.with_target(false)
.with_thread_names(true)
.with_target(true)
.with_level(true)
.compact();
// This limits the logger to emits only rpxy crate
let level_string = std::env::var(EnvFilter::DEFAULT_ENV).unwrap_or_else(|_| "info".to_string());
let filter_layer = EnvFilter::new(format!("{}={}", env!("CARGO_PKG_NAME"), level_string));
// let filter_layer = EnvFilter::from_default_env();
tracing_subscriber::registry()
.with(format_layer)
.with(filter_layer)
.init();
}

View file

@ -23,6 +23,9 @@ impl PathNameBytesExp {
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.len() == 0
}
pub fn get<I>(&self, index: I) -> Option<&I::Output>
where
I: std::slice::SliceIndex<[u8]>,