Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: upgrade to hyper v1.0 #96

Merged
merged 6 commits into from
Nov 22, 2023
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ jobs:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@clippy
- uses: Swatinem/rust-cache@v2
- run: cargo clippy --tests -- -Dclippy::all -Dclippy::pedantic
- run: cargo clippy --tests

fmt:
name: Fmt
Expand Down
37 changes: 28 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,13 @@ thiserror = "1.0"
path-tree = "0.7"

# http
headers = "0.3"
http = "0.2"
http-body = "=1.0.0-rc.2"
http-body-util = "=0.1.0-rc.3"
hyper = { version = "=1.0.0-rc.4", features = ["server"] }
hyper-util = { git = "https://github.com/hyperium/hyper-util", rev = "63e84bf", features = ["auto"] }
# TODO: wait headers-v1.0
headers = { git = "https://github.com/hyperium/headers.git", rev = "4400aa9" }
http = "1"
http-body = "1"
http-body-util = "0.1"
hyper = { version = "1", features = ["server"] }
hyper-util = { version = "0.1", features = ["server-auto", "tokio"] }

futures-util = "0.3"
tokio = { version = "1.33", features = ["net"] }
Expand All @@ -86,11 +87,12 @@ hex = "0.4"
rust-embed = "8"

# OpenTelemetry
opentelemetry = { version = "0.20", default-features = false }
opentelemetry-prometheus = { version = "0.13", features = [
opentelemetry = { version = "0.21", default-features = false }
opentelemetry_sdk = { version = "0.21", default-features = false }
opentelemetry-prometheus = { version = "0.14", features = [
"prometheus-encoding",
] }
opentelemetry-semantic-conventions = { version = "0.12" }
opentelemetry-semantic-conventions = { version = "0.13" }
prometheus = "0.13"

# Tracing
Expand All @@ -102,8 +104,25 @@ all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[profile.dev]
opt-level = 1
split-debuginfo = "unpacked"

[profile.dev.package."*"]
opt-level = 3
debug = false

[workspace.lints.rust]
unsafe_code = "forbid"
rust_2018_idioms = "warn"
single_use_lifetimes = "warn"
non_ascii_idents = "warn"
unreachable_pub = "warn"
missing_debug_implementations = "warn"
missing_docs = "warn"

[workspace.lints.clippy]
all = "deny"
pedantic = "deny"
module_name_repetitions = { level = "allow", priority = 1 }
too_many_lines = { level = "allow", priority = 1 }
type_complexity = { level = "allow", priority = 1 }
3 changes: 2 additions & 1 deletion clippy.toml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
msrv = "1.64"
# Clippy configuration
# https://doc.rust-lang.org/nightly/clippy/lint_configuration.html
3 changes: 2 additions & 1 deletion examples/otel/metrics/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ publish = false
viz = { workspace = true, features = ["otel-metrics", "otel-prometheus"] }

tokio = { workspace = true, features = [ "rt-multi-thread", "macros" ] }
opentelemetry = { workspace = true, default-features = false, features = ["metrics"]}
opentelemetry = { workspace = true, features = ["metrics"]}
opentelemetry_sdk = { workspace = true, features = ["metrics"] }
11 changes: 4 additions & 7 deletions examples/otel/metrics/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@
use std::{net::SocketAddr, sync::Arc};
use tokio::net::TcpListener;

use opentelemetry::{
global,
sdk::{
metrics::{self, Aggregation, Instrument, MeterProvider, Stream},
Resource,
},
KeyValue,
use opentelemetry::{global, KeyValue};
use opentelemetry_sdk::{
metrics::{self, Aggregation, Instrument, MeterProvider, Stream},
Resource,
};

use viz::{
Expand Down
3 changes: 2 additions & 1 deletion examples/otel/tracing/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ viz = { workspace = true, features = ["otel-tracing"] }

tokio = { workspace = true, features = [ "rt-multi-thread", "macros" ] }
opentelemetry.workspace = true
opentelemetry-jaeger = { version = "0.19.0", features = ["rt-tokio-current-thread"]}
opentelemetry_sdk = { workspace = true, features = ["trace", "rt-tokio-current-thread"] }
opentelemetry-jaeger = { version = "0.20", features = ["rt-tokio-current-thread"]}
6 changes: 3 additions & 3 deletions examples/otel/tracing/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#![deny(warnings)]
#![allow(clippy::unused_async)]

use opentelemetry::{
global,
use opentelemetry::global;
use opentelemetry_sdk::{
runtime::TokioCurrentThread,
sdk::{propagation::TraceContextPropagator, trace::Tracer},
{propagation::TraceContextPropagator, trace::Tracer},
};
use std::{net::SocketAddr, sync::Arc};
use tokio::net::TcpListener;
Expand Down
4 changes: 2 additions & 2 deletions examples/routing/openapi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }

utoipa = "4.0"
utoipa-swagger-ui = "4.0"
utoipa = "4"
utoipa-swagger-ui = "4"
2 changes: 1 addition & 1 deletion examples/templates/markup/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ viz.workspace = true

tokio = { workspace = true, features = [ "rt-multi-thread", "macros" ] }

markup = "0.13"
markup = "0.14"
v_htmlescape = "0.15"
2 changes: 2 additions & 0 deletions examples/templates/markup/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#![deny(warnings)]
#![allow(clippy::unused_async)]
#![allow(clippy::must_use_candidate)]
#![allow(clippy::inherent_to_string_shadow_display)]

use std::{net::SocketAddr, sync::Arc};
use tokio::net::TcpListener;
Expand Down
4 changes: 2 additions & 2 deletions examples/websocket-chat/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{net::SocketAddr, sync::Arc};
use tokio::net::TcpListener;
use tokio::sync::broadcast::{channel, Sender};
use viz::{
get, serve,
get, serve_with_upgrades,
types::{Message, Params, State, WebSocket},
HandlerExt, IntoHandler, IntoResponse, Request, RequestExt, Response, ResponseExt, Result,
Router, Tree,
Expand Down Expand Up @@ -67,7 +67,7 @@ async fn main() -> Result<()> {
let (stream, addr) = listener.accept().await?;
let tree = tree.clone();
tokio::task::spawn(async move {
if let Err(err) = serve(stream, tree, Some(addr)).await {
if let Err(err) = serve_with_upgrades(stream, tree, Some(addr)).await {
eprintln!("Error while serving HTTP connection: {err}");
}
});
Expand Down
5 changes: 4 additions & 1 deletion viz-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ thiserror.workspace = true

rfc7239 = "0.1" # realip
cookie = { version = "0.18", features = ["percent-encode"], optional = true }
form-data = { version = "0.5.0-rc.2", optional = true }
form-data = { version = "0.5.0", optional = true }
serde = { workspace = true, features = ["derive"], optional = true }
serde_json = { workspace = true, optional = true }
serde_urlencoded = { workspace = true, optional = true }
Expand Down Expand Up @@ -105,3 +105,6 @@ tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[lints]
workspace = true
8 changes: 0 additions & 8 deletions viz-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,6 @@
#![doc(html_logo_url = "https://viz.rs/logo.svg")]
#![doc(html_favicon_url = "https://viz.rs/logo.svg")]
#![allow(clippy::module_name_repetitions)]
#![forbid(unsafe_code)]
#![warn(
missing_debug_implementations,
missing_docs,
rust_2018_idioms,
unreachable_pub
)]
#![doc(test(
no_crate_inject,
attr(
Expand Down
2 changes: 0 additions & 2 deletions viz-core/src/middleware/cors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ pub struct Config {
allow_headers: HashSet<HeaderName>,
allow_origins: HashSet<HeaderValue>,
expose_headers: HashSet<HeaderName>,
#[allow(clippy::type_complexity)]
origin_verify: Option<Arc<dyn Fn(&HeaderValue) -> bool + Send + Sync>>,
}

Expand Down Expand Up @@ -118,7 +117,6 @@ impl Config {
}

/// A function to verify the origin. If the function returns false, the request will be rejected.
#[allow(clippy::type_complexity)]
#[must_use]
pub fn origin_verify(
mut self,
Expand Down
49 changes: 25 additions & 24 deletions viz-core/src/middleware/otel/tracing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ use http::uri::Scheme;
use opentelemetry::{
global,
propagation::Extractor,
trace::{
FutureExt as OtelFutureExt, OrderMap, Span, SpanKind, Status, TraceContextExt, Tracer,
},
Context, Key, Value,
trace::{FutureExt as OtelFutureExt, Span, SpanKind, Status, TraceContextExt, Tracer},
Context, KeyValue,
};
use opentelemetry_semantic_conventions::trace::{
CLIENT_ADDRESS, CLIENT_SOCKET_ADDRESS, EXCEPTION_MESSAGE, HTTP_REQUEST_BODY_SIZE,
Expand Down Expand Up @@ -82,7 +80,7 @@ where
.tracer
.span_builder(format!("{} {}", req.method(), http_route))
.with_kind(SpanKind::Server)
.with_attributes_map(attributes)
.with_attributes(attributes)
.start_with_context(&*self.tracer, &parent_context);

span.add_event("request.started".to_string(), vec![]);
Expand Down Expand Up @@ -143,7 +141,7 @@ impl<'a> RequestHeaderCarrier<'a> {
}
}

impl<'a> Extractor for RequestHeaderCarrier<'a> {
impl Extractor for RequestHeaderCarrier<'_> {
fn get(&self, key: &str) -> Option<&str> {
self.headers.get(key).and_then(|v| v.to_str().ok())
}
Expand All @@ -153,70 +151,73 @@ impl<'a> Extractor for RequestHeaderCarrier<'a> {
}
}

fn build_attributes(req: &Request, http_route: &str) -> OrderMap<Key, Value> {
let mut attributes = OrderMap::<Key, Value>::with_capacity(10);
fn build_attributes(req: &Request, http_route: &str) -> Vec<KeyValue> {
let mut attributes = Vec::with_capacity(10);
// <https://github.com/open-telemetry/semantic-conventions/blob/v1.21.0/docs/http/http-spans.md#http-server>
attributes.insert(HTTP_ROUTE, http_route.to_string().into());
attributes.push(KeyValue::new(HTTP_ROUTE, http_route.to_string()));

// <https://github.com/open-telemetry/semantic-conventions/blob/v1.21.0/docs/http/http-spans.md#common-attributes>
attributes.insert(HTTP_REQUEST_METHOD, req.method().to_string().into());
attributes.insert(
attributes.push(KeyValue::new(HTTP_REQUEST_METHOD, req.method().to_string()));
attributes.push(KeyValue::new(
NETWORK_PROTOCOL_VERSION,
format!("{:?}", req.version()).into(),
);
format!("{:?}", req.version()),
));

let remote_addr = req.remote_addr();
if let Some(remote_addr) = remote_addr {
attributes.insert(CLIENT_ADDRESS, remote_addr.to_string().into());
attributes.push(KeyValue::new(CLIENT_ADDRESS, remote_addr.to_string()));
}
if let Some(realip) = req.realip().map(|value| value.0).filter(|realip| {
remote_addr
.map(SocketAddr::ip)
.map_or(true, |remoteip| &remoteip != realip)
}) {
attributes.insert(CLIENT_SOCKET_ADDRESS, realip.to_string().into());
attributes.push(KeyValue::new(CLIENT_SOCKET_ADDRESS, realip.to_string()));
}

let uri = req.uri();
if let Some(host) = uri.host() {
attributes.insert(SERVER_ADDRESS, host.to_string().into());
attributes.push(KeyValue::new(SERVER_ADDRESS, host.to_string()));
}
if let Some(port) = uri
.port_u16()
.map(i64::from)
.filter(|port| *port != 80 && *port != 443)
{
attributes.insert(SERVER_PORT, port.into());
attributes.push(KeyValue::new(SERVER_PORT, port.to_string()));
}

if let Some(path_query) = uri.path_and_query() {
if path_query.path() != "/" {
attributes.insert(URL_PATH, path_query.path().to_string().into());
attributes.push(KeyValue::new(URL_PATH, path_query.path().to_string()));
}
if let Some(query) = path_query.query() {
attributes.insert(URL_QUERY, query.to_string().into());
attributes.push(KeyValue::new(URL_QUERY, query.to_string()));
}
}

attributes.insert(
attributes.push(KeyValue::new(
URL_SCHEME,
uri.scheme().unwrap_or(&Scheme::HTTP).to_string().into(),
);
uri.scheme().unwrap_or(&Scheme::HTTP).to_string(),
));

if let Some(content_length) = req
.content_length()
.and_then(|len| i64::try_from(len).ok())
.filter(|len| *len > 0)
{
attributes.insert(HTTP_REQUEST_BODY_SIZE, content_length.into());
attributes.push(KeyValue::new(
HTTP_REQUEST_BODY_SIZE,
content_length.to_string(),
));
}

if let Some(user_agent) = req
.header_typed::<UserAgent>()
.as_ref()
.map(UserAgent::as_str)
{
attributes.insert(USER_AGENT_ORIGINAL, user_agent.to_string().into());
attributes.push(KeyValue::new(USER_AGENT_ORIGINAL, user_agent.to_string()));
}

attributes
Expand Down
1 change: 0 additions & 1 deletion viz-core/tests/handler.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#![allow(dead_code)]
#![allow(clippy::unused_async)]
#![allow(clippy::similar_names)]
#![allow(clippy::too_many_lines)]
#![allow(clippy::wildcard_imports)]

use http_body_util::Full;
Expand Down
21 changes: 17 additions & 4 deletions viz-core/tests/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,19 @@ use headers::{authorization::Bearer, Authorization, ContentType, HeaderValue};
use http::uri::Scheme;
use serde::{Deserialize, Serialize};
use viz_core::{
header::{AUTHORIZATION, CONTENT_TYPE, COOKIE, SET_COOKIE},
// TODO: reqwest and hyper haven't used the same version of `http`.
// header::{AUTHORIZATION, CONTENT_TYPE, COOKIE, SET_COOKIE},
// StatusCode,
header::CONTENT_TYPE,
types::{self, PayloadError},
Error, IncomingBody, IntoResponse, Request, RequestExt, Response, ResponseExt, Result,
StatusCode,
Error,
IncomingBody,
IntoResponse,
Request,
RequestExt,
Response,
ResponseExt,
Result,
};

#[derive(Debug, Deserialize, Serialize, PartialEq)]
Expand Down Expand Up @@ -62,14 +71,17 @@ fn request_ext() -> Result<()> {
Ok(())
}

#[allow(clippy::too_many_lines)]
#[tokio::test]
async fn request_body() -> Result<()> {
use futures_util::stream::TryStreamExt;
use viz::{
middleware::{cookie, limits},
Router,
};
use viz_test::http::{
header::{AUTHORIZATION, COOKIE},
StatusCode,
};
use viz_test::TestServer;

let router = Router::new()
Expand Down Expand Up @@ -300,6 +312,7 @@ async fn request_session() -> Result<()> {
middleware::{cookie, helper::CookieOptions, session},
Router,
};
use viz_test::http::header::{COOKIE, SET_COOKIE};
use viz_test::{nano_id, sessions, TestServer};

let router = Router::new()
Expand Down
Loading
Loading