Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 43 additions & 31 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ categories = ["network-programming", "web-programming"]
exclude.workspace = true

[workspace.package]
version = "21.13.4"
version = "21.13.7"
readme = "README.md"
edition = "2024"
authors = ["root@ltpp.vip"]
Expand All @@ -34,20 +34,24 @@ members = [
]

[workspace.dependencies]
hyperlane = { path = ".", version = "21.13.4" }
http-type = { path = "type", version = "21.13.4" }
hyperlane-cli = { path = "cli", version = "21.13.4" }
hyperlane-core = { path = "core", version = "21.13.4" }
http-request = { path = "request", version = "21.13.4" }
http-compress = { path = "compress", version = "21.13.4" }
http-constant = { path = "constant", version = "21.13.4" }
hyperlane-macros = { path = "macros", version = "21.13.4" }
hyperlane-plugin-websocket = { path = "plugin/websocket", version = "21.13.4" }
hyperlane = { path = ".", version = "21.13.6" }
http-type = { path = "type", version = "21.13.6" }
hyperlane-cli = { path = "cli", version = "21.13.6" }
hyperlane-core = { path = "core", version = "21.13.6" }
http-request = { path = "request", version = "21.13.6" }
http-compress = { path = "compress", version = "21.13.6" }
http-constant = { path = "constant", version = "21.13.6" }
hyperlane-macros = { path = "macros", version = "21.13.6" }
hyperlane-plugin-websocket = { path = "plugin/websocket", version = "21.13.6" }

h3 = "0.0.8"
h2 = "0.4.20"
hex = "0.4.3"
md5 = "0.8.1"
url = "2.5.8"
http = "1.5.0"
log = "0.4.34"
futures = "0.3"
rand = "0.10.2"
redis = "1.4.1"
rinja = "0.3.5"
Expand All @@ -56,6 +60,7 @@ snafu = "0.9.2"
which = "8.0.5"
ahash = "0.8.12"
brotli = "9.0.0"
bytes = "1.12.1"
quote = "1.0.47"
regex = "1.13.1"
base64 = "0.23.1"
Expand All @@ -65,10 +70,11 @@ dotenvy = "0.15.7"
lettre = "0.11.22"
scraper = "0.27.0"
sysinfo = "0.39.6"
chunkify = "10.2.6"
chunkify = "10.2.8"
h3-quinn = "0.0.10"
num_cpus = "1.17.0"
twox-hash = "2.1.4"
future-fn = "10.2.6"
future-fn = "10.2.8"
inventory = "0.3.24"
once_cell = "1.21.4"
simd-json = "0.18.1"
Expand All @@ -77,35 +83,35 @@ serde_with = "3.21.0"
serde_yaml = "0.9.34"
tracing-log = "0.2.0"
urlencoding = "2.1.3"
hot-restart = "10.2.6"
jwt-service = "10.2.6"
hot-restart = "10.2.8"
jwt-service = "10.2.8"
serde-xml-rs = "0.8.2"
serde_json = "1.0.151"
webpki-roots = "1.0.9"
clonelicious = "10.2.6"
color-output = "10.2.6"
clonelicious = "10.2.8"
color-output = "10.2.8"
proc-macro2 = "1.0.107"
lombok-macros = "10.2.6"
file-operation = "10.2.6"
server-manager = "10.2.6"
lombok-macros = "10.2.8"
file-operation = "10.2.8"
server-manager = "10.2.8"
bytemuck_derive = "1.11.0"
compare_version = "2.0.14"
compare_version = "10.2.8"
serde_urlencoded = "0.7.1"
tokio-broadcast = "10.2.6"
instrument-level = "10.2.6"
rustls-pki-types = "1.15.1"
bin-encode-decode = "1.1.51"
recoverable-spawn = "3.9.30"
tokio-broadcast = "10.2.8"
instrument-level = "10.2.8"
bin-encode-decode = "10.2.8"
recoverable-spawn = "10.2.8"
hyperlane-broadcast = "2.0.13"
std-macro-extensions = "10.2.6"
recoverable-thread-pool = "2.4.28"
std-macro-extensions = "10.2.8"
recoverable-thread-pool = "10.2.8"
syn = { version = "3.0.6", features = ["full"] }
aes = { version = "0.9.1", features = ["hazmat"] }
tokio = { version = "1.53.1", features = ["full"] }
serde = { version = "1.0.229", features = ["derive"] }
getrandom = { version = "0.4.3", features = ["sys_rng"] }
rust_decimal = { version = "1.42.1", features = ["serde"] }
cipher = { version = "0.5.2", features = ["block-padding"] }
rustls-pki-types = { version = "1.15.1", features = ["std"] }
ed25519-dalek = { version = "2.2.0", features = ["rand_core"] }
utoipa-rapidoc = { version = "7.0.0", features = ["actix-web"] }
jsonwebtoken = { version = "10.4.0", features = ["rust_crypto"] }
Expand All @@ -115,10 +121,6 @@ sqlx = { version = "0.9.0", features = ["mysql", "postgres", "runtime-tokio"] }
notify = { version = "8.2.0", default-features = false, features = [
"macos_fsevent",
] }
rustls = { version = "0.23.45", default-features = false, features = [
"ring",
"tls12",
] }
tokio-rustls = { version = "0.26.6", default-features = false, features = [
"ring",
"tls12",
Expand All @@ -128,6 +130,16 @@ utoipa-swagger-ui = { version = "9.0.2", features = [
"actix-web",
"debug-embed",
] }
rustls = { version = "0.23.45", default-features = false, features = [
"std",
"ring",
"tls12",
] }
quinn = { version = "0.11.12", default-features = false, features = [
"log",
"rustls-ring",
"runtime-tokio",
] }
reqwest = { version = "0.13.4", features = [
"gzip",
"json",
Expand Down
14 changes: 11 additions & 3 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,18 @@ exclude.workspace = true
[dependencies]
http-type = { workspace = true }

h2 = { workspace = true }
h3 = { workspace = true }
http = { workspace = true }
bytes = { workspace = true }
quinn = { workspace = true }
regex = { workspace = true }
serde = { workspace = true }
tokio = { workspace = true }
rustls = { workspace = true }
futures = { workspace = true }
h3-quinn = { workspace = true }
inventory = { workspace = true }
tokio-rustls = { workspace = true }
lombok-macros = { workspace = true }

[dev-dependencies]
tokio = { workspace = true }
rustls-pki-types = { workspace = true }
8 changes: 8 additions & 0 deletions core/src/config/const.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/// ALPN identifier advertised for HTTP/1.1.
pub(crate) const ALPN_HTTP1: &[u8] = b"http/1.1";

/// ALPN identifier advertised for HTTP/2 over TLS.
pub(crate) const ALPN_HTTP2: &[u8] = b"h2";

/// ALPN identifier advertised for HTTP/3 over QUIC.
pub(crate) const ALPN_HTTP3: &[u8] = b"h3";
18 changes: 18 additions & 0 deletions core/src/config/enum.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use super::*;

/// The wire protocol a server connection speaks.
///
/// The variant is selected at runtime from the server configuration, never at
/// compile time: one binary serves every protocol it is configured for.
#[derive(Clone, Copy, Debug, Default, Deserialize, DisplayDebug, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum ServerProtocol {
/// HTTP/1.0 and HTTP/1.1 over a plain or TLS terminated byte stream.
#[default]
Http1,
/// HTTP/2, either with prior knowledge over a plain socket or negotiated
/// through `h2` ALPN over TLS.
Http2,
/// HTTP/3 over QUIC, which always terminates TLS inside its own handshake.
Http3,
}
56 changes: 56 additions & 0 deletions core/src/config/impl.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,49 @@
use super::*;

/// Implementation block for ServerProtocol.
impl ServerProtocol {
/// Returns the ALPN protocol identifier used to negotiate this protocol.
///
/// The value is sent verbatim in the TLS handshake, so it must be the
/// wire identifier and not the human-readable version string.
///
/// # Returns
///
/// - `&'static [u8]` - The ALPN protocol identifier bytes.
#[inline(always)]
pub fn get_alpn_protocol(&self) -> &'static [u8] {
match self {
Self::Http1 => ALPN_HTTP1,
Self::Http2 => ALPN_HTTP2,
Self::Http3 => ALPN_HTTP3,
}
}

/// Returns the HTTP version negotiated by this protocol.
///
/// # Returns
///
/// - `HttpVersion` - The protocol's HTTP version.
#[inline(always)]
pub fn get_version(&self) -> HttpVersion {
match self {
Self::Http1 => HttpVersion::Http1_1,
Self::Http2 => HttpVersion::Http2,
Self::Http3 => HttpVersion::Http3,
}
}

/// Returns `true` when this protocol runs over QUIC rather than TCP.
///
/// # Returns
///
/// - `bool` - `true` for QUIC transports, `false` for TCP transports.
#[inline(always)]
pub fn is_quic(&self) -> bool {
matches!(self, Self::Http3)
}
}

/// Provides a default implementation for ServerConfig.
impl Default for ServerConfig {
/// Creates a new ServerConfig instance with default values.
Expand All @@ -13,6 +57,8 @@ impl Default for ServerConfig {
address: Server::format_bind_address(DEFAULT_HOST, DEFAULT_WEB_PORT),
nodelay: DEFAULT_NODELAY,
ttl: DEFAULT_TTI,
protocol: ServerProtocol::default(),
tls: None,
}
}
}
Expand All @@ -34,4 +80,14 @@ impl ServerConfig {
{
serde_json::from_str(json.as_ref())
}

/// Returns the negotiated ALPN protocol identifier for this configuration.
///
/// # Returns
///
/// - `&'static [u8]` - The ALPN identifier of the configured protocol.
#[inline(always)]
pub fn get_alpn_protocol(&self) -> &'static [u8] {
self.get_protocol().get_alpn_protocol()
}
}
6 changes: 5 additions & 1 deletion core/src/config/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
mod r#const;
mod r#enum;
mod r#impl;
mod r#struct;

pub use r#struct::*;
pub use {r#enum::*, r#struct::*};

pub(crate) use r#const::*;

use super::*;
38 changes: 35 additions & 3 deletions core/src/config/struct.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
use super::*;

/// TLS material a server needs to terminate a connection.
///
/// The certificate and key are stored as filesystem paths and only read when a
/// listener is created, so a configuration can be deserialized, compared and
/// cloned without touching the disk.
///
/// The two path fields are part of the public surface: `TlsConfig::new` is the
/// documented constructor and applications read back what they configured.
#[derive(Clone, CustomDebug, Data, Deserialize, DisplayDebug, Eq, New, PartialEq, Serialize)]
pub struct TlsConfig {
/// Path to the PEM encoded certificate chain presented to clients.
pub certificate_path: String,
/// Path to the PEM encoded private key matching the leaf certificate.
pub private_key_path: String,
}

/// Represents the server configuration.
///
/// This structure holds all the settings for the HTTP and WebSocket server,
Expand All @@ -8,11 +24,27 @@ use super::*;
pub struct ServerConfig {
/// The address the server will bind to.
#[set(type(AsRef<str>))]
pub(super) address: String,
pub address: String,
/// The `TCP_NODELAY` option for sockets.
#[get(type(copy))]
pub(super) nodelay: Option<bool>,
pub nodelay: Option<bool>,
/// The `IP_TTL` option for sockets.
#[get(type(copy))]
pub(super) ttl: Option<u32>,
pub ttl: Option<u32>,
/// The wire protocol the listener speaks, defaulting to HTTP/1.
///
/// Skipped by `new` so the three argument constructor keeps its signature;
/// a configuration built that way speaks HTTP/1 until a setter changes it.
#[get(type(copy))]
#[new(skip)]
#[serde(default)]
pub protocol: ServerProtocol,
/// TLS material used to terminate connections, or `None` for plaintext.
///
/// Skipped by `new` for the same reason as `protocol`; the setters take an
/// `Option`, so `set_tls(None)` restores plaintext without a separate call.
#[get(type(clone))]
#[new(skip)]
#[serde(default)]
pub tls: Option<TlsConfig>,
}
8 changes: 4 additions & 4 deletions core/src/context/struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ use super::*;
#[derive(Clone, CustomDebug, Data, DisplayDebug)]
pub struct Context {
/// The incoming HTTP request.
pub(super) request: Request,
pub request: Request,
/// The outgoing HTTP response.
pub(super) response: Response,
pub response: Response,
/// Parameters extracted from the route path.
pub(super) route_params: RouteParams,
pub route_params: RouteParams,
/// A collection of custom attributes for sharing data within the request lifecycle.
pub(super) attributes: ThreadSafeAttributeStore,
pub attributes: ThreadSafeAttributeStore,
}
4 changes: 4 additions & 0 deletions core/src/error/enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ use super::*;
pub enum ServerError {
/// An error occurred while trying to bind to a TCP socket.
TcpBind(String),
/// An error occurred while loading or configuring TLS material.
Tls(String),
/// HTTP/3 was selected without TLS, which the protocol requires.
MissingTlsForHttp3,
/// An unknown or unexpected error occurred.
Unknown(String),
/// An error occurred while reading an HTTP request.
Expand Down
Loading
Loading