mirror of
https://github.com/tokio-rs/axum.git
synced 2024-12-12 01:40:41 +01:00
Merge branch 'main' into main
This commit is contained in:
commit
2077c89b2b
64 changed files with 309 additions and 245 deletions
|
@ -28,7 +28,6 @@ If your project isn't listed here and you would like it to be, please feel free
|
|||
- [aide](https://docs.rs/aide): Code-first Open API documentation generator with [axum integration](https://docs.rs/aide/latest/aide/axum/index.html).
|
||||
- [axum-typed-routing](https://docs.rs/axum-typed-routing/latest/axum_typed_routing/): Statically typed routing macros with OpenAPI generation using aide.
|
||||
- [axum-jsonschema](https://docs.rs/axum-jsonschema/): A `Json<T>` extractor that does JSON schema validation of requests.
|
||||
- [tower-sessions](https://docs.rs/tower-sessions): Cookie-based sessions.
|
||||
- [axum-login](https://docs.rs/axum-login): Session-based user authentication for axum.
|
||||
- [axum-csrf-sync-pattern](https://crates.io/crates/axum-csrf-sync-pattern): A middleware implementing CSRF STP for AJAX backends and API endpoints.
|
||||
- [axum-otel-metrics](https://github.com/ttys3/axum-otel-metrics/): A axum OpenTelemetry Metrics middleware with prometheus exporter supported.
|
||||
|
@ -105,6 +104,7 @@ If your project isn't listed here and you would like it to be, please feel free
|
|||
- [Introduction to axum]: YouTube playlist
|
||||
- [Rust Axum Full Course]: YouTube video
|
||||
- [Deploying Axum projects with Shuttle]
|
||||
- [API Development with Rust](https://rust-api.dev/docs/front-matter/preface/): REST APIs based on Axum
|
||||
|
||||
[axum-tutorial]: https://github.com/programatik29/axum-tutorial
|
||||
[axum-tutorial-website]: https://programatik29.github.io/axum-tutorial/
|
||||
|
|
|
@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
# 0.4.5
|
||||
|
||||
- **fixed:** Compile errors from the internal `__log_rejection` macro under
|
||||
certain Cargo feature combinations between axum crates ([#2933])
|
||||
|
||||
[#2933]: https://github.com/tokio-rs/axum/pull/2933
|
||||
|
||||
# 0.4.4
|
||||
|
||||
- **added:** Derive `Clone` and `Copy` for `AppendHeaders` ([#2776])
|
||||
|
|
|
@ -9,7 +9,7 @@ license = "MIT"
|
|||
name = "axum-core"
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/tokio-rs/axum"
|
||||
version = "0.4.4" # remember to also bump the version that axum and axum-extra depend on
|
||||
version = "0.4.5" # remember to also bump the version that axum and axum-extra depend on
|
||||
|
||||
[features]
|
||||
tracing = ["dep:tracing"]
|
||||
|
@ -54,6 +54,9 @@ allowed = [
|
|||
"http_body",
|
||||
]
|
||||
|
||||
[package.metadata.cargo-machete]
|
||||
ignored = ["tower-http"] # See __private_docs feature
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
rustdoc-args = ["--cfg", "docsrs"]
|
||||
|
|
|
@ -50,6 +50,11 @@
|
|||
|
||||
#[macro_use]
|
||||
pub(crate) mod macros;
|
||||
#[doc(hidden)] // macro helpers
|
||||
pub mod __private {
|
||||
#[cfg(feature = "tracing")]
|
||||
pub use tracing;
|
||||
}
|
||||
|
||||
mod error;
|
||||
mod ext_traits;
|
||||
|
|
|
@ -9,12 +9,12 @@ macro_rules! __log_rejection {
|
|||
status = $status:expr,
|
||||
) => {
|
||||
{
|
||||
tracing::event!(
|
||||
$crate::__private::tracing::event!(
|
||||
target: "axum::rejection",
|
||||
tracing::Level::TRACE,
|
||||
$crate::__private::tracing::Level::TRACE,
|
||||
status = $status.as_u16(),
|
||||
body = $body_text,
|
||||
rejection_type = std::any::type_name::<$ty>(),
|
||||
rejection_type = ::std::any::type_name::<$ty>(),
|
||||
"rejecting request",
|
||||
);
|
||||
}
|
||||
|
|
|
@ -34,13 +34,13 @@ json-lines = [
|
|||
multipart = ["dep:multer"]
|
||||
protobuf = ["dep:prost"]
|
||||
query = ["dep:serde_html_form"]
|
||||
tracing = ["dep:tracing", "axum-core/tracing", "axum/tracing"]
|
||||
tracing = ["axum-core/tracing", "axum/tracing"]
|
||||
typed-header = ["dep:headers"]
|
||||
typed-routing = ["dep:axum-macros", "dep:percent-encoding", "dep:serde_html_form", "dep:form_urlencoded"]
|
||||
|
||||
[dependencies]
|
||||
axum = { path = "../axum", version = "0.7.6", default-features = false }
|
||||
axum-core = { path = "../axum-core", version = "0.4.4" }
|
||||
axum = { path = "../axum", version = "0.7.7", default-features = false }
|
||||
axum-core = { path = "../axum-core", version = "0.4.5" }
|
||||
bytes = "1.1.0"
|
||||
futures-util = { version = "0.3", default-features = false, features = ["alloc"] }
|
||||
http = "1.0.0"
|
||||
|
|
|
@ -5,6 +5,19 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
# Unreleased
|
||||
|
||||
- **breaking:** The tuple and tuple_struct `Path` extractor deserializers now check that the number of parameters matches the tuple length exactly ([#2931])
|
||||
|
||||
[#2931]: https://github.com/tokio-rs/axum/pull/2931
|
||||
|
||||
# 0.7.7
|
||||
|
||||
- **change**: Remove manual tables of content from the documentation, since
|
||||
rustdoc now generates tables of content in the sidebar ([#2921])
|
||||
|
||||
[#2921]: https://github.com/tokio-rs/axum/pull/2921
|
||||
|
||||
# 0.7.6
|
||||
|
||||
- **change:** Avoid cloning `Arc` during deserialization of `Path`
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "axum"
|
||||
version = "0.7.6"
|
||||
version = "0.7.7"
|
||||
categories = ["asynchronous", "network-programming", "web-programming::http-server"]
|
||||
description = "Web framework that focuses on ergonomics and modularity"
|
||||
edition = "2021"
|
||||
|
@ -41,7 +41,7 @@ ws = ["dep:hyper", "tokio", "dep:tokio-tungstenite", "dep:sha1", "dep:base64"]
|
|||
__private_docs = ["tower/full", "dep:tower-http"]
|
||||
|
||||
[dependencies]
|
||||
axum-core = { path = "../axum-core", version = "0.4.4" }
|
||||
axum-core = { path = "../axum-core", version = "0.4.5" }
|
||||
bytes = "1.0"
|
||||
futures-util = { version = "0.3", default-features = false, features = ["alloc"] }
|
||||
http = "1.0.0"
|
||||
|
@ -62,7 +62,7 @@ tower-service = "0.3"
|
|||
|
||||
# optional dependencies
|
||||
axum-macros = { path = "../axum-macros", version = "0.4.2", optional = true }
|
||||
base64 = { version = "0.21.0", optional = true }
|
||||
base64 = { version = "0.22.1", optional = true }
|
||||
hyper = { version = "1.1.0", optional = true }
|
||||
hyper-util = { version = "0.1.3", features = ["tokio", "server", "service"], optional = true }
|
||||
multer = { version = "3.0.0", optional = true }
|
||||
|
@ -71,7 +71,7 @@ serde_path_to_error = { version = "0.1.8", optional = true }
|
|||
serde_urlencoded = { version = "0.7", optional = true }
|
||||
sha1 = { version = "0.10", optional = true }
|
||||
tokio = { package = "tokio", version = "1.25.0", features = ["time"], optional = true }
|
||||
tokio-tungstenite = { version = "0.23", optional = true }
|
||||
tokio-tungstenite = { version = "0.24.0", optional = true }
|
||||
tracing = { version = "0.1", default-features = false, optional = true }
|
||||
|
||||
[dependencies.tower-http]
|
||||
|
@ -120,7 +120,7 @@ serde_json = "1.0"
|
|||
time = { version = "0.3", features = ["serde-human-readable"] }
|
||||
tokio = { package = "tokio", version = "1.25.0", features = ["macros", "rt", "rt-multi-thread", "net", "test-util"] }
|
||||
tokio-stream = "0.1"
|
||||
tokio-tungstenite = "0.23"
|
||||
tokio-tungstenite = "0.24.0"
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["json"] }
|
||||
uuid = { version = "1.0", features = ["serde", "v4"] }
|
||||
|
|
|
@ -1,12 +1,5 @@
|
|||
Error handling model and utilities
|
||||
|
||||
# Table of contents
|
||||
|
||||
- [axum's error handling model](#axums-error-handling-model)
|
||||
- [Routing to fallible services](#routing-to-fallible-services)
|
||||
- [Applying fallible middleware](#applying-fallible-middleware)
|
||||
- [Running extractors for error handling](#running-extractors-for-error-handling)
|
||||
|
||||
# axum's error handling model
|
||||
|
||||
axum is based on [`tower::Service`] which bundles errors through its associated
|
||||
|
|
|
@ -1,20 +1,5 @@
|
|||
Types and traits for extracting data from requests.
|
||||
|
||||
# Table of contents
|
||||
|
||||
- [Intro](#intro)
|
||||
- [Common extractors](#common-extractors)
|
||||
- [Applying multiple extractors](#applying-multiple-extractors)
|
||||
- [The order of extractors](#the-order-of-extractors)
|
||||
- [Optional extractors](#optional-extractors)
|
||||
- [Customizing extractor responses](#customizing-extractor-responses)
|
||||
- [Accessing inner errors](#accessing-inner-errors)
|
||||
- [Defining custom extractors](#defining-custom-extractors)
|
||||
- [Accessing other extractors in `FromRequest` or `FromRequestParts` implementations](#accessing-other-extractors-in-fromrequest-or-fromrequestparts-implementations)
|
||||
- [Request body limits](#request-body-limits)
|
||||
- [Wrapping extractors](#wrapping-extractors)
|
||||
- [Logging rejections](#logging-rejections)
|
||||
|
||||
# Intro
|
||||
|
||||
A handler function is an async function that takes any number of
|
||||
|
|
|
@ -1,15 +1,3 @@
|
|||
# Table of contents
|
||||
|
||||
- [Intro](#intro)
|
||||
- [Applying middleware](#applying-middleware)
|
||||
- [Commonly used middleware](#commonly-used-middleware)
|
||||
- [Ordering](#ordering)
|
||||
- [Writing middleware](#writing-middleware)
|
||||
- [Routing to services/middleware and backpressure](#routing-to-servicesmiddleware-and-backpressure)
|
||||
- [Accessing state in middleware](#accessing-state-in-middleware)
|
||||
- [Passing state from middleware to handlers](#passing-state-from-middleware-to-handlers)
|
||||
- [Rewriting request URI in middleware](#rewriting-request-uri-in-middleware)
|
||||
|
||||
# Intro
|
||||
|
||||
axum is unique in that it doesn't have its own bespoke middleware system and
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
Types and traits for generating responses.
|
||||
|
||||
# Table of contents
|
||||
|
||||
- [Building responses](#building-responses)
|
||||
- [Returning different response types](#returning-different-response-types)
|
||||
- [Regarding `impl IntoResponse`](#regarding-impl-intoresponse)
|
||||
|
||||
# Building responses
|
||||
|
||||
Anything that implements [`IntoResponse`] can be returned from a handler. axum
|
||||
|
|
|
@ -23,7 +23,11 @@ async fn fallback(uri: Uri) -> (StatusCode, String) {
|
|||
|
||||
Fallbacks only apply to routes that aren't matched by anything in the
|
||||
router. If a handler is matched by a request but returns 404 the
|
||||
fallback is not called.
|
||||
fallback is not called. Note that this applies to [`MethodRouter`]s too: if the
|
||||
request hits a valid path but the [`MethodRouter`] does not have an appropriate
|
||||
method handler installed, the fallback is not called (use
|
||||
[`MethodRouter::fallback`] for this purpose instead).
|
||||
|
||||
|
||||
# Handling all requests without other routes
|
||||
|
||||
|
|
|
@ -82,6 +82,11 @@ let app = Router::new()
|
|||
# let _: Router = app;
|
||||
```
|
||||
|
||||
Additionally, while the wildcard route `/foo/*rest` will not match the
|
||||
paths `/foo` or `/foo/`, a nested router at `/foo` will match the path `/foo`
|
||||
(but not `/foo/`), and a nested router at `/foo/` will match the path `/foo/`
|
||||
(but not `/foo`).
|
||||
|
||||
# Fallbacks
|
||||
|
||||
If a nested router doesn't have its own fallback then it will inherit the
|
||||
|
|
|
@ -140,7 +140,7 @@ impl<'de> Deserializer<'de> for PathDeserializer<'de> {
|
|||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
if self.url_params.len() < len {
|
||||
if self.url_params.len() != len {
|
||||
return Err(PathDeserializationError::wrong_number_of_parameters()
|
||||
.got(self.url_params.len())
|
||||
.expected(len));
|
||||
|
@ -160,7 +160,7 @@ impl<'de> Deserializer<'de> for PathDeserializer<'de> {
|
|||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
if self.url_params.len() < len {
|
||||
if self.url_params.len() != len {
|
||||
return Err(PathDeserializationError::wrong_number_of_parameters()
|
||||
.got(self.url_params.len())
|
||||
.expected(len));
|
||||
|
@ -773,20 +773,6 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_tuple_ignoring_additional_fields() {
|
||||
let url_params = create_url_params(vec![
|
||||
("a", "abc"),
|
||||
("b", "true"),
|
||||
("c", "1"),
|
||||
("d", "false"),
|
||||
]);
|
||||
assert_eq!(
|
||||
<(&str, bool, u32)>::deserialize(PathDeserializer::new(&url_params)).unwrap(),
|
||||
("abc", true, 1)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_map() {
|
||||
let url_params = create_url_params(vec![("a", "1"), ("b", "true"), ("c", "abc")]);
|
||||
|
@ -813,6 +799,18 @@ mod tests {
|
|||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_tuple_too_many_fields() {
|
||||
test_parse_error!(
|
||||
vec![("a", "abc"), ("b", "true"), ("c", "1"), ("d", "false"),],
|
||||
(&str, bool, u32),
|
||||
ErrorKind::WrongNumberOfParameters {
|
||||
got: 4,
|
||||
expected: 3,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wrong_number_of_parameters_error() {
|
||||
test_parse_error!(
|
||||
|
|
|
@ -744,6 +744,33 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[crate::test]
|
||||
async fn tuple_param_matches_exactly() {
|
||||
#[allow(dead_code)]
|
||||
#[derive(Deserialize)]
|
||||
struct Tuple(String, String);
|
||||
|
||||
let app = Router::new()
|
||||
.route("/foo/:a/:b/:c", get(|_: Path<(String, String)>| async {}))
|
||||
.route("/bar/:a/:b/:c", get(|_: Path<Tuple>| async {}));
|
||||
|
||||
let client = TestClient::new(app);
|
||||
|
||||
let res = client.get("/foo/a/b/c").await;
|
||||
assert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR);
|
||||
assert_eq!(
|
||||
res.text().await,
|
||||
"Wrong number of path arguments for `Path`. Expected 2 but got 3",
|
||||
);
|
||||
|
||||
let res = client.get("/bar/a/b/c").await;
|
||||
assert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR);
|
||||
assert_eq!(
|
||||
res.text().await,
|
||||
"Wrong number of path arguments for `Path`. Expected 2 but got 3",
|
||||
);
|
||||
}
|
||||
|
||||
#[crate::test]
|
||||
async fn deserialize_into_vec_of_tuples() {
|
||||
let app = Router::new().route(
|
||||
|
|
|
@ -1,22 +1,5 @@
|
|||
//! axum is a web application framework that focuses on ergonomics and modularity.
|
||||
//!
|
||||
//! # Table of contents
|
||||
//!
|
||||
//! - [High-level features](#high-level-features)
|
||||
//! - [Compatibility](#compatibility)
|
||||
//! - [Example](#example)
|
||||
//! - [Routing](#routing)
|
||||
//! - [Handlers](#handlers)
|
||||
//! - [Extractors](#extractors)
|
||||
//! - [Responses](#responses)
|
||||
//! - [Error handling](#error-handling)
|
||||
//! - [Middleware](#middleware)
|
||||
//! - [Sharing state with handlers](#sharing-state-with-handlers)
|
||||
//! - [Building integrations for axum](#building-integrations-for-axum)
|
||||
//! - [Required dependencies](#required-dependencies)
|
||||
//! - [Examples](#examples)
|
||||
//! - [Feature flags](#feature-flags)
|
||||
//!
|
||||
//! # High-level features
|
||||
//!
|
||||
//! - Route requests to handlers with a macro-free API.
|
||||
|
|
|
@ -966,7 +966,7 @@ async fn logging_rejections() {
|
|||
rejection_type: String,
|
||||
}
|
||||
|
||||
let events = capture_tracing::<RejectionEvent, _, _>(|| async {
|
||||
let events = capture_tracing::<RejectionEvent, _>(|| async {
|
||||
let app = Router::new()
|
||||
.route("/extension", get(|_: Extension<Infallible>| async {}))
|
||||
.route("/string", post(|_: String| async {}));
|
||||
|
@ -987,6 +987,7 @@ async fn logging_rejections() {
|
|||
StatusCode::BAD_REQUEST,
|
||||
);
|
||||
})
|
||||
.with_filter("axum::rejection=trace")
|
||||
.await;
|
||||
|
||||
assert_eq!(
|
||||
|
|
|
@ -213,61 +213,8 @@ where
|
|||
type IntoFuture = private::ServeFuture;
|
||||
|
||||
fn into_future(self) -> Self::IntoFuture {
|
||||
private::ServeFuture(Box::pin(async move {
|
||||
let Self {
|
||||
tcp_listener,
|
||||
mut make_service,
|
||||
tcp_nodelay,
|
||||
_marker: _,
|
||||
} = self;
|
||||
|
||||
loop {
|
||||
let (tcp_stream, remote_addr) = match tcp_accept(&tcp_listener).await {
|
||||
Some(conn) => conn,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
if let Some(nodelay) = tcp_nodelay {
|
||||
if let Err(err) = tcp_stream.set_nodelay(nodelay) {
|
||||
trace!("failed to set TCP_NODELAY on incoming connection: {err:#}");
|
||||
}
|
||||
}
|
||||
|
||||
let tcp_stream = TokioIo::new(tcp_stream);
|
||||
|
||||
poll_fn(|cx| make_service.poll_ready(cx))
|
||||
.await
|
||||
.unwrap_or_else(|err| match err {});
|
||||
|
||||
let tower_service = make_service
|
||||
.call(IncomingStream {
|
||||
tcp_stream: &tcp_stream,
|
||||
remote_addr,
|
||||
})
|
||||
.await
|
||||
.unwrap_or_else(|err| match err {})
|
||||
.map_request(|req: Request<Incoming>| req.map(Body::new));
|
||||
|
||||
let hyper_service = TowerToHyperService::new(tower_service);
|
||||
|
||||
tokio::spawn(async move {
|
||||
match Builder::new(TokioExecutor::new())
|
||||
// upgrades needed for websockets
|
||||
.serve_connection_with_upgrades(tcp_stream, hyper_service)
|
||||
.await
|
||||
{
|
||||
Ok(()) => {}
|
||||
Err(_err) => {
|
||||
// This error only appears when the client doesn't send a request and
|
||||
// terminate the connection.
|
||||
//
|
||||
// If client sends one request then terminate connection whenever, it doesn't
|
||||
// appear.
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}))
|
||||
self.with_graceful_shutdown(std::future::pending())
|
||||
.into_future()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
use crate::util::AxumMutex;
|
||||
use std::{future::Future, io, sync::Arc};
|
||||
use std::{
|
||||
future::{Future, IntoFuture},
|
||||
io,
|
||||
marker::PhantomData,
|
||||
pin::Pin,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use serde::{de::DeserializeOwned, Deserialize};
|
||||
use tracing::instrument::WithSubscriber;
|
||||
use tracing_subscriber::prelude::*;
|
||||
use tracing_subscriber::{filter::Targets, fmt::MakeWriter};
|
||||
|
||||
|
@ -14,36 +21,69 @@ pub(crate) struct TracingEvent<T> {
|
|||
}
|
||||
|
||||
/// Run an async closure and capture the tracing output it produces.
|
||||
pub(crate) async fn capture_tracing<T, F, Fut>(f: F) -> Vec<TracingEvent<T>>
|
||||
pub(crate) fn capture_tracing<T, F>(f: F) -> CaptureTracing<T, F>
|
||||
where
|
||||
F: Fn() -> Fut,
|
||||
Fut: Future,
|
||||
T: DeserializeOwned,
|
||||
{
|
||||
let (make_writer, handle) = TestMakeWriter::new();
|
||||
CaptureTracing {
|
||||
f,
|
||||
filter: None,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
let subscriber = tracing_subscriber::registry().with(
|
||||
tracing_subscriber::fmt::layer()
|
||||
.with_writer(make_writer)
|
||||
.with_target(true)
|
||||
.without_time()
|
||||
.with_ansi(false)
|
||||
.json()
|
||||
.flatten_event(false)
|
||||
.with_filter("axum=trace".parse::<Targets>().unwrap()),
|
||||
);
|
||||
pub(crate) struct CaptureTracing<T, F> {
|
||||
f: F,
|
||||
filter: Option<Targets>,
|
||||
_phantom: PhantomData<fn() -> T>,
|
||||
}
|
||||
|
||||
let guard = tracing::subscriber::set_default(subscriber);
|
||||
impl<T, F> CaptureTracing<T, F> {
|
||||
pub(crate) fn with_filter(mut self, filter_string: &str) -> Self {
|
||||
self.filter = Some(filter_string.parse().unwrap());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
f().await;
|
||||
impl<T, F, Fut> IntoFuture for CaptureTracing<T, F>
|
||||
where
|
||||
F: Fn() -> Fut + Send + Sync + 'static,
|
||||
Fut: Future + Send,
|
||||
T: DeserializeOwned,
|
||||
{
|
||||
type Output = Vec<TracingEvent<T>>;
|
||||
type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send>>;
|
||||
|
||||
drop(guard);
|
||||
fn into_future(self) -> Self::IntoFuture {
|
||||
let Self { f, filter, .. } = self;
|
||||
Box::pin(async move {
|
||||
let (make_writer, handle) = TestMakeWriter::new();
|
||||
|
||||
handle
|
||||
.take()
|
||||
.lines()
|
||||
.map(|line| serde_json::from_str(line).unwrap())
|
||||
.collect()
|
||||
let filter = filter.unwrap_or_else(|| "axum=trace".parse().unwrap());
|
||||
let subscriber = tracing_subscriber::registry().with(
|
||||
tracing_subscriber::fmt::layer()
|
||||
.with_writer(make_writer)
|
||||
.with_target(true)
|
||||
.without_time()
|
||||
.with_ansi(false)
|
||||
.json()
|
||||
.flatten_event(false)
|
||||
.with_filter(filter),
|
||||
);
|
||||
|
||||
let guard = tracing::subscriber::set_default(subscriber);
|
||||
|
||||
f().with_current_subscriber().await;
|
||||
|
||||
drop(guard);
|
||||
|
||||
handle
|
||||
.take()
|
||||
.lines()
|
||||
.map(|line| serde_json::from_str(line).unwrap())
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct TestMakeWriter {
|
||||
|
|
|
@ -8,6 +8,5 @@ publish = false
|
|||
axum = { path = "../../axum", features = ["ws"] }
|
||||
futures = "0.3"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tower = { version = "0.4", features = ["util"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
|
|
@ -6,17 +6,16 @@ publish = false
|
|||
|
||||
[dependencies]
|
||||
axum = { path = "../../axum" }
|
||||
axum-extra = { path = "../../axum-extra", features = ["typed-header"] }
|
||||
serde_json = "1"
|
||||
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
|
||||
tower = "0.4"
|
||||
tower-http = { version = "0.5", features = ["compression-full", "decompression-full"] }
|
||||
tower = "0.5.1"
|
||||
tower-http = { version = "0.6.1", features = ["compression-full", "decompression-full"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
||||
[dev-dependencies]
|
||||
assert-json-diff = "2.0"
|
||||
brotli = "3.4"
|
||||
brotli = "6.0"
|
||||
flate2 = "1"
|
||||
http = "1"
|
||||
zstd = "0.13"
|
||||
|
|
|
@ -7,9 +7,6 @@ publish = false
|
|||
[dependencies]
|
||||
axum = { path = "../../axum" }
|
||||
http-body-util = "0.1.0"
|
||||
hyper = "1.0.0"
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tower = "0.4"
|
||||
tower-http = { version = "0.5.0", features = ["map-request-body", "util"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
|
|
@ -7,4 +7,4 @@ publish = false
|
|||
[dependencies]
|
||||
axum = { path = "../../axum" }
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tower-http = { version = "0.5.0", features = ["cors"] }
|
||||
tower-http = { version = "0.6.1", features = ["cors"] }
|
||||
|
|
|
@ -7,7 +7,6 @@ publish = false
|
|||
[dependencies]
|
||||
axum = { path = "../../axum" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
|
|
@ -8,9 +8,8 @@ publish = false
|
|||
axum = { path = "../../axum", features = ["macros"] }
|
||||
bb8 = "0.8"
|
||||
diesel = "2"
|
||||
diesel-async = { version = "0.3", features = ["postgres", "bb8"] }
|
||||
diesel-async = { version = "0.5", features = ["postgres", "bb8"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
|
|
@ -6,11 +6,10 @@ publish = false
|
|||
|
||||
[dependencies]
|
||||
axum = { path = "../../axum", features = ["macros"] }
|
||||
deadpool-diesel = { version = "0.4.1", features = ["postgres"] }
|
||||
deadpool-diesel = { version = "0.6.1", features = ["postgres"] }
|
||||
diesel = { version = "2", features = ["postgres"] }
|
||||
diesel_migrations = "2"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
|
|
@ -8,6 +8,6 @@ publish = false
|
|||
axum = { path = "../../axum", features = ["macros"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tower-http = { version = "0.5", features = ["trace"] }
|
||||
tower-http = { version = "0.6.1", features = ["trace"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
|
|
@ -7,6 +7,5 @@ publish = false
|
|||
[dependencies]
|
||||
axum = { path = "../../axum" }
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tower = { version = "0.4", features = ["util"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
|
|
@ -6,10 +6,6 @@ publish = false
|
|||
|
||||
[dependencies]
|
||||
axum = { path = "../../axum", features = ["tracing"] }
|
||||
hyper = { version = "1.0", features = [] }
|
||||
hyper-util = { version = "0.1", features = ["tokio", "server-auto", "http1"] }
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tower = { version = "0.4", features = ["util"] }
|
||||
tower-http = { version = "0.5", features = ["timeout", "trace"] }
|
||||
tracing = "0.1"
|
||||
tower-http = { version = "0.6.1", features = ["timeout", "trace"] }
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
|
|
@ -11,4 +11,4 @@ tokio = { version = "1.0", features = ["full"] }
|
|||
[dev-dependencies]
|
||||
http-body-util = "0.1.0"
|
||||
hyper = { version = "1.0.0", features = ["full"] }
|
||||
tower = { version = "0.4", features = ["util"] }
|
||||
tower = { version = "0.5.1", features = ["util"] }
|
||||
|
|
|
@ -9,6 +9,6 @@ axum = { path = "../../axum" }
|
|||
hyper = { version = "1", features = ["full"] }
|
||||
hyper-util = "0.1.1"
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tower = { version = "0.4", features = ["make"] }
|
||||
tower = { version = "0.5.1", features = ["make", "util"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
|
|
@ -7,7 +7,7 @@ publish = false
|
|||
[dependencies]
|
||||
axum = { path = "../../axum" }
|
||||
axum-extra = { path = "../../axum-extra", features = ["typed-header"] }
|
||||
jsonwebtoken = "8.0"
|
||||
jsonwebtoken = "9.3"
|
||||
once_cell = "1.8"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
|
|
|
@ -7,14 +7,13 @@ publish = false
|
|||
[dependencies]
|
||||
axum = { path = "../../axum" }
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tower = { version = "0.4", features = ["util", "timeout", "load-shed", "limit"] }
|
||||
tower-http = { version = "0.5.0", features = [
|
||||
tower = { version = "0.5.1", features = ["util", "timeout", "load-shed", "limit"] }
|
||||
tower-http = { version = "0.6.1", features = [
|
||||
"add-extension",
|
||||
"auth",
|
||||
"compression-full",
|
||||
"limit",
|
||||
"trace",
|
||||
] }
|
||||
tower-layer = "0.3.2"
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "listen-multiple-addrs"
|
||||
name = "example-listen-multiple-addrs"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
@ -9,4 +9,4 @@ axum = { path = "../../axum" }
|
|||
hyper = { version = "1.0.0", features = ["full"] }
|
||||
hyper-util = { version = "0.1", features = ["tokio", "server-auto", "http1"] }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tower = { version = "0.4", features = ["util"] }
|
||||
tower = { version = "0.5.1", features = ["util"] }
|
||||
|
|
|
@ -12,6 +12,6 @@ hyper-util = { version = "0.1" }
|
|||
openssl = "0.10"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tokio-openssl = "0.6"
|
||||
tower = { version = "0.4", features = ["make"] }
|
||||
tower = { version = "0.5.1", features = ["make"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
|
|
@ -12,7 +12,6 @@ hyper-util = { version = "0.1" }
|
|||
rustls-pemfile = "1.0.4"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tokio-rustls = "0.24.1"
|
||||
tower = { version = "0.4", features = ["make"] }
|
||||
tower-service = "0.3.2"
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
|
|
@ -7,6 +7,6 @@ publish = false
|
|||
[dependencies]
|
||||
axum = { path = "../../axum", features = ["multipart"] }
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tower-http = { version = "0.5.0", features = ["limit", "trace"] }
|
||||
tower-http = { version = "0.6.1", features = ["limit", "trace"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
|
|
@ -7,8 +7,6 @@ publish = false
|
|||
[dependencies]
|
||||
axum = { path = "../../axum" }
|
||||
http-body-util = "0.1.0"
|
||||
hyper = { version = "1.0.0", features = ["full"] }
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tower = { version = "0.4", features = ["util", "filter"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
|
|
@ -6,8 +6,8 @@ publish = false
|
|||
|
||||
[dependencies]
|
||||
axum = { path = "../../axum" }
|
||||
metrics = { version = "0.22", default-features = false }
|
||||
metrics-exporter-prometheus = { version = "0.13", default-features = false }
|
||||
metrics = { version = "0.23", default-features = false }
|
||||
metrics-exporter-prometheus = { version = "0.15", default-features = false }
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
|
|
@ -7,7 +7,6 @@ publish = false
|
|||
[dependencies]
|
||||
axum = { path = "../../axum" }
|
||||
http-body-util = "0.1.0"
|
||||
hyper = "1.0.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tower = { version = "0.4", features = ["util"] }
|
||||
tower = { version = "0.5.1", features = ["util"] }
|
||||
|
|
|
@ -7,7 +7,6 @@ publish = false
|
|||
[dependencies]
|
||||
axum = { path = "../../axum" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0.68"
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
|
13
examples/request-id/Cargo.toml
Normal file
13
examples/request-id/Cargo.toml
Normal file
|
@ -0,0 +1,13 @@
|
|||
[package]
|
||||
name = "example-request-id"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
axum = { path = "../../axum" }
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tower = "0.5"
|
||||
tower-http = { version = "0.5", features = ["request-id", "trace"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
81
examples/request-id/src/main.rs
Normal file
81
examples/request-id/src/main.rs
Normal file
|
@ -0,0 +1,81 @@
|
|||
//! Run with
|
||||
//!
|
||||
//! ```not_rust
|
||||
//! cargo run -p example-request-id
|
||||
//! ```
|
||||
|
||||
use axum::{
|
||||
http::{HeaderName, Request},
|
||||
response::Html,
|
||||
routing::get,
|
||||
Router,
|
||||
};
|
||||
use tower::ServiceBuilder;
|
||||
use tower_http::{
|
||||
request_id::{MakeRequestUuid, PropagateRequestIdLayer, SetRequestIdLayer},
|
||||
trace::TraceLayer,
|
||||
};
|
||||
use tracing::{error, info, info_span};
|
||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||
|
||||
const REQUEST_ID_HEADER: &str = "x-request-id";
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
tracing_subscriber::registry()
|
||||
.with(
|
||||
tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| {
|
||||
// axum logs rejections from built-in extractors with the `axum::rejection`
|
||||
// target, at `TRACE` level. `axum::rejection=trace` enables showing those events
|
||||
format!(
|
||||
"{}=debug,tower_http=debug,axum::rejection=trace",
|
||||
env!("CARGO_CRATE_NAME")
|
||||
)
|
||||
.into()
|
||||
}),
|
||||
)
|
||||
.with(tracing_subscriber::fmt::layer())
|
||||
.init();
|
||||
|
||||
let x_request_id = HeaderName::from_static(REQUEST_ID_HEADER);
|
||||
|
||||
let middleware = ServiceBuilder::new()
|
||||
.layer(SetRequestIdLayer::new(
|
||||
x_request_id.clone(),
|
||||
MakeRequestUuid,
|
||||
))
|
||||
.layer(
|
||||
TraceLayer::new_for_http().make_span_with(|request: &Request<_>| {
|
||||
// Log the request id as generated.
|
||||
let request_id = request.headers().get(REQUEST_ID_HEADER);
|
||||
|
||||
match request_id {
|
||||
Some(request_id) => info_span!(
|
||||
"http_request",
|
||||
request_id = ?request_id,
|
||||
),
|
||||
None => {
|
||||
error!("could not extract request_id");
|
||||
info_span!("http_request")
|
||||
}
|
||||
}
|
||||
}),
|
||||
)
|
||||
// send headers from request to response headers
|
||||
.layer(PropagateRequestIdLayer::new(x_request_id));
|
||||
|
||||
// build our application with a route
|
||||
let app = Router::new().route("/", get(handler)).layer(middleware);
|
||||
|
||||
// run it
|
||||
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||
.await
|
||||
.unwrap();
|
||||
println!("listening on {}", listener.local_addr().unwrap());
|
||||
axum::serve(listener, app).await.unwrap();
|
||||
}
|
||||
|
||||
async fn handler() -> Html<&'static str> {
|
||||
info!("Hello world!");
|
||||
Html("<h1>Hello, World!</h1>")
|
||||
}
|
|
@ -9,6 +9,6 @@ axum = { path = "../../axum" }
|
|||
reqwest = { version = "0.12", features = ["stream"] }
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tokio-stream = "0.1"
|
||||
tower-http = { version = "0.5.0", features = ["trace"] }
|
||||
tower-http = { version = "0.6.1", features = ["trace"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
|
|
@ -8,13 +8,13 @@ publish = false
|
|||
axum = { path = "../../axum" }
|
||||
futures = "0.3"
|
||||
hyper = { version = "1.0.0", features = ["full"] }
|
||||
prost = "0.11"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tonic = { version = "0.9" }
|
||||
tonic-reflection = "0.9"
|
||||
tower = { version = "0.4", features = ["full"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
#prost = "0.11"
|
||||
#tokio = { version = "1", features = ["full"] }
|
||||
#tonic = { version = "0.9" }
|
||||
#tonic-reflection = "0.9"
|
||||
tower = { version = "0.5.1", features = ["full"] }
|
||||
#tracing = "0.1"
|
||||
#tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
||||
[build-dependencies]
|
||||
tonic-build = { version = "0.9", features = ["prost"] }
|
||||
|
|
|
@ -9,4 +9,4 @@ axum = { path = "../../axum" }
|
|||
hyper = { version = "1.0", features = [] }
|
||||
hyper-util = { version = "0.1", features = ["tokio", "server-auto", "http1"] }
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tower = { version = "0.4", features = ["util"] }
|
||||
tower = { version = "0.5.1", features = ["util"] }
|
||||
|
|
|
@ -14,3 +14,6 @@ axum-extra = { path = "../../axum-extra", default-features = false }
|
|||
futures-executor = "0.3.21"
|
||||
http = "1.0.0"
|
||||
tower-service = "0.3.1"
|
||||
|
||||
[package.metadata.cargo-machete]
|
||||
ignored = ["axum-extra"]
|
||||
|
|
|
@ -10,4 +10,4 @@ tokio = { version = "1.0", features = ["full"] }
|
|||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
||||
sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "any", "postgres"] }
|
||||
sqlx = { version = "0.8", features = ["runtime-tokio-rustls", "any", "postgres"] }
|
||||
|
|
|
@ -11,11 +11,11 @@ futures = "0.3"
|
|||
headers = "0.4"
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tokio-stream = "0.1"
|
||||
tower-http = { version = "0.5.0", features = ["fs", "trace"] }
|
||||
tower-http = { version = "0.6.1", features = ["fs", "trace"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
||||
[dev-dependencies]
|
||||
eventsource-stream = "0.2"
|
||||
reqwest = { version = "0.12", features = ["stream"] }
|
||||
reqwest-eventsource = "0.5"
|
||||
reqwest-eventsource = "0.6"
|
||||
|
|
|
@ -6,9 +6,8 @@ publish = false
|
|||
|
||||
[dependencies]
|
||||
axum = { path = "../../axum" }
|
||||
axum-extra = { path = "../../axum-extra" }
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tower = { version = "0.4", features = ["util"] }
|
||||
tower-http = { version = "0.5.0", features = ["fs", "trace"] }
|
||||
tower = { version = "0.5.1", features = ["util"] }
|
||||
tower-http = { version = "0.6.1", features = ["fs", "trace"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
|
|
@ -6,5 +6,5 @@ publish = false
|
|||
|
||||
[dependencies]
|
||||
axum = { path = "../../axum" }
|
||||
minijinja = "1.0.11"
|
||||
minijinja = "2.3.1"
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
|
|
|
@ -5,7 +5,7 @@ edition = "2021"
|
|||
publish = false
|
||||
|
||||
[dependencies]
|
||||
askama = "0.11"
|
||||
askama = "0.12"
|
||||
axum = { path = "../../axum" }
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tracing = "0.1"
|
||||
|
|
|
@ -7,6 +7,5 @@ publish = false
|
|||
[dependencies]
|
||||
axum = { path = "../../axum", features = ["ws"] }
|
||||
futures = "0.3"
|
||||
hyper = { version = "1.0.0", features = ["full"] }
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tokio-tungstenite = "0.23"
|
||||
tokio-tungstenite = "0.24"
|
||||
|
|
|
@ -7,14 +7,13 @@ publish = false
|
|||
[dependencies]
|
||||
axum = { path = "../../axum" }
|
||||
http-body-util = "0.1.0"
|
||||
hyper = { version = "1.0.0", features = ["full"] }
|
||||
hyper-util = { version = "0.1", features = ["client", "http1", "client-legacy"] }
|
||||
mime = "0.3"
|
||||
serde_json = "1.0"
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tower-http = { version = "0.5.0", features = ["trace"] }
|
||||
tower-http = { version = "0.6.1", features = ["trace"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
||||
[dev-dependencies]
|
||||
tower = { version = "0.4", features = ["util"] }
|
||||
tower = { version = "0.5.1", features = ["util"] }
|
||||
|
|
|
@ -6,8 +6,7 @@ publish = false
|
|||
|
||||
[dependencies]
|
||||
axum = { path = "../../axum" }
|
||||
axum-server = { version = "0.6", features = ["tls-rustls"] }
|
||||
hyper = { version = "0.14", features = ["full"] }
|
||||
axum-server = { version = "0.7", features = ["tls-rustls"] }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
|
|
@ -6,7 +6,7 @@ publish = false
|
|||
|
||||
[dependencies]
|
||||
axum = { path = "../../axum" }
|
||||
axum-server = { version = "0.6", features = ["tls-rustls"] }
|
||||
axum-server = { version = "0.7", features = ["tls-rustls"] }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
|
|
@ -8,8 +8,8 @@ publish = false
|
|||
axum = { path = "../../axum" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tower = { version = "0.4", features = ["util", "timeout"] }
|
||||
tower-http = { version = "0.5.0", features = ["add-extension", "trace"] }
|
||||
tower = { version = "0.5.1", features = ["util", "timeout"] }
|
||||
tower-http = { version = "0.6.1", features = ["add-extension", "trace"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
uuid = { version = "1.0", features = ["serde", "v4"] }
|
||||
|
|
|
@ -6,8 +6,8 @@ publish = false
|
|||
|
||||
[dependencies]
|
||||
axum = { path = "../../axum" }
|
||||
bb8 = "0.7.1"
|
||||
bb8-postgres = "0.7.0"
|
||||
bb8 = "0.8.5"
|
||||
bb8-postgres = "0.8.1"
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tokio-postgres = "0.7.2"
|
||||
tracing = "0.1"
|
||||
|
|
|
@ -6,9 +6,9 @@ publish = false
|
|||
|
||||
[dependencies]
|
||||
axum = { path = "../../axum" }
|
||||
bb8 = "0.7.1"
|
||||
bb8-redis = "0.14.0"
|
||||
redis = "0.24.0"
|
||||
bb8 = "0.8.5"
|
||||
bb8-redis = "0.17.0"
|
||||
redis = "0.27.2"
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
|
|
@ -7,6 +7,6 @@ publish = false
|
|||
[dependencies]
|
||||
axum = { path = "../../axum", features = ["tracing"] }
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tower-http = { version = "0.5.0", features = ["trace"] }
|
||||
tower-http = { version = "0.6.1", features = ["trace"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
|
|
@ -10,6 +10,5 @@ http-body-util = "0.1"
|
|||
hyper = { version = "1.0.0", features = ["full"] }
|
||||
hyper-util = { version = "0.1", features = ["tokio", "server-auto", "http1"] }
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tower = { version = "0.4", features = ["util"] }
|
||||
tracing = "0.1"
|
||||
tower = { version = "0.5.1", features = ["util"] }
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
|
|
@ -6,10 +6,9 @@ version = "0.1.0"
|
|||
|
||||
[dependencies]
|
||||
axum = { path = "../../axum" }
|
||||
http-body = "1.0.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
thiserror = "1.0.29"
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
validator = { version = "0.14.0", features = ["derive"] }
|
||||
validator = { version = "0.18.1", features = ["derive"] }
|
||||
|
|
|
@ -11,9 +11,8 @@ futures = "0.3"
|
|||
futures-util = { version = "0.3", default-features = false, features = ["sink", "std"] }
|
||||
headers = "0.4"
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tokio-tungstenite = "0.23"
|
||||
tower = { version = "0.4", features = ["util"] }
|
||||
tower-http = { version = "0.5.0", features = ["fs", "trace"] }
|
||||
tokio-tungstenite = "0.24.0"
|
||||
tower-http = { version = "0.6.1", features = ["fs", "trace"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
||||
|
|
Loading…
Reference in a new issue