Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,14 @@ RAM: 31686MiB
```
### Results
```
Running 10s test @ http://127.0.0.1:7878/hello
Running 10s test @ http://0.0.0.0:7878/plaintext
4 threads and 500 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 1.39ms 1.05ms 18.45ms 81.47%
Req/Sec 89.69k 18.07k 126.91k 57.50%
3575551 requests in 10.07s, 395.55MB read
Requests/sec: 355053.82
Transfer/sec: 39.28MB
Latency 1.30ms 1.06ms 16.75ms 84.52%
Req/Sec 97.79k 18.43k 133.87k 61.50%
3902819 requests in 10.07s, 483.86MB read
Requests/sec: 387433.91
Transfer/sec: 48.03MB
```

> ⚠️ Benchmark results are provided for reference only.
Expand Down
1 change: 0 additions & 1 deletion volga-open-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ keywords = ["volga", "openapi", "documentation", "rest-api"]
[dependencies]
http = "1.4.0"
mime = "0.3.17"
sha1 = "0.10.6"
serde_json = "1.0.149"
serde_urlencoded = "0.7.1"
serde = { version = "1.0.228", features = ["derive"] }
Expand Down
6 changes: 3 additions & 3 deletions volga/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ httpdate = { version = "1.0.3", optional = true }
hyper = { version = "1.8.1", features = ["server"], optional = true }
hyper-util = { version = "0.1.20", features = ["server", "server-auto", "server-graceful", "service", "tokio"], optional = true }
multer = { version = "3.1.0", optional = true }
sha1 = { version = "0.10.6", optional = true }
sha1 = { version = "0.11.0", optional = true }
reqwest = { version = "0.13.2", optional = true }
tempfile = { version = "3.27.0", optional = true }
tokio-rustls = { version = "0.26.4", default-features = false, features = ["tls12", "aws-lc-rs"], optional = true }
tokio-tungstenite = { version = "0.29.0", optional = true }
tracing = { version = "0.1.44", default-features = false, optional = true }
twox-hash = { version = "2.1.2", optional = true }
uuid = { version = "1.22.0", features = ["v4"], optional = true }
uuid = { version = "1.23.0", features = ["v4"], optional = true }

# volga
volga-dev-cert = { workspace = true, optional = true }
Expand All @@ -65,7 +65,7 @@ hyper = { version = "1.8.1", features = ["client"] }
reqwest = { version = "0.13.2", features = ["rustls-no-provider"] }
serde = { version = "1.0.228", features = ["derive"] }
tracing-subscriber = { version = "0.3.23", features = ["env-filter"] }
uuid = { version = "1.22.0", features = ["v4"] }
uuid = { version = "1.23.0", features = ["v4"] }
criterion = { version = "0.8.2", features = ["async_tokio"] }
tempfile = "3.26.0"

Expand Down
12 changes: 6 additions & 6 deletions volga/src/app/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ use std::sync::Arc;
use crate::{
HttpResult,
error::{
ErrorFunc, FallbackFunc,
FallbackFunc,
fallback::{PipelineFallbackHandler, default_fallback_handler},
handler::{PipelineErrorHandler, WeakErrorHandler, default_error_handler},
handler::{DefaultErrorHandler, PipelineErrorHandler},
},
http::endpoints::Endpoints,
};
Expand Down Expand Up @@ -43,7 +43,7 @@ impl PipelineBuilder {
Self {
middlewares: Middlewares::new(),
endpoints: Endpoints::new(),
error_handler: ErrorFunc::new(default_error_handler).into(),
error_handler: Arc::new(DefaultErrorHandler),
fallback_handler: FallbackFunc::new(default_fallback_handler).into(),
}
}
Expand All @@ -52,7 +52,7 @@ impl PipelineBuilder {
pub(super) fn new() -> Self {
Self {
endpoints: Endpoints::new(),
error_handler: ErrorFunc::new(default_error_handler).into(),
error_handler: Arc::new(DefaultErrorHandler),
fallback_handler: FallbackFunc::new(default_fallback_handler).into(),
}
}
Expand Down Expand Up @@ -112,8 +112,8 @@ impl Pipeline {
}

#[inline]
pub(super) fn error_handler(&self) -> WeakErrorHandler {
Arc::downgrade(&self.error_handler)
pub(super) fn error_handler(&self) -> &PipelineErrorHandler {
&self.error_handler
}

#[inline]
Expand Down
58 changes: 16 additions & 42 deletions volga/src/app/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::{
app::AppEnv,
error::{Error, handler::extract_error_args},
headers::CACHE_CONTROL,
http::endpoints::FindResult,
http::{endpoints::FindResult, request_scope::HttpRequestScope},
status,
};

Expand All @@ -34,9 +34,6 @@ use {
#[cfg(feature = "middleware")]
use crate::middleware::HttpContext;

#[cfg(feature = "rate-limiting")]
use crate::rate_limiting::TrustedProxies;

const REQUEST_HEADERS_TOO_LARGE_MESSAGE: &str = "Request headers too large.";

/// Represents the execution scope of the current connection
Expand Down Expand Up @@ -187,50 +184,32 @@ async fn handle_impl(
let error_handler = pipeline.error_handler();
let (mut parts, body) = request.into_parts();

{
let extensions = &mut parts.extensions;
extensions.insert(ClientIp(peer_addr));
extensions.insert(cancellation_token);
extensions.insert(env.body_limit);
extensions.insert(params);

parts.extensions.insert(HttpRequestScope {
client_ip: ClientIp(peer_addr),
cancellation_token,
body_limit: env.body_limit,
params,
#[cfg(feature = "ws")]
extensions.insert(error_handler.clone());

error_handler: Arc::clone(error_handler),
#[cfg(feature = "jwt-auth")]
if let Some(bts) = &env.bearer_token_service {
extensions.insert(bts.clone());
}

bearer_token_service: env.bearer_token_service.clone(),
#[cfg(any(
feature = "decompression-brotli",
feature = "decompression-gzip",
feature = "decompression-zstd",
feature = "decompression-full"
))]
{
extensions.insert(env.decompression_limits);
}

decompression_limits: env.decompression_limits,
#[cfg(feature = "rate-limiting")]
{
if let Some(rate_limiter) = &env.rate_limiter {
extensions.insert(rate_limiter.clone());
}

if let Some(trusted_proxies) = &env.trusted_proxies {
extensions.insert(TrustedProxies(trusted_proxies.clone()));
}
}

rate_limiter: env.rate_limiter.clone(),
#[cfg(feature = "rate-limiting")]
trusted_proxies: env.trusted_proxies.clone(),
#[cfg(feature = "config")]
if let Some(config) = &env.config {
extensions.insert(Arc::clone(config));
}
}
config: env.config.clone(),
});

// Pre-extract error handler args from parts before consuming them.
let error_args = extract_error_args(&error_handler, &parts);
let error_args = extract_error_args(error_handler, &parts);

let request =
HttpRequest::new(Request::from_parts(parts, body)).into_limited(env.body_limit);
Expand All @@ -249,12 +228,7 @@ async fn handle_impl(

match response {
Ok(response) => Ok(response),
Err(err) => match error_args {
Some(args) => args.call(err).await,
None => Err(Error::server_error(
"Server Error: error handler could not be upgraded",
)),
},
Err(err) => error_args.call(err).await,
}
}
}
Expand Down
19 changes: 13 additions & 6 deletions volga/src/auth/bearer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::{
http::{
Extensions,
endpoints::args::{FromPayload, FromRequestParts, FromRequestRef, Payload, Source},
request_scope::HttpRequestScope,
},
};
use futures_util::future::{Ready, ready};
Expand Down Expand Up @@ -367,10 +368,12 @@ impl TryFrom<&Extensions> for BearerTokenService {

#[inline]
fn try_from(extensions: &Extensions) -> Result<Self, Self::Error> {
let bts = extensions.get::<BearerTokenService>().ok_or_else(|| {
Error::server_error("Bearer Token authorization is not properly configured")
})?;
Ok(bts.clone())
extensions
.get::<HttpRequestScope>()
.and_then(|s| s.bearer_token_service.clone())
.ok_or_else(|| {
Error::server_error("Bearer Token authorization is not properly configured")
})
}
}

Expand Down Expand Up @@ -689,9 +692,13 @@ mod tests {

#[tokio::test]
async fn it_tests_bearer_token_service_from_extensions_success() {
let mut extensions = Extensions::new();
use crate::http::request_scope::HttpRequestScope;
let service = BearerTokenService::from(BearerAuthConfig::default());
extensions.insert(service.clone());
let mut extensions = Extensions::new();
extensions.insert(HttpRequestScope {
bearer_token_service: Some(service.clone()),
..HttpRequestScope::default()
});

let result = BearerTokenService::try_from(&extensions);
assert!(result.is_ok());
Expand Down
15 changes: 11 additions & 4 deletions volga/src/config/extractor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

use crate::{
HttpRequest,
config::store::ConfigStore,
error::Error,
http::endpoints::args::{FromPayload, FromRequestParts, FromRequestRef, Payload, Source},
http::{
endpoints::args::{FromPayload, FromRequestParts, FromRequestRef, Payload, Source},
request_scope::HttpRequestScope,
},
};
use futures_util::future::{Ready, ready};
use hyper::http::request::Parts;
Expand Down Expand Up @@ -46,7 +48,8 @@ impl<T: Send + Sync> Deref for Config<T> {
impl<T: Send + Sync + 'static> Config<T> {
fn from_extensions(ext: &hyper::http::Extensions) -> Result<Self, Error> {
let store = ext
.get::<Arc<ConfigStore>>()
.get::<HttpRequestScope>()
.and_then(|s| s.config.as_ref())
.ok_or_else(|| Error::server_error("Config store not found in extensions"))?;
let arc = store
.get::<T>()
Expand Down Expand Up @@ -86,6 +89,7 @@ impl<T: Send + Sync + 'static> FromPayload for Config<T> {
mod tests {
use super::*;
use crate::config::store::{ConfigStore, SectionKind};
use crate::http::request_scope::HttpRequestScope;
use hyper::http::Extensions;
use serde::Deserialize;

Expand All @@ -101,7 +105,10 @@ mod tests {
.register::<Db>("db", SectionKind::Required, &json)
.unwrap();
let mut ext = Extensions::new();
ext.insert(Arc::new(store));
ext.insert(HttpRequestScope {
config: Some(Arc::new(store)),
..HttpRequestScope::default()
});
ext
}

Expand Down
Loading
Loading