mirror of
https://github.com/tokio-rs/axum.git
synced 2026-09-08 00:00:24 +02:00
Add serve function and remove Server re-export (#1868)
This commit is contained in:
@@ -41,9 +41,7 @@ use std::fmt;
|
|||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// let app = Router::new().route("/list_things", get(list_things));
|
/// let app = Router::new().route("/list_things", get(list_things));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// If the query string cannot be parsed it will reject the request with a `400
|
/// If the query string cannot be parsed it will reject the request with a `400
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ use axum_macros::__private_axum_test as test;
|
|||||||
pub(crate) mod test_helpers {
|
pub(crate) mod test_helpers {
|
||||||
#![allow(unused_imports)]
|
#![allow(unused_imports)]
|
||||||
|
|
||||||
use axum::{body::HttpBody, BoxError, Router};
|
use axum::{extract::Request, response::Response, serve};
|
||||||
|
|
||||||
mod test_client {
|
mod test_client {
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|||||||
@@ -45,9 +45,7 @@ use prost::Message;
|
|||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// let app = Router::new().route("/users", post(create_user));
|
/// let app = Router::new().route("/users", post(create_user));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// # As response
|
/// # As response
|
||||||
@@ -85,9 +83,7 @@ use prost::Message;
|
|||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// let app = Router::new().route("/users/:id", get(get_user));
|
/// let app = Router::new().route("/users/:id", get(get_user));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Debug, Clone, Copy, Default)]
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "protobuf")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "protobuf")))]
|
||||||
|
|||||||
+6
-12
@@ -416,10 +416,8 @@ pub fn derive_from_request_parts(item: TokenStream) -> TokenStream {
|
|||||||
/// async fn main() {
|
/// async fn main() {
|
||||||
/// let app = Router::new().route("/", get(handler));
|
/// let app = Router::new().route("/", get(handler));
|
||||||
///
|
///
|
||||||
/// axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
|
/// let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
/// .serve(app.into_make_service())
|
/// axum::serve(listener, app).await.unwrap();
|
||||||
/// .await
|
|
||||||
/// .unwrap();
|
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// fn handler() -> &'static str {
|
/// fn handler() -> &'static str {
|
||||||
@@ -438,10 +436,8 @@ pub fn derive_from_request_parts(item: TokenStream) -> TokenStream {
|
|||||||
/// # async fn main() {
|
/// # async fn main() {
|
||||||
/// # let app = Router::new().route("/", get(handler));
|
/// # let app = Router::new().route("/", get(handler));
|
||||||
/// #
|
/// #
|
||||||
/// # axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
|
/// # let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
/// # .serve(app.into_make_service())
|
/// # axum::serve(listener, app).await.unwrap();
|
||||||
/// # .await
|
|
||||||
/// # .unwrap();
|
|
||||||
/// # }
|
/// # }
|
||||||
/// #
|
/// #
|
||||||
/// #[debug_handler]
|
/// #[debug_handler]
|
||||||
@@ -468,10 +464,8 @@ pub fn derive_from_request_parts(item: TokenStream) -> TokenStream {
|
|||||||
/// # async {
|
/// # async {
|
||||||
/// let app = Router::new().route("/", get(handler));
|
/// let app = Router::new().route("/", get(handler));
|
||||||
///
|
///
|
||||||
/// axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
|
/// let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
/// .serve(app.into_make_service())
|
/// axum::serve(listener, app).await.unwrap();
|
||||||
/// .await
|
|
||||||
/// .unwrap();
|
|
||||||
/// # };
|
/// # };
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -40,12 +40,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- **added:** Add `axum::extract::Request` type alias where the body is `axum::body::Body` ([#1789])
|
- **added:** Add `axum::extract::Request` type alias where the body is `axum::body::Body` ([#1789])
|
||||||
- **added:** Add `Router::as_service` and `Router::into_service` to workaround
|
- **added:** Add `Router::as_service` and `Router::into_service` to workaround
|
||||||
type inference issues when calling `ServiceExt` methods on a `Router` ([#1835])
|
type inference issues when calling `ServiceExt` methods on a `Router` ([#1835])
|
||||||
|
- **breaking:** Removed `axum::Server` as it was removed in hyper 1.0. Instead
|
||||||
|
use `axum::serve(listener, service)` or hyper/hyper-util for more configuration options ([#1868])
|
||||||
|
|
||||||
[#1664]: https://github.com/tokio-rs/axum/pull/1664
|
[#1664]: https://github.com/tokio-rs/axum/pull/1664
|
||||||
[#1751]: https://github.com/tokio-rs/axum/pull/1751
|
[#1751]: https://github.com/tokio-rs/axum/pull/1751
|
||||||
[#1762]: https://github.com/tokio-rs/axum/pull/1762
|
[#1762]: https://github.com/tokio-rs/axum/pull/1762
|
||||||
[#1835]: https://github.com/tokio-rs/axum/pull/1835
|
[#1835]: https://github.com/tokio-rs/axum/pull/1835
|
||||||
[#1789]: https://github.com/tokio-rs/axum/pull/1789
|
[#1789]: https://github.com/tokio-rs/axum/pull/1789
|
||||||
|
[#1868]: https://github.com/tokio-rs/axum/pull/1868
|
||||||
|
|
||||||
# 0.6.16 (18. April, 2023)
|
# 0.6.16 (18. April, 2023)
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,10 @@ tower = { version = "0.4.13", default-features = false, features = ["util"] }
|
|||||||
tower-layer = "0.3.2"
|
tower-layer = "0.3.2"
|
||||||
tower-service = "0.3"
|
tower-service = "0.3"
|
||||||
|
|
||||||
|
# wont need this when axum uses http-body 1.0
|
||||||
|
hyper1 = { package = "hyper", version = "1.0.0-rc.3", features = ["server", "http1"] }
|
||||||
|
tower-hyper-http-body-compat = { version = "0.1.4", features = ["server", "http1"] }
|
||||||
|
|
||||||
# optional dependencies
|
# optional dependencies
|
||||||
axum-macros = { path = "../axum-macros", version = "0.3.7", optional = true }
|
axum-macros = { path = "../axum-macros", version = "0.3.7", optional = true }
|
||||||
base64 = { version = "0.21.0", optional = true }
|
base64 = { version = "0.21.0", optional = true }
|
||||||
@@ -192,6 +196,7 @@ allowed = [
|
|||||||
"http_body",
|
"http_body",
|
||||||
"hyper",
|
"hyper",
|
||||||
"serde",
|
"serde",
|
||||||
|
"tokio",
|
||||||
"tower_layer",
|
"tower_layer",
|
||||||
"tower_service",
|
"tower_service",
|
||||||
]
|
]
|
||||||
|
|||||||
+2
-7
@@ -54,13 +54,8 @@ async fn main() {
|
|||||||
.route("/users", post(create_user));
|
.route("/users", post(create_user));
|
||||||
|
|
||||||
// run our app with hyper
|
// run our app with hyper
|
||||||
// `axum::Server` is a re-export of `hyper::Server`
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
axum::serve(listener, app).await.unwrap();
|
||||||
tracing::debug!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// basic handler that responds with a static string
|
// basic handler that responds with a static string
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use axum::{
|
use axum::{
|
||||||
extract::State,
|
extract::State,
|
||||||
routing::{get, post},
|
routing::{get, post},
|
||||||
Extension, Json, Router, Server,
|
Extension, Json, Router,
|
||||||
};
|
};
|
||||||
use hyper::server::conn::AddrIncoming;
|
use hyper::server::conn::AddrIncoming;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -164,7 +164,7 @@ impl BenchmarkBuilder {
|
|||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
rt.block_on(async move {
|
rt.block_on(async move {
|
||||||
let incoming = AddrIncoming::from_listener(listener).unwrap();
|
let incoming = AddrIncoming::from_listener(listener).unwrap();
|
||||||
Server::builder(incoming)
|
hyper::Server::builder(incoming)
|
||||||
.serve(app.into_make_service())
|
.serve(app.into_make_service())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
@@ -47,9 +47,7 @@ pin_project! {
|
|||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// let app = Router::new().route("/", get(handler));
|
/// let app = Router::new().route("/", get(handler));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// [`Stream`]: futures_util::stream::Stream
|
/// [`Stream`]: futures_util::stream::Stream
|
||||||
|
|||||||
@@ -85,9 +85,7 @@ async fn handle_anyhow_error(err: anyhow::Error) -> (StatusCode, String) {
|
|||||||
format!("Something went wrong: {}", err),
|
format!("Something went wrong: {}", err),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
# async {
|
# let _: Router = app;
|
||||||
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
# };
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# Applying fallible middleware
|
# Applying fallible middleware
|
||||||
@@ -129,9 +127,7 @@ async fn handle_timeout_error(err: BoxError) -> (StatusCode, String) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# async {
|
# let _: Router = app;
|
||||||
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
# };
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# Running extractors for error handling
|
# Running extractors for error handling
|
||||||
@@ -171,9 +167,7 @@ async fn handle_timeout_error(
|
|||||||
format!("`{} {}` failed with {}", method, uri, err),
|
format!("`{} {}` failed with {}", method, uri, err),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
# async {
|
# let _: Router = app;
|
||||||
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
# };
|
|
||||||
```
|
```
|
||||||
|
|
||||||
[`tower::Service`]: `tower::Service`
|
[`tower::Service`]: `tower::Service`
|
||||||
|
|||||||
@@ -47,9 +47,7 @@ async fn create_user(Json(payload): Json<CreateUser>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let app = Router::new().route("/users", post(create_user));
|
let app = Router::new().route("/users", post(create_user));
|
||||||
# async {
|
# let _: Router = app;
|
||||||
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
# };
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# Common extractors
|
# Common extractors
|
||||||
@@ -111,9 +109,7 @@ let app = Router::new()
|
|||||||
.route("/json", post(json))
|
.route("/json", post(json))
|
||||||
.route("/request", post(request))
|
.route("/request", post(request))
|
||||||
.route("/extension", post(extension));
|
.route("/extension", post(extension));
|
||||||
# async {
|
# let _: Router = app;
|
||||||
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
# };
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# Applying multiple extractors
|
# Applying multiple extractors
|
||||||
@@ -151,9 +147,7 @@ async fn get_user_things(
|
|||||||
|
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
# async {
|
# let _: Router = app;
|
||||||
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
# };
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# The order of extractors
|
# The order of extractors
|
||||||
@@ -253,9 +247,7 @@ async fn create_user(payload: Option<Json<Value>>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let app = Router::new().route("/users", post(create_user));
|
let app = Router::new().route("/users", post(create_user));
|
||||||
# async {
|
# let _: Router = app;
|
||||||
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
# };
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Wrapping extractors in `Result` makes them optional and gives you the reason
|
Wrapping extractors in `Result` makes them optional and gives you the reason
|
||||||
@@ -295,9 +287,7 @@ async fn create_user(payload: Result<Json<Value>, JsonRejection>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let app = Router::new().route("/users", post(create_user));
|
let app = Router::new().route("/users", post(create_user));
|
||||||
# async {
|
# let _: Router = app;
|
||||||
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
# };
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# Customizing extractor responses
|
# Customizing extractor responses
|
||||||
@@ -452,9 +442,7 @@ async fn handler(ExtractUserAgent(user_agent): ExtractUserAgent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let app = Router::new().route("/foo", get(handler));
|
let app = Router::new().route("/foo", get(handler));
|
||||||
# async {
|
# let _: Router = app;
|
||||||
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
# };
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Implementing `FromRequest`
|
## Implementing `FromRequest`
|
||||||
@@ -501,9 +489,7 @@ async fn handler(ValidatedBody(body): ValidatedBody) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let app = Router::new().route("/foo", get(handler));
|
let app = Router::new().route("/foo", get(handler));
|
||||||
# async {
|
# let _: Router = app;
|
||||||
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
# };
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Cannot implement both `FromRequest` and `FromRequestParts`
|
## Cannot implement both `FromRequest` and `FromRequestParts`
|
||||||
@@ -624,9 +610,7 @@ async fn handler(user: AuthenticatedUser) {
|
|||||||
let state = State { /* ... */ };
|
let state = State { /* ... */ };
|
||||||
|
|
||||||
let app = Router::new().route("/", get(handler)).layer(Extension(state));
|
let app = Router::new().route("/", get(handler)).layer(Extension(state));
|
||||||
# async {
|
# let _: Router = app;
|
||||||
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
# };
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# Request body limits
|
# Request body limits
|
||||||
|
|||||||
@@ -23,7 +23,5 @@ let app = Router::new().route(
|
|||||||
// All requests to `GET /` will be sent through `ConcurrencyLimitLayer`
|
// All requests to `GET /` will be sent through `ConcurrencyLimitLayer`
|
||||||
get(hander).layer(ConcurrencyLimitLayer::new(64)),
|
get(hander).layer(ConcurrencyLimitLayer::new(64)),
|
||||||
);
|
);
|
||||||
# async {
|
# let _: Router = app;
|
||||||
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
# };
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -28,7 +28,5 @@ let app = Router::new().route(
|
|||||||
// `GET /foo` with a valid token will receive `200 OK`
|
// `GET /foo` with a valid token will receive `200 OK`
|
||||||
// `GET /foo` with a invalid token will receive `401 Unauthorized`
|
// `GET /foo` with a invalid token will receive `401 Unauthorized`
|
||||||
// `POST /FOO` with a invalid token will receive `405 Method Not Allowed`
|
// `POST /FOO` with a invalid token will receive `405 Method Not Allowed`
|
||||||
# async {
|
# let _: Router = app;
|
||||||
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
# };
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -55,9 +55,7 @@ let app = Router::new()
|
|||||||
.layer(TraceLayer::new_for_http())
|
.layer(TraceLayer::new_for_http())
|
||||||
.layer(Extension(State {}))
|
.layer(Extension(State {}))
|
||||||
);
|
);
|
||||||
# async {
|
# let _: Router = app;
|
||||||
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
# };
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# Commonly used middleware
|
# Commonly used middleware
|
||||||
@@ -319,9 +317,7 @@ let app = Router::new()
|
|||||||
}))
|
}))
|
||||||
.layer(TimeoutLayer::new(Duration::from_secs(10)))
|
.layer(TimeoutLayer::new(Duration::from_secs(10)))
|
||||||
);
|
);
|
||||||
# async {
|
# let _: Router = app;
|
||||||
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
# };
|
|
||||||
```
|
```
|
||||||
|
|
||||||
See [`error_handling`](crate::error_handling) for more details on axum's error
|
See [`error_handling`](crate::error_handling) for more details on axum's error
|
||||||
@@ -376,9 +372,7 @@ let app = Router::new().route("/", get(handler));
|
|||||||
let app = ServiceBuilder::new()
|
let app = ServiceBuilder::new()
|
||||||
.layer(some_backpressure_sensitive_middleware)
|
.layer(some_backpressure_sensitive_middleware)
|
||||||
.service(app);
|
.service(app);
|
||||||
# async {
|
# let _: Router = app;
|
||||||
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
# };
|
|
||||||
```
|
```
|
||||||
|
|
||||||
However when applying middleware around your whole application in this way
|
However when applying middleware around your whole application in this way
|
||||||
@@ -563,10 +557,8 @@ let app = Router::new();
|
|||||||
let app_with_middleware = middleware.layer(app);
|
let app_with_middleware = middleware.layer(app);
|
||||||
|
|
||||||
# async {
|
# async {
|
||||||
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
.serve(app_with_middleware.into_make_service())
|
axum::serve(listener, app_with_middleware.into_make_service()).await.unwrap();
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
# };
|
# };
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -21,12 +21,8 @@ async fn handler(ConnectInfo(addr): ConnectInfo<SocketAddr>) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# async {
|
# async {
|
||||||
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
.serve(
|
axum::serve(listener, app.into_make_service_with_connect_info::<SocketAddr>()).await.unwrap();
|
||||||
app.into_make_service_with_connect_info::<SocketAddr>()
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.expect("server failed");
|
|
||||||
# };
|
# };
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -36,9 +32,9 @@ You can implement custom a [`Connected`] like so:
|
|||||||
use axum::{
|
use axum::{
|
||||||
extract::connect_info::{ConnectInfo, Connected},
|
extract::connect_info::{ConnectInfo, Connected},
|
||||||
routing::get,
|
routing::get,
|
||||||
|
serve::IncomingStream,
|
||||||
Router,
|
Router,
|
||||||
};
|
};
|
||||||
use hyper::server::conn::AddrStream;
|
|
||||||
|
|
||||||
let app = Router::new().route("/", get(handler));
|
let app = Router::new().route("/", get(handler));
|
||||||
|
|
||||||
@@ -53,8 +49,8 @@ struct MyConnectInfo {
|
|||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Connected<&AddrStream> for MyConnectInfo {
|
impl Connected<IncomingStream<'_>> for MyConnectInfo {
|
||||||
fn connect_info(target: &AddrStream) -> Self {
|
fn connect_info(target: IncomingStream<'_>) -> Self {
|
||||||
MyConnectInfo {
|
MyConnectInfo {
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
@@ -62,12 +58,8 @@ impl Connected<&AddrStream> for MyConnectInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# async {
|
# async {
|
||||||
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
.serve(
|
axum::serve(listener, app.into_make_service_with_connect_info::<MyConnectInfo>()).await.unwrap();
|
||||||
app.into_make_service_with_connect_info::<MyConnectInfo>()
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.expect("server failed");
|
|
||||||
# };
|
# };
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -24,9 +24,7 @@ let app = Router::new().nest("/api", api_routes);
|
|||||||
// Our app now accepts
|
// Our app now accepts
|
||||||
// - GET /api/users/:id
|
// - GET /api/users/:id
|
||||||
// - POST /api/teams
|
// - POST /api/teams
|
||||||
# async {
|
# let _: Router = app;
|
||||||
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
# };
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# How the URI changes
|
# How the URI changes
|
||||||
@@ -59,9 +57,7 @@ async fn users_get(Path(params): Path<HashMap<String, String>>) {
|
|||||||
let users_api = Router::new().route("/users/:id", get(users_get));
|
let users_api = Router::new().route("/users/:id", get(users_get));
|
||||||
|
|
||||||
let app = Router::new().nest("/:version/api", users_api);
|
let app = Router::new().nest("/:version/api", users_api);
|
||||||
# async {
|
# let _: Router = app;
|
||||||
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
# };
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# Differences from wildcard routes
|
# Differences from wildcard routes
|
||||||
@@ -83,9 +79,7 @@ let app = Router::new()
|
|||||||
// `uri` will contain `/foo`
|
// `uri` will contain `/foo`
|
||||||
}))
|
}))
|
||||||
.nest("/bar", nested_router);
|
.nest("/bar", nested_router);
|
||||||
# async {
|
# let _: Router = app;
|
||||||
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
# };
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# Fallbacks
|
# Fallbacks
|
||||||
|
|||||||
@@ -77,9 +77,7 @@ async fn get_root() {}
|
|||||||
async fn post_root() {}
|
async fn post_root() {}
|
||||||
|
|
||||||
async fn delete_root() {}
|
async fn delete_root() {}
|
||||||
# async {
|
# let _: Router = app;
|
||||||
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
# };
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# More examples
|
# More examples
|
||||||
@@ -105,9 +103,7 @@ async fn show_user(Path(id): Path<u64>) {}
|
|||||||
async fn do_users_action(Path((version, id)): Path<(String, u64)>) {}
|
async fn do_users_action(Path((version, id)): Path<(String, u64)>) {}
|
||||||
|
|
||||||
async fn serve_asset(Path(path): Path<String>) {}
|
async fn serve_asset(Path(path): Path<String>) {}
|
||||||
# async {
|
# let _: Router = app;
|
||||||
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
# };
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# Panics
|
# Panics
|
||||||
@@ -120,9 +116,7 @@ use axum::{routing::get, Router};
|
|||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
.route("/", get(|| async {}))
|
.route("/", get(|| async {}))
|
||||||
.route("/", get(|| async {}));
|
.route("/", get(|| async {}));
|
||||||
# async {
|
# let _: Router = app;
|
||||||
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
# };
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The static route `/foo` and the dynamic route `/:key` are not considered to
|
The static route `/foo` and the dynamic route `/:key` are not considered to
|
||||||
|
|||||||
@@ -26,7 +26,5 @@ let app = Router::new()
|
|||||||
// `GET /foo` with a valid token will receive `200 OK`
|
// `GET /foo` with a valid token will receive `200 OK`
|
||||||
// `GET /foo` with a invalid token will receive `401 Unauthorized`
|
// `GET /foo` with a invalid token will receive `401 Unauthorized`
|
||||||
// `GET /not-found` with a invalid token will receive `404 Not Found`
|
// `GET /not-found` with a invalid token will receive `404 Not Found`
|
||||||
# async {
|
# let _: Router = app;
|
||||||
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
# };
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -43,9 +43,7 @@ let app = Router::new()
|
|||||||
"/static/Cargo.toml",
|
"/static/Cargo.toml",
|
||||||
ServeFile::new("Cargo.toml"),
|
ServeFile::new("Cargo.toml"),
|
||||||
);
|
);
|
||||||
# async {
|
# let _: Router = app;
|
||||||
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
# };
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Routing to arbitrary services in this way has complications for backpressure
|
Routing to arbitrary services in this way has complications for backpressure
|
||||||
@@ -64,9 +62,7 @@ let app = Router::new().route_service(
|
|||||||
"/",
|
"/",
|
||||||
Router::new().route("/foo", get(|| async {})),
|
Router::new().route("/foo", get(|| async {})),
|
||||||
);
|
);
|
||||||
# async {
|
# let _: Router = app;
|
||||||
# axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
# };
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Use [`Router::nest`] instead.
|
Use [`Router::nest`] instead.
|
||||||
|
|||||||
@@ -13,9 +13,8 @@ let routes = Router::new()
|
|||||||
.with_state(AppState {});
|
.with_state(AppState {});
|
||||||
|
|
||||||
# async {
|
# async {
|
||||||
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
.serve(routes.into_make_service())
|
axum::serve(listener, routes).await.unwrap();
|
||||||
.await;
|
|
||||||
# };
|
# };
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -40,9 +39,8 @@ fn routes() -> Router<AppState> {
|
|||||||
let routes = routes().with_state(AppState {});
|
let routes = routes().with_state(AppState {});
|
||||||
|
|
||||||
# async {
|
# async {
|
||||||
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
.serve(routes.into_make_service())
|
axum::serve(listener, routes).await.unwrap();
|
||||||
.await;
|
|
||||||
# };
|
# };
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -64,9 +62,8 @@ fn routes(state: AppState) -> Router {
|
|||||||
let routes = routes(AppState {});
|
let routes = routes(AppState {});
|
||||||
|
|
||||||
# async {
|
# async {
|
||||||
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
.serve(routes.into_make_service())
|
axum::serve(listener, routes).await.unwrap();
|
||||||
.await;
|
|
||||||
# };
|
# };
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -92,9 +89,8 @@ fn routes<S>(state: AppState) -> Router<S> {
|
|||||||
let routes = Router::new().nest("/api", routes(AppState {}));
|
let routes = Router::new().nest("/api", routes(AppState {}));
|
||||||
|
|
||||||
# async {
|
# async {
|
||||||
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
.serve(routes.into_make_service())
|
axum::serve(listener, routes).await.unwrap();
|
||||||
.await;
|
|
||||||
# };
|
# };
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -133,9 +129,8 @@ let router: Router<()> = router.with_state(AppState {});
|
|||||||
// You cannot call `into_make_service` on a `Router<AppState>`
|
// You cannot call `into_make_service` on a `Router<AppState>`
|
||||||
// because it is still missing an `AppState`.
|
// because it is still missing an `AppState`.
|
||||||
# async {
|
# async {
|
||||||
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
.serve(router.into_make_service())
|
axum::serve(listener, router).await.unwrap();
|
||||||
.await;
|
|
||||||
# };
|
# };
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -163,9 +158,8 @@ let final_router: Router<()> = string_router.with_state("foo".to_owned());
|
|||||||
|
|
||||||
// Since we have a `Router<()>` we can run it.
|
// Since we have a `Router<()>` we can run it.
|
||||||
# async {
|
# async {
|
||||||
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
.serve(final_router.into_make_service())
|
axum::serve(listener, final_router).await.unwrap();
|
||||||
.await;
|
|
||||||
# };
|
# };
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -190,9 +184,8 @@ let app = routes(AppState {});
|
|||||||
// We can only call `Router::into_make_service` on a `Router<()>`
|
// We can only call `Router::into_make_service` on a `Router<()>`
|
||||||
// but `app` is a `Router<AppState>`
|
// but `app` is a `Router<AppState>`
|
||||||
# async {
|
# async {
|
||||||
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
.serve(app.into_make_service())
|
axum::serve(listener, app).await.unwrap();
|
||||||
.await;
|
|
||||||
# };
|
# };
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -214,9 +207,8 @@ let app = routes(AppState {});
|
|||||||
|
|
||||||
// We can now call `Router::into_make_service`
|
// We can now call `Router::into_make_service`
|
||||||
# async {
|
# async {
|
||||||
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
.serve(app.into_make_service())
|
axum::serve(listener, app).await.unwrap();
|
||||||
.await;
|
|
||||||
# };
|
# };
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -40,9 +40,7 @@ use tower_service::Service;
|
|||||||
/// // Add middleware that inserts the state into all incoming request's
|
/// // Add middleware that inserts the state into all incoming request's
|
||||||
/// // extensions.
|
/// // extensions.
|
||||||
/// .layer(Extension(state));
|
/// .layer(Extension(state));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// If the extension is missing it will reject the request with a `500 Internal
|
/// If the extension is missing it will reject the request with a `500 Internal
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
//! [`Router::into_make_service_with_connect_info`]: crate::routing::Router::into_make_service_with_connect_info
|
//! [`Router::into_make_service_with_connect_info`]: crate::routing::Router::into_make_service_with_connect_info
|
||||||
|
|
||||||
use super::{Extension, FromRequestParts};
|
use super::{Extension, FromRequestParts};
|
||||||
use crate::middleware::AddExtension;
|
use crate::{middleware::AddExtension, serve::IncomingStream};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use http::request::Parts;
|
use http::request::Parts;
|
||||||
use hyper::server::conn::AddrStream;
|
use hyper::server::conn::AddrStream;
|
||||||
@@ -89,6 +89,12 @@ impl Connected<&AddrStream> for SocketAddr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Connected<IncomingStream<'_>> for SocketAddr {
|
||||||
|
fn connect_info(target: IncomingStream<'_>) -> Self {
|
||||||
|
target.remote_addr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<S, C, T> Service<T> for IntoMakeServiceWithConnectInfo<S, C>
|
impl<S, C, T> Service<T> for IntoMakeServiceWithConnectInfo<S, C>
|
||||||
where
|
where
|
||||||
S: Clone,
|
S: Clone,
|
||||||
@@ -213,8 +219,9 @@ where
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{routing::get, test_helpers::TestClient, Router, Server};
|
use crate::{routing::get, test_helpers::TestClient, Router};
|
||||||
use std::net::{SocketAddr, TcpListener};
|
use std::net::SocketAddr;
|
||||||
|
use tokio::net::TcpListener;
|
||||||
|
|
||||||
#[crate::test]
|
#[crate::test]
|
||||||
async fn socket_addr() {
|
async fn socket_addr() {
|
||||||
@@ -222,17 +229,19 @@ mod tests {
|
|||||||
format!("{addr}")
|
format!("{addr}")
|
||||||
}
|
}
|
||||||
|
|
||||||
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
|
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
|
||||||
let addr = listener.local_addr().unwrap();
|
let addr = listener.local_addr().unwrap();
|
||||||
|
|
||||||
let (tx, rx) = tokio::sync::oneshot::channel();
|
let (tx, rx) = tokio::sync::oneshot::channel();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let app = Router::new().route("/", get(handler));
|
let app = Router::new().route("/", get(handler));
|
||||||
let server = Server::from_tcp(listener)
|
|
||||||
.unwrap()
|
|
||||||
.serve(app.into_make_service_with_connect_info::<SocketAddr>());
|
|
||||||
tx.send(()).unwrap();
|
tx.send(()).unwrap();
|
||||||
server.await.expect("server error");
|
crate::serve(
|
||||||
|
listener,
|
||||||
|
app.into_make_service_with_connect_info::<SocketAddr>(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
});
|
});
|
||||||
rx.await.unwrap();
|
rx.await.unwrap();
|
||||||
|
|
||||||
@@ -250,8 +259,8 @@ mod tests {
|
|||||||
value: &'static str,
|
value: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Connected<&AddrStream> for MyConnectInfo {
|
impl Connected<IncomingStream<'_>> for MyConnectInfo {
|
||||||
fn connect_info(_target: &AddrStream) -> Self {
|
fn connect_info(_target: IncomingStream<'_>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
value: "it worked!",
|
value: "it worked!",
|
||||||
}
|
}
|
||||||
@@ -262,17 +271,19 @@ mod tests {
|
|||||||
addr.value
|
addr.value
|
||||||
}
|
}
|
||||||
|
|
||||||
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
|
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
|
||||||
let addr = listener.local_addr().unwrap();
|
let addr = listener.local_addr().unwrap();
|
||||||
|
|
||||||
let (tx, rx) = tokio::sync::oneshot::channel();
|
let (tx, rx) = tokio::sync::oneshot::channel();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let app = Router::new().route("/", get(handler));
|
let app = Router::new().route("/", get(handler));
|
||||||
let server = Server::from_tcp(listener)
|
|
||||||
.unwrap()
|
|
||||||
.serve(app.into_make_service_with_connect_info::<MyConnectInfo>());
|
|
||||||
tx.send(()).unwrap();
|
tx.send(()).unwrap();
|
||||||
server.await.expect("server error");
|
crate::serve(
|
||||||
|
listener,
|
||||||
|
app.into_make_service_with_connect_info::<MyConnectInfo>(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
});
|
});
|
||||||
rx.await.unwrap();
|
rx.await.unwrap();
|
||||||
|
|
||||||
@@ -306,7 +317,7 @@ mod tests {
|
|||||||
format!("{addr}")
|
format!("{addr}")
|
||||||
}
|
}
|
||||||
|
|
||||||
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
|
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
|
||||||
let addr = listener.local_addr().unwrap();
|
let addr = listener.local_addr().unwrap();
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
@@ -314,10 +325,12 @@ mod tests {
|
|||||||
.route("/", get(handler))
|
.route("/", get(handler))
|
||||||
.layer(MockConnectInfo(SocketAddr::from(([0, 0, 0, 0], 1337))));
|
.layer(MockConnectInfo(SocketAddr::from(([0, 0, 0, 0], 1337))));
|
||||||
|
|
||||||
let server = Server::from_tcp(listener)
|
crate::serve(
|
||||||
.unwrap()
|
listener,
|
||||||
.serve(app.into_make_service_with_connect_info::<SocketAddr>());
|
app.into_make_service_with_connect_info::<SocketAddr>(),
|
||||||
server.await.expect("server error");
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
});
|
});
|
||||||
|
|
||||||
let client = reqwest::Client::new();
|
let client = reqwest::Client::new();
|
||||||
|
|||||||
@@ -20,9 +20,7 @@ use std::{collections::HashMap, sync::Arc};
|
|||||||
/// // `path` will be "/users/:id"
|
/// // `path` will be "/users/:id"
|
||||||
/// })
|
/// })
|
||||||
/// );
|
/// );
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// # Accessing `MatchedPath` via extensions
|
/// # Accessing `MatchedPath` via extensions
|
||||||
|
|||||||
@@ -48,9 +48,7 @@ use std::{
|
|||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// let app = Router::new().route("/upload", post(upload));
|
/// let app = Router::new().route("/upload", post(upload));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "multipart")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "multipart")))]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|||||||
@@ -42,9 +42,7 @@ use std::{fmt, sync::Arc};
|
|||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// let app = Router::new().route("/users/:user_id/team/:team_id", get(users_teams_show));
|
/// let app = Router::new().route("/users/:user_id/team/:team_id", get(users_teams_show));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// If the path contains only one parameter, then you can omit the tuple.
|
/// If the path contains only one parameter, then you can omit the tuple.
|
||||||
@@ -62,9 +60,7 @@ use std::{fmt, sync::Arc};
|
|||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// let app = Router::new().route("/users/:user_id", get(user_info));
|
/// let app = Router::new().route("/users/:user_id", get(user_info));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Path segments also can be deserialized into any type that implements
|
/// Path segments also can be deserialized into any type that implements
|
||||||
@@ -103,9 +99,7 @@ use std::{fmt, sync::Arc};
|
|||||||
/// "/users/:user_id/team/:team_id",
|
/// "/users/:user_id/team/:team_id",
|
||||||
/// get(users_teams_show).post(users_teams_create),
|
/// get(users_teams_show).post(users_teams_create),
|
||||||
/// );
|
/// );
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// If you wish to capture all path parameters you can use `HashMap` or `Vec`:
|
/// If you wish to capture all path parameters you can use `HashMap` or `Vec`:
|
||||||
@@ -132,9 +126,7 @@ use std::{fmt, sync::Arc};
|
|||||||
///
|
///
|
||||||
/// let app = Router::new()
|
/// let app = Router::new()
|
||||||
/// .route("/users/:user_id/team/:team_id", get(params_map).post(params_vec));
|
/// .route("/users/:user_id/team/:team_id", get(params_map).post(params_vec));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// # Providing detailed rejection output
|
/// # Providing detailed rejection output
|
||||||
|
|||||||
@@ -32,9 +32,7 @@ use serde::de::DeserializeOwned;
|
|||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// let app = Router::new().route("/list_things", get(list_things));
|
/// let app = Router::new().route("/list_things", get(list_things));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// If the query string cannot be parsed it will reject the request with a `400
|
/// If the query string cannot be parsed it will reject the request with a `400
|
||||||
|
|||||||
@@ -25,9 +25,7 @@ use super::{
|
|||||||
/// async fn handler(RawForm(form): RawForm) {}
|
/// async fn handler(RawForm(form): RawForm) {}
|
||||||
///
|
///
|
||||||
/// let app = Router::new().route("/", get(handler));
|
/// let app = Router::new().route("/", get(handler));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RawForm(pub Bytes);
|
pub struct RawForm(pub Bytes);
|
||||||
|
|||||||
@@ -20,9 +20,7 @@ use std::convert::Infallible;
|
|||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// let app = Router::new().route("/users", get(handler));
|
/// let app = Router::new().route("/users", get(handler));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RawQuery(pub Option<String>);
|
pub struct RawQuery(pub Option<String>);
|
||||||
|
|||||||
@@ -28,9 +28,7 @@ use std::convert::Infallible;
|
|||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
/// let app = Router::new().nest("/api", api_routes);
|
/// let app = Router::new().nest("/api", api_routes);
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// # Extracting via request extensions
|
/// # Extracting via request extensions
|
||||||
@@ -65,9 +63,7 @@ use std::convert::Infallible;
|
|||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
/// let app = Router::new().nest("/api", api_routes);
|
/// let app = Router::new().nest("/api", api_routes);
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(feature = "original-uri")]
|
#[cfg(feature = "original-uri")]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|||||||
@@ -131,13 +131,11 @@ use std::{
|
|||||||
/// let method_router_with_state = get(handler)
|
/// let method_router_with_state = get(handler)
|
||||||
/// // provide the state so the handler can access it
|
/// // provide the state so the handler can access it
|
||||||
/// .with_state(state);
|
/// .with_state(state);
|
||||||
|
/// # let _: axum::routing::MethodRouter = method_router_with_state;
|
||||||
///
|
///
|
||||||
/// async fn handler(State(state): State<AppState>) {
|
/// async fn handler(State(state): State<AppState>) {
|
||||||
/// // use `state`...
|
/// // use `state`...
|
||||||
/// }
|
/// }
|
||||||
/// # async {
|
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(method_router_with_state.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// # With `Handler`
|
/// # With `Handler`
|
||||||
@@ -158,10 +156,8 @@ use std::{
|
|||||||
/// let handler_with_state = handler.with_state(state);
|
/// let handler_with_state = handler.with_state(state);
|
||||||
///
|
///
|
||||||
/// # async {
|
/// # async {
|
||||||
/// axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
|
/// let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
/// .serve(handler_with_state.into_make_service())
|
/// axum::serve(listener, handler_with_state.into_make_service()).await.unwrap();
|
||||||
/// .await
|
|
||||||
/// .expect("server failed");
|
|
||||||
/// # };
|
/// # };
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
|||||||
+6
-13
@@ -31,9 +31,7 @@
|
|||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//! }
|
//! }
|
||||||
//! # async {
|
//! # let _: Router = app;
|
||||||
//! # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
//! # };
|
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! # Passing data and/or state to an `on_upgrade` callback
|
//! # Passing data and/or state to an `on_upgrade` callback
|
||||||
@@ -62,9 +60,7 @@
|
|||||||
//! let app = Router::new()
|
//! let app = Router::new()
|
||||||
//! .route("/ws", get(handler))
|
//! .route("/ws", get(handler))
|
||||||
//! .with_state(AppState { /* ... */ });
|
//! .with_state(AppState { /* ... */ });
|
||||||
//! # async {
|
//! # let _: Router = app;
|
||||||
//! # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
//! # };
|
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! # Read and write concurrently
|
//! # Read and write concurrently
|
||||||
@@ -108,7 +104,6 @@ use http::{
|
|||||||
request::Parts,
|
request::Parts,
|
||||||
Method, StatusCode,
|
Method, StatusCode,
|
||||||
};
|
};
|
||||||
use hyper::upgrade::{OnUpgrade, Upgraded};
|
|
||||||
use sha1::{Digest, Sha1};
|
use sha1::{Digest, Sha1};
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
@@ -137,7 +132,7 @@ pub struct WebSocketUpgrade<F = DefaultOnFailedUpgrade> {
|
|||||||
/// The chosen protocol sent in the `Sec-WebSocket-Protocol` header of the response.
|
/// The chosen protocol sent in the `Sec-WebSocket-Protocol` header of the response.
|
||||||
protocol: Option<HeaderValue>,
|
protocol: Option<HeaderValue>,
|
||||||
sec_websocket_key: HeaderValue,
|
sec_websocket_key: HeaderValue,
|
||||||
on_upgrade: OnUpgrade,
|
on_upgrade: hyper1::upgrade::OnUpgrade,
|
||||||
on_failed_upgrade: F,
|
on_failed_upgrade: F,
|
||||||
sec_websocket_protocol: Option<HeaderValue>,
|
sec_websocket_protocol: Option<HeaderValue>,
|
||||||
}
|
}
|
||||||
@@ -206,9 +201,7 @@ impl<F> WebSocketUpgrade<F> {
|
|||||||
/// // ...
|
/// // ...
|
||||||
/// })
|
/// })
|
||||||
/// }
|
/// }
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
pub fn protocols<I>(mut self, protocols: I) -> Self
|
pub fn protocols<I>(mut self, protocols: I) -> Self
|
||||||
where
|
where
|
||||||
@@ -393,7 +386,7 @@ where
|
|||||||
|
|
||||||
let on_upgrade = parts
|
let on_upgrade = parts
|
||||||
.extensions
|
.extensions
|
||||||
.remove::<OnUpgrade>()
|
.remove::<hyper1::upgrade::OnUpgrade>()
|
||||||
.ok_or(ConnectionNotUpgradable)?;
|
.ok_or(ConnectionNotUpgradable)?;
|
||||||
|
|
||||||
let sec_websocket_protocol = parts.headers.get(header::SEC_WEBSOCKET_PROTOCOL).cloned();
|
let sec_websocket_protocol = parts.headers.get(header::SEC_WEBSOCKET_PROTOCOL).cloned();
|
||||||
@@ -436,7 +429,7 @@ fn header_contains(headers: &HeaderMap, key: HeaderName, value: &'static str) ->
|
|||||||
/// See [the module level documentation](self) for more details.
|
/// See [the module level documentation](self) for more details.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct WebSocket {
|
pub struct WebSocket {
|
||||||
inner: WebSocketStream<Upgraded>,
|
inner: WebSocketStream<hyper1::upgrade::Upgraded>,
|
||||||
protocol: Option<HeaderValue>,
|
protocol: Option<HeaderValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -135,9 +135,7 @@ pub trait Handler<T, S>: Clone + Send + Sized + 'static {
|
|||||||
///
|
///
|
||||||
/// let layered_handler = handler.layer(ConcurrencyLimitLayer::new(64));
|
/// let layered_handler = handler.layer(ConcurrencyLimitLayer::new(64));
|
||||||
/// let app = Router::new().route("/", get(layered_handler));
|
/// let app = Router::new().route("/", get(layered_handler));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
fn layer<L>(self, layer: L) -> Layered<L, Self, T, S>
|
fn layer<L>(self, layer: L) -> Layered<L, Self, T, S>
|
||||||
where
|
where
|
||||||
|
|||||||
+31
-10
@@ -37,7 +37,6 @@ impl<H, T, S> HandlerService<H, T, S> {
|
|||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use axum::{
|
/// use axum::{
|
||||||
/// Server,
|
|
||||||
/// handler::Handler,
|
/// handler::Handler,
|
||||||
/// extract::State,
|
/// extract::State,
|
||||||
/// http::{Uri, Method},
|
/// http::{Uri, Method},
|
||||||
@@ -55,10 +54,8 @@ impl<H, T, S> HandlerService<H, T, S> {
|
|||||||
/// let app = handler.with_state(AppState {});
|
/// let app = handler.with_state(AppState {});
|
||||||
///
|
///
|
||||||
/// # async {
|
/// # async {
|
||||||
/// Server::bind(&SocketAddr::from(([127, 0, 0, 1], 3000)))
|
/// let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
/// .serve(app.into_make_service())
|
/// axum::serve(listener, app.into_make_service()).await.unwrap();
|
||||||
/// .await?;
|
|
||||||
/// # Ok::<_, hyper::Error>(())
|
|
||||||
/// # };
|
/// # };
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
@@ -74,7 +71,6 @@ impl<H, T, S> HandlerService<H, T, S> {
|
|||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use axum::{
|
/// use axum::{
|
||||||
/// Server,
|
|
||||||
/// handler::Handler,
|
/// handler::Handler,
|
||||||
/// response::IntoResponse,
|
/// response::IntoResponse,
|
||||||
/// extract::{ConnectInfo, State},
|
/// extract::{ConnectInfo, State},
|
||||||
@@ -94,10 +90,11 @@ impl<H, T, S> HandlerService<H, T, S> {
|
|||||||
/// let app = handler.with_state(AppState {});
|
/// let app = handler.with_state(AppState {});
|
||||||
///
|
///
|
||||||
/// # async {
|
/// # async {
|
||||||
/// Server::bind(&SocketAddr::from(([127, 0, 0, 1], 3000)))
|
/// let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
/// .serve(app.into_make_service_with_connect_info::<SocketAddr>())
|
/// axum::serve(
|
||||||
/// .await?;
|
/// listener,
|
||||||
/// # Ok::<_, hyper::Error>(())
|
/// app.into_make_service_with_connect_info::<SocketAddr>(),
|
||||||
|
/// ).await.unwrap();
|
||||||
/// # };
|
/// # };
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
@@ -179,3 +176,27 @@ where
|
|||||||
super::future::IntoServiceFuture::new(future)
|
super::future::IntoServiceFuture::new(future)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for `axum::serve(listener, handler)`
|
||||||
|
#[cfg(feature = "tokio")]
|
||||||
|
const _: () = {
|
||||||
|
use crate::serve::IncomingStream;
|
||||||
|
|
||||||
|
impl<H, T, S> Service<IncomingStream<'_>> for HandlerService<H, T, S>
|
||||||
|
where
|
||||||
|
H: Clone,
|
||||||
|
S: Clone,
|
||||||
|
{
|
||||||
|
type Response = Self;
|
||||||
|
type Error = Infallible;
|
||||||
|
type Future = std::future::Ready<Result<Self::Response, Self::Error>>;
|
||||||
|
|
||||||
|
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||||
|
Poll::Ready(Ok(()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&mut self, _req: IncomingStream<'_>) -> Self::Future {
|
||||||
|
std::future::ready(Ok(self.clone()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
+2
-6
@@ -50,9 +50,7 @@ use serde::{de::DeserializeOwned, Serialize};
|
|||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// let app = Router::new().route("/users", post(create_user));
|
/// let app = Router::new().route("/users", post(create_user));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// When used as a response, it can serialize any type that implements [`serde::Serialize`] to
|
/// When used as a response, it can serialize any type that implements [`serde::Serialize`] to
|
||||||
@@ -87,9 +85,7 @@ use serde::{de::DeserializeOwned, Serialize};
|
|||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// let app = Router::new().route("/users/:id", get(get_user));
|
/// let app = Router::new().route("/users/:id", get(get_user));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Debug, Clone, Copy, Default)]
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
|
||||||
|
|||||||
+15
-25
@@ -53,11 +53,9 @@
|
|||||||
//! // build our application with a single route
|
//! // build our application with a single route
|
||||||
//! let app = Router::new().route("/", get(|| async { "Hello, World!" }));
|
//! let app = Router::new().route("/", get(|| async { "Hello, World!" }));
|
||||||
//!
|
//!
|
||||||
//! // run it with hyper on localhost:3000
|
//! // run it on localhost:3000
|
||||||
//! axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
|
//! let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
//! .serve(app.into_make_service())
|
//! axum::serve(listener, app).await.unwrap();
|
||||||
//! .await
|
|
||||||
//! .unwrap();
|
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
@@ -82,9 +80,7 @@
|
|||||||
//! async fn get_foo() {}
|
//! async fn get_foo() {}
|
||||||
//! async fn post_foo() {}
|
//! async fn post_foo() {}
|
||||||
//! async fn foo_bar() {}
|
//! async fn foo_bar() {}
|
||||||
//! # async {
|
//! # let _: Router = app;
|
||||||
//! # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
//! # };
|
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! See [`Router`] for more details on routing.
|
//! See [`Router`] for more details on routing.
|
||||||
@@ -145,9 +141,7 @@
|
|||||||
//! let app = Router::new()
|
//! let app = Router::new()
|
||||||
//! .route("/plain_text", get(plain_text))
|
//! .route("/plain_text", get(plain_text))
|
||||||
//! .route("/json", get(json));
|
//! .route("/json", get(json));
|
||||||
//! # async {
|
//! # let _: Router = app;
|
||||||
//! # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
//! # };
|
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! See [`response`](crate::response) for more details on building responses.
|
//! See [`response`](crate::response) for more details on building responses.
|
||||||
@@ -202,9 +196,7 @@
|
|||||||
//! ) {
|
//! ) {
|
||||||
//! // ...
|
//! // ...
|
||||||
//! }
|
//! }
|
||||||
//! # async {
|
//! # let _: Router = app;
|
||||||
//! # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
//! # };
|
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! You should prefer using [`State`] if possible since it's more type safe. The downside is that
|
//! You should prefer using [`State`] if possible since it's more type safe. The downside is that
|
||||||
@@ -240,9 +232,7 @@
|
|||||||
//! ) {
|
//! ) {
|
||||||
//! // ...
|
//! // ...
|
||||||
//! }
|
//! }
|
||||||
//! # async {
|
//! # let _: Router = app;
|
||||||
//! # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
//! # };
|
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! The downside to this approach is that you'll get runtime errors
|
//! The downside to this approach is that you'll get runtime errors
|
||||||
@@ -298,9 +288,7 @@
|
|||||||
//! struct CreateUserPayload {
|
//! struct CreateUserPayload {
|
||||||
//! // ...
|
//! // ...
|
||||||
//! }
|
//! }
|
||||||
//! # async {
|
//! # let _: Router = app;
|
||||||
//! # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
//! # };
|
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! The downside to this approach is that it's a little more verbose than using
|
//! The downside to this approach is that it's a little more verbose than using
|
||||||
@@ -356,7 +344,7 @@
|
|||||||
//! `matched-path` | Enables capturing of every request's router path and the [`MatchedPath`] extractor | Yes
|
//! `matched-path` | Enables capturing of every request's router path and the [`MatchedPath`] extractor | Yes
|
||||||
//! `multipart` | Enables parsing `multipart/form-data` requests with [`Multipart`] | No
|
//! `multipart` | Enables parsing `multipart/form-data` requests with [`Multipart`] | No
|
||||||
//! `original-uri` | Enables capturing of every request's original URI and the [`OriginalUri`] extractor | Yes
|
//! `original-uri` | Enables capturing of every request's original URI and the [`OriginalUri`] extractor | Yes
|
||||||
//! `tokio` | Enables `tokio` as a dependency and `axum::Server`, `SSE` and `extract::connect_info` types. | Yes
|
//! `tokio` | Enables `tokio` as a dependency and `axum::serve`, `SSE` and `extract::connect_info` types. | Yes
|
||||||
//! `tower-log` | Enables `tower`'s `log` feature | Yes
|
//! `tower-log` | Enables `tower`'s `log` feature | Yes
|
||||||
//! `tracing` | Log rejections from built-in extractors | No
|
//! `tracing` | Log rejections from built-in extractors | No
|
||||||
//! `ws` | Enables WebSockets support via [`extract::ws`] | No
|
//! `ws` | Enables WebSockets support via [`extract::ws`] | No
|
||||||
@@ -377,7 +365,6 @@
|
|||||||
//! [`Timeout`]: tower::timeout::Timeout
|
//! [`Timeout`]: tower::timeout::Timeout
|
||||||
//! [examples]: https://github.com/tokio-rs/axum/tree/main/examples
|
//! [examples]: https://github.com/tokio-rs/axum/tree/main/examples
|
||||||
//! [`Router::merge`]: crate::routing::Router::merge
|
//! [`Router::merge`]: crate::routing::Router::merge
|
||||||
//! [`axum::Server`]: hyper::server::Server
|
|
||||||
//! [`Service`]: tower::Service
|
//! [`Service`]: tower::Service
|
||||||
//! [`Service::poll_ready`]: tower::Service::poll_ready
|
//! [`Service::poll_ready`]: tower::Service::poll_ready
|
||||||
//! [`Service`'s]: tower::Service
|
//! [`Service`'s]: tower::Service
|
||||||
@@ -459,6 +446,8 @@ pub mod handler;
|
|||||||
pub mod middleware;
|
pub mod middleware;
|
||||||
pub mod response;
|
pub mod response;
|
||||||
pub mod routing;
|
pub mod routing;
|
||||||
|
#[cfg(feature = "tokio")]
|
||||||
|
pub mod serve;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_helpers;
|
mod test_helpers;
|
||||||
@@ -470,9 +459,6 @@ pub use async_trait::async_trait;
|
|||||||
pub use headers;
|
pub use headers;
|
||||||
#[doc(no_inline)]
|
#[doc(no_inline)]
|
||||||
pub use http;
|
pub use http;
|
||||||
#[cfg(feature = "tokio")]
|
|
||||||
#[doc(no_inline)]
|
|
||||||
pub use hyper::Server;
|
|
||||||
|
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use self::extension::Extension;
|
pub use self::extension::Extension;
|
||||||
@@ -496,6 +482,10 @@ pub use axum_core::{BoxError, Error, RequestExt, RequestPartsExt};
|
|||||||
#[cfg(feature = "macros")]
|
#[cfg(feature = "macros")]
|
||||||
pub use axum_macros::debug_handler;
|
pub use axum_macros::debug_handler;
|
||||||
|
|
||||||
|
#[cfg(feature = "tokio")]
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use self::serve::serve;
|
||||||
|
|
||||||
pub use self::service_ext::ServiceExt;
|
pub use self::service_ext::ServiceExt;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -84,9 +84,7 @@ use tower_service::Service;
|
|||||||
/// .route("/foo", post(other_handler))
|
/// .route("/foo", post(other_handler))
|
||||||
/// // The extractor will run before all routes
|
/// // The extractor will run before all routes
|
||||||
/// .route_layer(from_extractor::<RequireAuth>());
|
/// .route_layer(from_extractor::<RequireAuth>());
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// [`Bytes`]: bytes::Bytes
|
/// [`Bytes`]: bytes::Bytes
|
||||||
|
|||||||
@@ -48,9 +48,7 @@ macro_rules! top_level_service_fn {
|
|||||||
///
|
///
|
||||||
/// // Requests to `GET /` will go to `service`.
|
/// // Requests to `GET /` will go to `service`.
|
||||||
/// let app = Router::new().route("/", get_service(service));
|
/// let app = Router::new().route("/", get_service(service));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Note that `get` routes will also be called for `HEAD` requests but will have
|
/// Note that `get` routes will also be called for `HEAD` requests but will have
|
||||||
@@ -109,9 +107,7 @@ macro_rules! top_level_handler_fn {
|
|||||||
///
|
///
|
||||||
/// // Requests to `GET /` will go to `handler`.
|
/// // Requests to `GET /` will go to `handler`.
|
||||||
/// let app = Router::new().route("/", get(handler));
|
/// let app = Router::new().route("/", get(handler));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Note that `get` routes will also be called for `HEAD` requests but will have
|
/// Note that `get` routes will also be called for `HEAD` requests but will have
|
||||||
@@ -180,9 +176,7 @@ macro_rules! chained_service_fn {
|
|||||||
/// // Requests to `POST /` will go to `service` and `GET /` will go to
|
/// // Requests to `POST /` will go to `service` and `GET /` will go to
|
||||||
/// // `other_service`.
|
/// // `other_service`.
|
||||||
/// let app = Router::new().route("/", post_service(service).get_service(other_service));
|
/// let app = Router::new().route("/", post_service(service).get_service(other_service));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Note that `get` routes will also be called for `HEAD` requests but will have
|
/// Note that `get` routes will also be called for `HEAD` requests but will have
|
||||||
@@ -244,9 +238,7 @@ macro_rules! chained_handler_fn {
|
|||||||
/// // Requests to `POST /` will go to `handler` and `GET /` will go to
|
/// // Requests to `POST /` will go to `handler` and `GET /` will go to
|
||||||
/// // `other_handler`.
|
/// // `other_handler`.
|
||||||
/// let app = Router::new().route("/", post(handler).get(other_handler));
|
/// let app = Router::new().route("/", post(handler).get(other_handler));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Note that `get` routes will also be called for `HEAD` requests but will have
|
/// Note that `get` routes will also be called for `HEAD` requests but will have
|
||||||
@@ -316,9 +308,7 @@ top_level_service_fn!(trace_service, TRACE);
|
|||||||
///
|
///
|
||||||
/// // Requests to `POST /` will go to `service`.
|
/// // Requests to `POST /` will go to `service`.
|
||||||
/// let app = Router::new().route("/", on_service(MethodFilter::POST, service));
|
/// let app = Router::new().route("/", on_service(MethodFilter::POST, service));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
pub fn on_service<T, S>(filter: MethodFilter, svc: T) -> MethodRouter<S, T::Error>
|
pub fn on_service<T, S>(filter: MethodFilter, svc: T) -> MethodRouter<S, T::Error>
|
||||||
where
|
where
|
||||||
@@ -350,9 +340,7 @@ where
|
|||||||
///
|
///
|
||||||
/// // All requests to `/` will go to `service`.
|
/// // All requests to `/` will go to `service`.
|
||||||
/// let app = Router::new().route("/", any_service(service));
|
/// let app = Router::new().route("/", any_service(service));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Additional methods can still be chained:
|
/// Additional methods can still be chained:
|
||||||
@@ -379,9 +367,7 @@ where
|
|||||||
///
|
///
|
||||||
/// // `POST /` goes to `other_service`. All other requests go to `service`
|
/// // `POST /` goes to `other_service`. All other requests go to `service`
|
||||||
/// let app = Router::new().route("/", any_service(service).post_service(other_service));
|
/// let app = Router::new().route("/", any_service(service).post_service(other_service));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
pub fn any_service<T, S>(svc: T) -> MethodRouter<S, T::Error>
|
pub fn any_service<T, S>(svc: T) -> MethodRouter<S, T::Error>
|
||||||
where
|
where
|
||||||
@@ -419,9 +405,7 @@ top_level_handler_fn!(trace, TRACE);
|
|||||||
///
|
///
|
||||||
/// // Requests to `POST /` will go to `handler`.
|
/// // Requests to `POST /` will go to `handler`.
|
||||||
/// let app = Router::new().route("/", on(MethodFilter::POST, handler));
|
/// let app = Router::new().route("/", on(MethodFilter::POST, handler));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
pub fn on<H, T, S>(filter: MethodFilter, handler: H) -> MethodRouter<S, Infallible>
|
pub fn on<H, T, S>(filter: MethodFilter, handler: H) -> MethodRouter<S, Infallible>
|
||||||
where
|
where
|
||||||
@@ -446,9 +430,7 @@ where
|
|||||||
///
|
///
|
||||||
/// // All requests to `/` will go to `handler`.
|
/// // All requests to `/` will go to `handler`.
|
||||||
/// let app = Router::new().route("/", any(handler));
|
/// let app = Router::new().route("/", any(handler));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Additional methods can still be chained:
|
/// Additional methods can still be chained:
|
||||||
@@ -465,9 +447,7 @@ where
|
|||||||
///
|
///
|
||||||
/// // `POST /` goes to `other_handler`. All other requests go to `handler`
|
/// // `POST /` goes to `other_handler`. All other requests go to `handler`
|
||||||
/// let app = Router::new().route("/", any(handler).post(other_handler));
|
/// let app = Router::new().route("/", any(handler).post(other_handler));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
pub fn any<H, T, S>(handler: H) -> MethodRouter<S, Infallible>
|
pub fn any<H, T, S>(handler: H) -> MethodRouter<S, Infallible>
|
||||||
where
|
where
|
||||||
@@ -587,9 +567,7 @@ where
|
|||||||
/// // Requests to `GET /` will go to `handler` and `DELETE /` will go to
|
/// // Requests to `GET /` will go to `handler` and `DELETE /` will go to
|
||||||
/// // `other_handler`
|
/// // `other_handler`
|
||||||
/// let app = Router::new().route("/", get(handler).on(MethodFilter::DELETE, other_handler));
|
/// let app = Router::new().route("/", get(handler).on(MethodFilter::DELETE, other_handler));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn on<H, T>(self, filter: MethodFilter, handler: H) -> Self
|
pub fn on<H, T>(self, filter: MethodFilter, handler: H) -> Self
|
||||||
@@ -632,7 +610,6 @@ impl MethodRouter<(), Infallible> {
|
|||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use axum::{
|
/// use axum::{
|
||||||
/// Server,
|
|
||||||
/// handler::Handler,
|
/// handler::Handler,
|
||||||
/// http::{Uri, Method},
|
/// http::{Uri, Method},
|
||||||
/// response::IntoResponse,
|
/// response::IntoResponse,
|
||||||
@@ -647,10 +624,8 @@ impl MethodRouter<(), Infallible> {
|
|||||||
/// let router = get(handler).post(handler);
|
/// let router = get(handler).post(handler);
|
||||||
///
|
///
|
||||||
/// # async {
|
/// # async {
|
||||||
/// Server::bind(&SocketAddr::from(([127, 0, 0, 1], 3000)))
|
/// let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
/// .serve(router.into_make_service())
|
/// axum::serve(listener, router.into_make_service()).await.unwrap();
|
||||||
/// .await?;
|
|
||||||
/// # Ok::<_, hyper::Error>(())
|
|
||||||
/// # };
|
/// # };
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
@@ -666,7 +641,6 @@ impl MethodRouter<(), Infallible> {
|
|||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use axum::{
|
/// use axum::{
|
||||||
/// Server,
|
|
||||||
/// handler::Handler,
|
/// handler::Handler,
|
||||||
/// response::IntoResponse,
|
/// response::IntoResponse,
|
||||||
/// extract::ConnectInfo,
|
/// extract::ConnectInfo,
|
||||||
@@ -681,10 +655,8 @@ impl MethodRouter<(), Infallible> {
|
|||||||
/// let router = get(handler).post(handler);
|
/// let router = get(handler).post(handler);
|
||||||
///
|
///
|
||||||
/// # async {
|
/// # async {
|
||||||
/// Server::bind(&SocketAddr::from(([127, 0, 0, 1], 3000)))
|
/// let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
/// .serve(router.into_make_service_with_connect_info::<SocketAddr>())
|
/// axum::serve(listener, router.into_make_service()).await.unwrap();
|
||||||
/// .await?;
|
|
||||||
/// # Ok::<_, hyper::Error>(())
|
|
||||||
/// # };
|
/// # };
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
@@ -758,9 +730,7 @@ where
|
|||||||
///
|
///
|
||||||
/// // Requests to `DELETE /` will go to `service`
|
/// // Requests to `DELETE /` will go to `service`
|
||||||
/// let app = Router::new().route("/", on_service(MethodFilter::DELETE, service));
|
/// let app = Router::new().route("/", on_service(MethodFilter::DELETE, service));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn on_service<T>(self, filter: MethodFilter, svc: T) -> Self
|
pub fn on_service<T>(self, filter: MethodFilter, svc: T) -> Self
|
||||||
@@ -1261,6 +1231,26 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for `axum::serve(listener, router)`
|
||||||
|
#[cfg(feature = "tokio")]
|
||||||
|
const _: () = {
|
||||||
|
use crate::serve::IncomingStream;
|
||||||
|
|
||||||
|
impl Service<IncomingStream<'_>> for MethodRouter<()> {
|
||||||
|
type Response = Self;
|
||||||
|
type Error = Infallible;
|
||||||
|
type Future = std::future::Ready<Result<Self::Response, Self::Error>>;
|
||||||
|
|
||||||
|
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||||
|
Poll::Ready(Ok(()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&mut self, _req: IncomingStream<'_>) -> Self::Future {
|
||||||
|
std::future::ready(Ok(self.clone()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -1361,7 +1351,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn buiding_complex_router() {
|
async fn buiding_complex_router() {
|
||||||
let app = crate::Router::new().route(
|
let app = crate::Router::new().route(
|
||||||
"/",
|
"/",
|
||||||
// use the all the things :bomb:
|
// use the all the things :bomb:
|
||||||
@@ -1380,7 +1370,8 @@ mod tests {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
crate::Server::bind(&"0.0.0.0:0".parse().unwrap()).serve(app.into_make_service());
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:0").await.unwrap();
|
||||||
|
crate::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[crate::test]
|
#[crate::test]
|
||||||
|
|||||||
+22
-4
@@ -413,10 +413,8 @@ impl Router {
|
|||||||
/// let app = Router::new().route("/", get(|| async { "Hi!" }));
|
/// let app = Router::new().route("/", get(|| async { "Hi!" }));
|
||||||
///
|
///
|
||||||
/// # async {
|
/// # async {
|
||||||
/// axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
|
/// let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
/// .serve(app.into_make_service())
|
/// axum::serve(listener, app).await.unwrap();
|
||||||
/// .await
|
|
||||||
/// .expect("server failed");
|
|
||||||
/// # };
|
/// # };
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
@@ -436,6 +434,26 @@ impl Router {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for `axum::serve(listener, router)`
|
||||||
|
#[cfg(feature = "tokio")]
|
||||||
|
const _: () = {
|
||||||
|
use crate::serve::IncomingStream;
|
||||||
|
|
||||||
|
impl Service<IncomingStream<'_>> for Router<()> {
|
||||||
|
type Response = Self;
|
||||||
|
type Error = Infallible;
|
||||||
|
type Future = std::future::Ready<Result<Self::Response, Self::Error>>;
|
||||||
|
|
||||||
|
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||||
|
Poll::Ready(Ok(()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&mut self, _req: IncomingStream<'_>) -> Self::Future {
|
||||||
|
std::future::ready(Ok(self.clone()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
impl<B> Service<Request<B>> for Router<()>
|
impl<B> Service<Request<B>> for Router<()>
|
||||||
where
|
where
|
||||||
B: HttpBody<Data = bytes::Bytes> + Send + 'static,
|
B: HttpBody<Data = bytes::Bytes> + Send + 'static,
|
||||||
|
|||||||
@@ -0,0 +1,234 @@
|
|||||||
|
//! Serve services.
|
||||||
|
|
||||||
|
use std::{convert::Infallible, io, net::SocketAddr};
|
||||||
|
|
||||||
|
use axum_core::{body::Body, extract::Request, response::Response};
|
||||||
|
use futures_util::{future::poll_fn, FutureExt};
|
||||||
|
use hyper1::server::conn::http1;
|
||||||
|
use tokio::net::{TcpListener, TcpStream};
|
||||||
|
use tower_hyper_http_body_compat::{HttpBody04ToHttpBody1, HttpBody1ToHttpBody04};
|
||||||
|
use tower_service::Service;
|
||||||
|
|
||||||
|
/// Serve the service with the supplied listener.
|
||||||
|
///
|
||||||
|
/// This method of running a service is intentionally simple and doesn't support any configuration.
|
||||||
|
/// Use hyper or hyper-util if you need configuration.
|
||||||
|
///
|
||||||
|
/// It only supports HTTP/1.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Serving a [`Router`]:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use axum::{Router, routing::get};
|
||||||
|
///
|
||||||
|
/// # async {
|
||||||
|
/// let router = Router::new().route("/", get(|| async { "Hello, World!" }));
|
||||||
|
///
|
||||||
|
/// let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
|
/// axum::serve(listener, router).await.unwrap();
|
||||||
|
/// # };
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// See also [`Router::into_make_service_with_connect_info`].
|
||||||
|
///
|
||||||
|
/// Serving a [`MethodRouter`]:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use axum::routing::get;
|
||||||
|
///
|
||||||
|
/// # async {
|
||||||
|
/// let router = get(|| async { "Hello, World!" });
|
||||||
|
///
|
||||||
|
/// let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
|
/// axum::serve(listener, router).await.unwrap();
|
||||||
|
/// # };
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// See also [`MethodRouter::into_make_service_with_connect_info`].
|
||||||
|
///
|
||||||
|
/// Serving a [`Handler`]:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use axum::handler::HandlerWithoutStateExt;
|
||||||
|
///
|
||||||
|
/// # async {
|
||||||
|
/// async fn handler() -> &'static str {
|
||||||
|
/// "Hello, World!"
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
|
/// axum::serve(listener, handler.into_make_service()).await.unwrap();
|
||||||
|
/// # };
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// See also [`HandlerWithoutStateExt::into_make_service_with_connect_info`] and
|
||||||
|
/// [`HandlerService::into_make_service_with_connect_info`].
|
||||||
|
///
|
||||||
|
/// [`Router`]: crate::Router
|
||||||
|
/// [`Router::into_make_service_with_connect_info`]: crate::Router::into_make_service_with_connect_info
|
||||||
|
/// [`MethodRouter`]: crate::routing::MethodRouter
|
||||||
|
/// [`MethodRouter::into_make_service_with_connect_info`]: crate::routing::MethodRouter::into_make_service_with_connect_info
|
||||||
|
/// [`Handler`]: crate::handler::Handler
|
||||||
|
/// [`HandlerWithoutStateExt::into_make_service_with_connect_info`]: crate::handler::HandlerWithoutStateExt::into_make_service_with_connect_info
|
||||||
|
/// [`HandlerService::into_make_service_with_connect_info`]: crate::handler::HandlerService::into_make_service_with_connect_info
|
||||||
|
#[cfg(feature = "tokio")]
|
||||||
|
pub async fn serve<M, S>(tcp_listener: TcpListener, mut make_service: M) -> io::Result<()>
|
||||||
|
where
|
||||||
|
M: for<'a> Service<IncomingStream<'a>, Error = Infallible, Response = S>,
|
||||||
|
S: Service<Request, Response = Response, Error = Infallible> + Clone + Send + 'static,
|
||||||
|
S::Future: Send,
|
||||||
|
{
|
||||||
|
loop {
|
||||||
|
let (tcp_stream, remote_addr) = tcp_listener.accept().await?;
|
||||||
|
|
||||||
|
poll_fn(|cx| make_service.poll_ready(cx))
|
||||||
|
.await
|
||||||
|
.unwrap_or_else(|err| match err {});
|
||||||
|
|
||||||
|
let mut service = make_service
|
||||||
|
.call(IncomingStream {
|
||||||
|
tcp_stream: &tcp_stream,
|
||||||
|
remote_addr,
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap_or_else(|err| match err {});
|
||||||
|
|
||||||
|
let service = hyper1::service::service_fn(move |req: Request<hyper1::body::Incoming>| {
|
||||||
|
let req = req.map(|body| {
|
||||||
|
// wont need this when axum uses http-body 1.0
|
||||||
|
let http_body_04 = HttpBody1ToHttpBody04::new(body);
|
||||||
|
Body::new(http_body_04)
|
||||||
|
});
|
||||||
|
|
||||||
|
// doing this saves cloning the service just to await the service being ready
|
||||||
|
//
|
||||||
|
// services like `Router` are always ready, so assume the service
|
||||||
|
// we're running here is also always ready...
|
||||||
|
match futures_util::future::poll_fn(|cx| service.poll_ready(cx)).now_or_never() {
|
||||||
|
Some(Ok(())) => {}
|
||||||
|
Some(Err(err)) => match err {},
|
||||||
|
None => {
|
||||||
|
// ...otherwise load shed
|
||||||
|
let mut res = Response::new(HttpBody04ToHttpBody1::new(Body::empty()));
|
||||||
|
*res.status_mut() = http::StatusCode::SERVICE_UNAVAILABLE;
|
||||||
|
return std::future::ready(Ok(res)).left_future();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let future = service.call(req);
|
||||||
|
|
||||||
|
async move {
|
||||||
|
let response = future
|
||||||
|
.await
|
||||||
|
.unwrap_or_else(|err| match err {})
|
||||||
|
// wont need this when axum uses http-body 1.0
|
||||||
|
.map(HttpBody04ToHttpBody1::new);
|
||||||
|
|
||||||
|
Ok::<_, Infallible>(response)
|
||||||
|
}
|
||||||
|
.right_future()
|
||||||
|
});
|
||||||
|
|
||||||
|
tokio::task::spawn(async move {
|
||||||
|
match http1::Builder::new()
|
||||||
|
.serve_connection(tcp_stream, service)
|
||||||
|
// for websockets
|
||||||
|
.with_upgrades()
|
||||||
|
.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.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An incoming stream.
|
||||||
|
///
|
||||||
|
/// Used with [`serve`] and [`IntoMakeServiceWithConnectInfo`].
|
||||||
|
///
|
||||||
|
/// [`IntoMakeServiceWithConnectInfo`]: crate::extract::connect_info::IntoMakeServiceWithConnectInfo
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct IncomingStream<'a> {
|
||||||
|
tcp_stream: &'a TcpStream,
|
||||||
|
remote_addr: SocketAddr,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IncomingStream<'_> {
|
||||||
|
/// Returns the local address that this stream is bound to.
|
||||||
|
pub fn local_addr(&self) -> std::io::Result<SocketAddr> {
|
||||||
|
self.tcp_stream.local_addr()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the remote address that this stream is bound to.
|
||||||
|
pub fn remote_addr(&self) -> SocketAddr {
|
||||||
|
self.remote_addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::{
|
||||||
|
handler::{Handler, HandlerWithoutStateExt},
|
||||||
|
routing::get,
|
||||||
|
Router,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[allow(dead_code, unused_must_use)]
|
||||||
|
async fn if_it_compiles_it_works() {
|
||||||
|
let router: Router = Router::new();
|
||||||
|
|
||||||
|
let addr = "0.0.0.0:0";
|
||||||
|
|
||||||
|
// router
|
||||||
|
serve(TcpListener::bind(addr).await.unwrap(), router.clone());
|
||||||
|
serve(
|
||||||
|
TcpListener::bind(addr).await.unwrap(),
|
||||||
|
router.clone().into_make_service(),
|
||||||
|
);
|
||||||
|
serve(
|
||||||
|
TcpListener::bind(addr).await.unwrap(),
|
||||||
|
router.into_make_service_with_connect_info::<SocketAddr>(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// method router
|
||||||
|
serve(TcpListener::bind(addr).await.unwrap(), get(handler));
|
||||||
|
serve(
|
||||||
|
TcpListener::bind(addr).await.unwrap(),
|
||||||
|
get(handler).into_make_service(),
|
||||||
|
);
|
||||||
|
serve(
|
||||||
|
TcpListener::bind(addr).await.unwrap(),
|
||||||
|
get(handler).into_make_service_with_connect_info::<SocketAddr>(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// handler
|
||||||
|
serve(
|
||||||
|
TcpListener::bind(addr).await.unwrap(),
|
||||||
|
handler.into_service(),
|
||||||
|
);
|
||||||
|
serve(
|
||||||
|
TcpListener::bind(addr).await.unwrap(),
|
||||||
|
handler.with_state(()),
|
||||||
|
);
|
||||||
|
serve(
|
||||||
|
TcpListener::bind(addr).await.unwrap(),
|
||||||
|
handler.into_make_service(),
|
||||||
|
);
|
||||||
|
serve(
|
||||||
|
TcpListener::bind(addr).await.unwrap(),
|
||||||
|
handler.into_make_service_with_connect_info::<SocketAddr>(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handler() {}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#![allow(clippy::disallowed_names)]
|
#![allow(clippy::disallowed_names)]
|
||||||
|
|
||||||
use crate::{body::HttpBody, BoxError};
|
use crate::{extract::Request, response::Response, serve};
|
||||||
|
|
||||||
mod test_client;
|
mod test_client;
|
||||||
pub(crate) use self::test_client::*;
|
pub(crate) use self::test_client::*;
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
use super::{BoxError, HttpBody};
|
use super::{serve, Request, Response};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use http::{
|
use http::{
|
||||||
header::{HeaderName, HeaderValue},
|
header::{HeaderName, HeaderValue},
|
||||||
Request, StatusCode,
|
StatusCode,
|
||||||
};
|
};
|
||||||
use hyper::Server;
|
use std::{convert::Infallible, net::SocketAddr};
|
||||||
use std::net::{SocketAddr, TcpListener};
|
use tokio::net::TcpListener;
|
||||||
use tower::make::Shared;
|
use tower::make::Shared;
|
||||||
use tower_service::Service;
|
use tower_service::Service;
|
||||||
|
|
||||||
@@ -15,25 +15,22 @@ pub(crate) struct TestClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TestClient {
|
impl TestClient {
|
||||||
pub(crate) fn new<S, ResBody>(svc: S) -> Self
|
pub(crate) fn new<S>(svc: S) -> Self
|
||||||
where
|
where
|
||||||
S: Service<Request<hyper::Body>, Response = http::Response<ResBody>>
|
S: Service<Request, Response = Response, Error = Infallible> + Clone + Send + 'static,
|
||||||
+ Clone
|
|
||||||
+ Send
|
|
||||||
+ 'static,
|
|
||||||
ResBody: HttpBody + Send + 'static,
|
|
||||||
ResBody::Data: Send,
|
|
||||||
ResBody::Error: Into<BoxError>,
|
|
||||||
S::Future: Send,
|
S::Future: Send,
|
||||||
S::Error: Into<BoxError>,
|
|
||||||
{
|
{
|
||||||
let listener = TcpListener::bind("127.0.0.1:0").expect("Could not bind ephemeral socket");
|
let std_listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
|
||||||
|
std_listener.set_nonblocking(true).unwrap();
|
||||||
|
let listener = TcpListener::from_std(std_listener).unwrap();
|
||||||
|
|
||||||
let addr = listener.local_addr().unwrap();
|
let addr = listener.local_addr().unwrap();
|
||||||
println!("Listening on {addr}");
|
println!("Listening on {addr}");
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let server = Server::from_tcp(listener).unwrap().serve(Shared::new(svc));
|
serve(listener, Shared::new(svc))
|
||||||
server.await.expect("server error");
|
.await
|
||||||
|
.expect("server error")
|
||||||
});
|
});
|
||||||
|
|
||||||
let client = reqwest::Client::builder()
|
let client = reqwest::Client::builder()
|
||||||
|
|||||||
@@ -27,9 +27,7 @@ use std::convert::Infallible;
|
|||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// let app = Router::new().route("/users/:user_id/team/:team_id", get(users_teams_show));
|
/// let app = Router::new().route("/users/:user_id/team/:team_id", get(users_teams_show));
|
||||||
/// # async {
|
/// # let _: Router = app;
|
||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
|
||||||
/// # };
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// # As response
|
/// # As response
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ skip-tree = [
|
|||||||
{ name = "spin" },
|
{ name = "spin" },
|
||||||
# lots still pulls in syn 1.x
|
# lots still pulls in syn 1.x
|
||||||
{ name = "syn" },
|
{ name = "syn" },
|
||||||
|
# until 1.0 is out we're pulling in both 0.14 and 1.0-rc.x
|
||||||
|
{ name = "hyper" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[sources]
|
[sources]
|
||||||
|
|||||||
@@ -10,18 +10,16 @@ use axum::{
|
|||||||
routing::get,
|
routing::get,
|
||||||
Router,
|
Router,
|
||||||
};
|
};
|
||||||
use std::net::SocketAddr;
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let app = Router::new().route("/", get(handler));
|
let app = Router::new().route("/", get(handler));
|
||||||
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
println!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
println!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handler() -> Result<(), AppError> {
|
async fn handler() -> Result<(), AppError> {
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ use axum::{
|
|||||||
use futures::{sink::SinkExt, stream::StreamExt};
|
use futures::{sink::SinkExt, stream::StreamExt};
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashSet,
|
collections::HashSet,
|
||||||
net::SocketAddr,
|
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
use tokio::sync::broadcast;
|
use tokio::sync::broadcast;
|
||||||
@@ -53,12 +52,11 @@ async fn main() {
|
|||||||
.route("/websocket", get(websocket_handler))
|
.route("/websocket", get(websocket_handler))
|
||||||
.with_state(app_state);
|
.with_state(app_state);
|
||||||
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
tracing::debug!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn websocket_handler(
|
async fn websocket_handler(
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ use axum::{
|
|||||||
routing::post,
|
routing::post,
|
||||||
Router,
|
Router,
|
||||||
};
|
};
|
||||||
use std::net::SocketAddr;
|
|
||||||
use tower::ServiceBuilder;
|
use tower::ServiceBuilder;
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
@@ -32,12 +31,11 @@ async fn main() {
|
|||||||
.route("/", post(handler))
|
.route("/", post(handler))
|
||||||
.layer(ServiceBuilder::new().layer(middleware::from_fn(print_request_body)));
|
.layer(ServiceBuilder::new().layer(middleware::from_fn(print_request_body)));
|
||||||
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
tracing::debug!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// middleware that shows how to consume the request body upfront
|
// middleware that shows how to consume the request body upfront
|
||||||
|
|||||||
@@ -40,10 +40,8 @@ async fn main() {
|
|||||||
|
|
||||||
async fn serve(app: Router, port: u16) {
|
async fn serve(app: Router, port: u16) {
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], port));
|
let addr = SocketAddr::from(([127, 0, 0, 1], port));
|
||||||
axum::Server::bind(&addr)
|
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
|
||||||
.serve(app.into_make_service())
|
axum::serve(listener, app).await.unwrap();
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn html() -> impl IntoResponse {
|
async fn html() -> impl IntoResponse {
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ mod derive_from_request;
|
|||||||
mod with_rejection;
|
mod with_rejection;
|
||||||
|
|
||||||
use axum::{routing::post, Router};
|
use axum::{routing::post, Router};
|
||||||
use std::net::SocketAddr;
|
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
@@ -29,10 +28,9 @@ async fn main() {
|
|||||||
.route("/derive-from-request", post(derive_from_request::handler));
|
.route("/derive-from-request", post(derive_from_request::handler));
|
||||||
|
|
||||||
// Run our application
|
// Run our application
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
tracing::debug!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ use axum::{
|
|||||||
Router,
|
Router,
|
||||||
};
|
};
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
use std::net::SocketAddr;
|
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
@@ -30,12 +29,11 @@ async fn main() {
|
|||||||
let app = Router::new().route("/users/:user_id/teams/:team_id", get(handler));
|
let app = Router::new().route("/users/:user_id/teams/:team_id", get(handler));
|
||||||
|
|
||||||
// run it
|
// run it
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
println!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handler(Path(params): Path<Params>) -> impl IntoResponse {
|
async fn handler(Path(params): Path<Params>) -> impl IntoResponse {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use axum::{
|
|||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::{net::SocketAddr, sync::Arc};
|
use std::sync::Arc;
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@@ -42,12 +42,11 @@ async fn main() {
|
|||||||
.with_state(user_repo);
|
.with_state(user_repo);
|
||||||
|
|
||||||
// Run our application
|
// Run our application
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
tracing::debug!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handler for `GET /users/:id`.
|
/// Handler for `GET /users/:id`.
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
use axum::{extract::Form, response::Html, routing::get, Router};
|
use axum::{extract::Form, response::Html, routing::get, Router};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::net::SocketAddr;
|
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
@@ -22,13 +21,12 @@ async fn main() {
|
|||||||
// build our application with some routes
|
// build our application with some routes
|
||||||
let app = Router::new().route("/", get(show_form).post(accept_form));
|
let app = Router::new().route("/", get(show_form).post(accept_form));
|
||||||
|
|
||||||
// run it with hyper
|
// run it
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
tracing::debug!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn show_form() -> Html<&'static str> {
|
async fn show_form() -> Html<&'static str> {
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ use axum::{
|
|||||||
routing::get,
|
routing::get,
|
||||||
Router,
|
Router,
|
||||||
};
|
};
|
||||||
use std::net::SocketAddr;
|
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
@@ -30,12 +29,11 @@ async fn main() {
|
|||||||
let app = app.fallback(handler_404);
|
let app = app.fallback(handler_404);
|
||||||
|
|
||||||
// run it
|
// run it
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
tracing::debug!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handler() -> Html<&'static str> {
|
async fn handler() -> Html<&'static str> {
|
||||||
|
|||||||
@@ -6,4 +6,5 @@ publish = false
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
axum = { path = "../../axum" }
|
axum = { path = "../../axum" }
|
||||||
|
hyper = { version = "0.14", features = ["full"] }
|
||||||
tokio = { version = "1.0", features = ["full"] }
|
tokio = { version = "1.0", features = ["full"] }
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ async fn main() {
|
|||||||
// run it
|
// run it
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
||||||
println!("listening on {}", addr);
|
println!("listening on {}", addr);
|
||||||
axum::Server::bind(&addr)
|
hyper::Server::bind(&addr)
|
||||||
.serve(app.into_make_service())
|
.serve(app.into_make_service())
|
||||||
.with_graceful_shutdown(shutdown_signal())
|
.with_graceful_shutdown(shutdown_signal())
|
||||||
.await
|
.await
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
use axum::response::{IntoResponse, Response};
|
use axum::response::{IntoResponse, Response};
|
||||||
use axum::{http, routing::get, Router};
|
use axum::{http, routing::get, Router};
|
||||||
use std::net::SocketAddr;
|
|
||||||
|
|
||||||
fn app() -> Router {
|
fn app() -> Router {
|
||||||
Router::new().route("/get-head", get(get_head_handler))
|
Router::new().route("/get-head", get(get_head_handler))
|
||||||
@@ -14,12 +13,11 @@ fn app() -> Router {
|
|||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app().into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
println!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app()).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET routes will also be called for HEAD requests but will have the response body removed.
|
// GET routes will also be called for HEAD requests but will have the response body removed.
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use axum::{response::Html, routing::get, Router};
|
use axum::{response::Html, routing::get, Router};
|
||||||
use std::net::SocketAddr;
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
@@ -13,12 +12,11 @@ async fn main() {
|
|||||||
let app = Router::new().route("/", get(handler));
|
let app = Router::new().route("/", get(handler));
|
||||||
|
|
||||||
// run it
|
// run it
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
println!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
println!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handler() -> Html<&'static str> {
|
async fn handler() -> Html<&'static str> {
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ async fn main() {
|
|||||||
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
||||||
tracing::debug!("listening on {}", addr);
|
tracing::debug!("listening on {}", addr);
|
||||||
axum::Server::bind(&addr)
|
hyper::Server::bind(&addr)
|
||||||
.http1_preserve_header_case(true)
|
.http1_preserve_header_case(true)
|
||||||
.http1_title_case_headers(true)
|
.http1_title_case_headers(true)
|
||||||
.serve(Shared::new(service))
|
.serve(Shared::new(service))
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation}
|
|||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::{fmt::Display, net::SocketAddr};
|
use std::fmt::Display;
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
// Quick instructions
|
// Quick instructions
|
||||||
@@ -67,13 +67,11 @@ async fn main() {
|
|||||||
.route("/protected", get(protected))
|
.route("/protected", get(protected))
|
||||||
.route("/authorize", post(authorize));
|
.route("/authorize", post(authorize));
|
||||||
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
tracing::debug!("listening on {}", addr);
|
|
||||||
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn protected(claims: Claims) -> Result<String, AuthError> {
|
async fn protected(claims: Claims) -> Result<String, AuthError> {
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ use axum::{
|
|||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
net::SocketAddr,
|
|
||||||
sync::{Arc, RwLock},
|
sync::{Arc, RwLock},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
@@ -74,12 +73,11 @@ async fn main() {
|
|||||||
.with_state(Arc::clone(&shared_state));
|
.with_state(Arc::clone(&shared_state));
|
||||||
|
|
||||||
// Run our app with hyper
|
// Run our app with hyper
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
tracing::debug!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
type SharedState = Arc<RwLock<AppState>>;
|
type SharedState = Arc<RwLock<AppState>>;
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ async fn main() {
|
|||||||
b: incoming_v6,
|
b: incoming_v6,
|
||||||
};
|
};
|
||||||
|
|
||||||
axum::Server::builder(combined)
|
hyper::Server::builder(combined)
|
||||||
.serve(app.into_make_service())
|
.serve(app.into_make_service())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ use axum::{
|
|||||||
routing::get,
|
routing::get,
|
||||||
Router,
|
Router,
|
||||||
};
|
};
|
||||||
use std::net::SocketAddr;
|
|
||||||
use tower_http::limit::RequestBodyLimitLayer;
|
use tower_http::limit::RequestBodyLimitLayer;
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
@@ -34,12 +33,11 @@ async fn main() {
|
|||||||
.layer(tower_http::trace::TraceLayer::new_for_http());
|
.layer(tower_http::trace::TraceLayer::new_for_http());
|
||||||
|
|
||||||
// run it with hyper
|
// run it with hyper
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
tracing::debug!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn show_form() -> Html<&'static str> {
|
async fn show_form() -> Html<&'static str> {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ use oauth2::{
|
|||||||
ClientSecret, CsrfToken, RedirectUrl, Scope, TokenResponse, TokenUrl,
|
ClientSecret, CsrfToken, RedirectUrl, Scope, TokenResponse, TokenUrl,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{env, net::SocketAddr};
|
use std::env;
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
static COOKIE_NAME: &str = "SESSION";
|
static COOKIE_NAME: &str = "SESSION";
|
||||||
@@ -56,13 +56,11 @@ async fn main() {
|
|||||||
.route("/logout", get(logout))
|
.route("/logout", get(logout))
|
||||||
.with_state(app_state);
|
.with_state(app_state);
|
||||||
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
tracing::debug!("listening on {}", addr);
|
|
||||||
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ use axum::{
|
|||||||
Form, Json, RequestExt, Router,
|
Form, Json, RequestExt, Router,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::net::SocketAddr;
|
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
@@ -31,12 +30,11 @@ async fn main() {
|
|||||||
|
|
||||||
let app = Router::new().route("/", post(handler));
|
let app = Router::new().route("/", post(handler));
|
||||||
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
tracing::debug!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ use axum::{
|
|||||||
routing::post,
|
routing::post,
|
||||||
Router,
|
Router,
|
||||||
};
|
};
|
||||||
use std::net::SocketAddr;
|
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
@@ -30,12 +29,11 @@ async fn main() {
|
|||||||
.route("/", post(|| async move { "Hello from `POST /`" }))
|
.route("/", post(|| async move { "Hello from `POST /`" }))
|
||||||
.layer(middleware::from_fn(print_request_response));
|
.layer(middleware::from_fn(print_request_response));
|
||||||
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
tracing::debug!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn print_request_response(
|
async fn print_request_response(
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ use axum::{
|
|||||||
use metrics_exporter_prometheus::{Matcher, PrometheusBuilder, PrometheusHandle};
|
use metrics_exporter_prometheus::{Matcher, PrometheusBuilder, PrometheusHandle};
|
||||||
use std::{
|
use std::{
|
||||||
future::ready,
|
future::ready,
|
||||||
net::SocketAddr,
|
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
@@ -42,24 +41,22 @@ fn main_app() -> Router {
|
|||||||
async fn start_main_server() {
|
async fn start_main_server() {
|
||||||
let app = main_app();
|
let app = main_app();
|
||||||
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
tracing::debug!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn start_metrics_server() {
|
async fn start_metrics_server() {
|
||||||
let app = metrics_app();
|
let app = metrics_app();
|
||||||
|
|
||||||
// NOTE: expose metrics enpoint on a different port
|
// NOTE: expose metrics enpoint on a different port
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3001));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3001")
|
||||||
tracing::debug!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
|||||||
@@ -10,10 +10,11 @@ use std::{fmt, str::FromStr};
|
|||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
.serve(app().into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
println!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app()).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Router {
|
fn app() -> Router {
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ use axum::{
|
|||||||
Json, Router,
|
Json, Router,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::net::SocketAddr;
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
@@ -26,13 +25,11 @@ async fn main() {
|
|||||||
.route("/users", post(create_user));
|
.route("/users", post(create_user));
|
||||||
|
|
||||||
// run our app with hyper
|
// run our app with hyper
|
||||||
// `axum::Server` is a re-export of `hyper::Server`
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
|
||||||
tracing::debug!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// basic handler that responds with a static string
|
// basic handler that responds with a static string
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ async fn main() {
|
|||||||
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
||||||
tracing::debug!("listening on {}", addr);
|
tracing::debug!("listening on {}", addr);
|
||||||
axum::Server::bind(&addr)
|
hyper::Server::bind(&addr)
|
||||||
.serve(tower::make::Shared::new(service))
|
.serve(tower::make::Shared::new(service))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ use axum::{
|
|||||||
Router,
|
Router,
|
||||||
};
|
};
|
||||||
use hyper::client::HttpConnector;
|
use hyper::client::HttpConnector;
|
||||||
use std::net::SocketAddr;
|
|
||||||
|
|
||||||
type Client = hyper::client::Client<HttpConnector, Body>;
|
type Client = hyper::client::Client<HttpConnector, Body>;
|
||||||
|
|
||||||
@@ -28,12 +27,11 @@ async fn main() {
|
|||||||
|
|
||||||
let app = Router::new().route("/", get(handler)).with_state(client);
|
let app = Router::new().route("/", get(handler)).with_state(client);
|
||||||
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 4000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:4000")
|
||||||
println!("reverse proxy listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
println!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handler(State(client): State<Client>, mut req: Request) -> Response {
|
async fn handler(State(client): State<Client>, mut req: Request) -> Response {
|
||||||
@@ -54,10 +52,9 @@ async fn handler(State(client): State<Client>, mut req: Request) -> Response {
|
|||||||
async fn server() {
|
async fn server() {
|
||||||
let app = Router::new().route("/", get(|| async { "Hello, world!" }));
|
let app = Router::new().route("/", get(|| async { "Hello, world!" }));
|
||||||
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
println!("server listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
println!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ use axum::{
|
|||||||
routing::{get, post, MethodRouter},
|
routing::{get, post, MethodRouter},
|
||||||
Router,
|
Router,
|
||||||
};
|
};
|
||||||
use std::net::SocketAddr;
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
@@ -17,12 +16,11 @@ async fn main() {
|
|||||||
.merge(get_foo())
|
.merge(get_foo())
|
||||||
.merge(post_foo());
|
.merge(post_foo());
|
||||||
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
println!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
println!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn root() -> Router {
|
fn root() -> Router {
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ use axum::{
|
|||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::net::SocketAddr;
|
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@@ -42,12 +41,11 @@ async fn main() {
|
|||||||
|
|
||||||
let app = Router::new().route("/", get(handler)).with_state(store);
|
let app = Router::new().route("/", get(handler)).with_state(store);
|
||||||
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
tracing::debug!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handler(user_id: UserIdFromSession) -> impl IntoResponse {
|
async fn handler(user_id: UserIdFromSession) -> impl IntoResponse {
|
||||||
|
|||||||
@@ -21,9 +21,10 @@ use axum::{
|
|||||||
Router,
|
Router,
|
||||||
};
|
};
|
||||||
use sqlx::postgres::{PgPool, PgPoolOptions};
|
use sqlx::postgres::{PgPool, PgPoolOptions};
|
||||||
|
use tokio::net::TcpListener;
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
use std::{net::SocketAddr, time::Duration};
|
use std::time::Duration;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
@@ -55,12 +56,9 @@ async fn main() {
|
|||||||
.with_state(pool);
|
.with_state(pool);
|
||||||
|
|
||||||
// run it with hyper
|
// run it with hyper
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = TcpListener::bind("127.0.0.1:3000").await.unwrap();
|
||||||
tracing::debug!("listening on {}", addr);
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
axum::Server::bind(&addr)
|
axum::serve(listener, app).await.unwrap();
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// we can extract the connection pool with `State`
|
// we can extract the connection pool with `State`
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use axum::{
|
|||||||
Router,
|
Router,
|
||||||
};
|
};
|
||||||
use futures::stream::{self, Stream};
|
use futures::stream::{self, Stream};
|
||||||
use std::{convert::Infallible, net::SocketAddr, path::PathBuf, time::Duration};
|
use std::{convert::Infallible, path::PathBuf, time::Duration};
|
||||||
use tokio_stream::StreamExt as _;
|
use tokio_stream::StreamExt as _;
|
||||||
use tower_http::{services::ServeDir, trace::TraceLayer};
|
use tower_http::{services::ServeDir, trace::TraceLayer};
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
@@ -37,12 +37,11 @@ async fn main() {
|
|||||||
.layer(TraceLayer::new_for_http());
|
.layer(TraceLayer::new_for_http());
|
||||||
|
|
||||||
// run it
|
// run it
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
tracing::debug!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn sse_handler(
|
async fn sse_handler(
|
||||||
|
|||||||
@@ -103,9 +103,9 @@ fn calling_serve_dir_from_a_handler() -> Router {
|
|||||||
|
|
||||||
async fn serve(app: Router, port: u16) {
|
async fn serve(app: Router, port: u16) {
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], port));
|
let addr = SocketAddr::from(([127, 0, 0, 1], port));
|
||||||
tracing::debug!("listening on {}", addr);
|
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
|
||||||
axum::Server::bind(&addr)
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
.serve(app.layer(TraceLayer::new_for_http()).into_make_service())
|
axum::serve(listener, app.layer(TraceLayer::new_for_http()))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use axum::{
|
|||||||
BoxError, Router,
|
BoxError, Router,
|
||||||
};
|
};
|
||||||
use futures::{Stream, TryStreamExt};
|
use futures::{Stream, TryStreamExt};
|
||||||
use std::{io, net::SocketAddr};
|
use std::io;
|
||||||
use tokio::{fs::File, io::BufWriter};
|
use tokio::{fs::File, io::BufWriter};
|
||||||
use tokio_util::io::StreamReader;
|
use tokio_util::io::StreamReader;
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
@@ -39,12 +39,11 @@ async fn main() {
|
|||||||
.route("/", get(show_form).post(accept_form))
|
.route("/", get(show_form).post(accept_form))
|
||||||
.route("/file/:file_name", post(save_request_body));
|
.route("/file/:file_name", post(save_request_body));
|
||||||
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
tracing::debug!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler that streams the request body to a file.
|
// Handler that streams the request body to a file.
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ use axum::{
|
|||||||
routing::get,
|
routing::get,
|
||||||
Router,
|
Router,
|
||||||
};
|
};
|
||||||
use std::net::SocketAddr;
|
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
@@ -29,12 +28,11 @@ async fn main() {
|
|||||||
let app = Router::new().route("/greet/:name", get(greet));
|
let app = Router::new().route("/greet/:name", get(greet));
|
||||||
|
|
||||||
// run it
|
// run it
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
tracing::debug!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn greet(extract::Path(name): extract::Path<String>) -> impl IntoResponse {
|
async fn greet(extract::Path(name): extract::Path<String>) -> impl IntoResponse {
|
||||||
|
|||||||
@@ -14,16 +14,14 @@ use axum::{
|
|||||||
Router,
|
Router,
|
||||||
};
|
};
|
||||||
use futures::{Sink, SinkExt, Stream, StreamExt};
|
use futures::{Sink, SinkExt, Stream, StreamExt};
|
||||||
use std::net::SocketAddr;
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
println!("listening on {addr}");
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app().into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
println!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app()).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Router {
|
fn app() -> Router {
|
||||||
@@ -94,17 +92,18 @@ where
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::net::Ipv4Addr;
|
use std::net::{Ipv4Addr, SocketAddr};
|
||||||
use tokio_tungstenite::tungstenite;
|
use tokio_tungstenite::tungstenite;
|
||||||
|
|
||||||
// We can integration test one handler by running the server in a background task and
|
// We can integration test one handler by running the server in a background task and
|
||||||
// connecting to it like any other client would.
|
// connecting to it like any other client would.
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn integration_test() {
|
async fn integration_test() {
|
||||||
let server = axum::Server::bind(&SocketAddr::from((Ipv4Addr::UNSPECIFIED, 0)))
|
let listener = tokio::net::TcpListener::bind(SocketAddr::from((Ipv4Addr::UNSPECIFIED, 0)))
|
||||||
.serve(app().into_make_service());
|
.await
|
||||||
let addr = server.local_addr();
|
.unwrap();
|
||||||
tokio::spawn(server);
|
let addr = listener.local_addr().unwrap();
|
||||||
|
tokio::spawn(axum::serve(listener, app()));
|
||||||
|
|
||||||
let (mut socket, _response) =
|
let (mut socket, _response) =
|
||||||
tokio_tungstenite::connect_async(format!("ws://{addr}/integration-testable"))
|
tokio_tungstenite::connect_async(format!("ws://{addr}/integration-testable"))
|
||||||
|
|||||||
@@ -24,14 +24,11 @@ async fn main() {
|
|||||||
.with(tracing_subscriber::fmt::layer())
|
.with(tracing_subscriber::fmt::layer())
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
let addr = std::net::SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
|
|
||||||
tracing::debug!("listening on {}", addr);
|
|
||||||
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app().into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app()).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Having a function that produces our app makes it easy to call it from tests
|
/// Having a function that produces our app makes it easy to call it from tests
|
||||||
@@ -63,7 +60,8 @@ mod tests {
|
|||||||
http::{self, Request, StatusCode},
|
http::{self, Request, StatusCode},
|
||||||
};
|
};
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
use std::net::{SocketAddr, TcpListener};
|
use std::net::SocketAddr;
|
||||||
|
use tokio::net::TcpListener;
|
||||||
use tower::Service; // for `call`
|
use tower::Service; // for `call`
|
||||||
use tower::ServiceExt; // for `oneshot` and `ready`
|
use tower::ServiceExt; // for `oneshot` and `ready`
|
||||||
|
|
||||||
@@ -131,15 +129,11 @@ mod tests {
|
|||||||
// You can also spawn a server and talk to it like any other HTTP server:
|
// You can also spawn a server and talk to it like any other HTTP server:
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn the_real_deal() {
|
async fn the_real_deal() {
|
||||||
let listener = TcpListener::bind("0.0.0.0:0".parse::<SocketAddr>().unwrap()).unwrap();
|
let listener = TcpListener::bind("0.0.0.0:0").await.unwrap();
|
||||||
let addr = listener.local_addr().unwrap();
|
let addr = listener.local_addr().unwrap();
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
axum::Server::from_tcp(listener)
|
axum::serve(listener, app()).await.unwrap();
|
||||||
.unwrap()
|
|
||||||
.serve(app().into_make_service())
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let client = hyper::Client::new();
|
let client = hyper::Client::new();
|
||||||
|
|||||||
@@ -93,10 +93,9 @@ async fn redirect_http_to_https(ports: Ports) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], ports.http));
|
let addr = SocketAddr::from(([127, 0, 0, 1], ports.http));
|
||||||
tracing::debug!("http redirect listening on {}", addr);
|
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
axum::Server::bind(&addr)
|
axum::serve(listener, redirect.into_make_service())
|
||||||
.serve(redirect.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ use axum::{
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
net::SocketAddr,
|
|
||||||
sync::{Arc, RwLock},
|
sync::{Arc, RwLock},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
@@ -68,12 +67,11 @@ async fn main() {
|
|||||||
)
|
)
|
||||||
.with_state(db);
|
.with_state(db);
|
||||||
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
tracing::debug!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The query parameters for todos index
|
// The query parameters for todos index
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ use axum::{
|
|||||||
};
|
};
|
||||||
use bb8::{Pool, PooledConnection};
|
use bb8::{Pool, PooledConnection};
|
||||||
use bb8_postgres::PostgresConnectionManager;
|
use bb8_postgres::PostgresConnectionManager;
|
||||||
use std::net::SocketAddr;
|
|
||||||
use tokio_postgres::NoTls;
|
use tokio_postgres::NoTls;
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
@@ -41,13 +40,12 @@ async fn main() {
|
|||||||
)
|
)
|
||||||
.with_state(pool);
|
.with_state(pool);
|
||||||
|
|
||||||
// run it with hyper
|
// run it
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
tracing::debug!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
type ConnectionPool = Pool<PostgresConnectionManager<NoTls>>;
|
type ConnectionPool = Pool<PostgresConnectionManager<NoTls>>;
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ use axum::{
|
|||||||
routing::get,
|
routing::get,
|
||||||
Router,
|
Router,
|
||||||
};
|
};
|
||||||
use std::{net::SocketAddr, time::Duration};
|
use std::time::Duration;
|
||||||
|
use tokio::net::TcpListener;
|
||||||
use tower_http::{classify::ServerErrorsFailureClass, trace::TraceLayer};
|
use tower_http::{classify::ServerErrorsFailureClass, trace::TraceLayer};
|
||||||
use tracing::{info_span, Span};
|
use tracing::{info_span, Span};
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
@@ -80,12 +81,9 @@ async fn main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// run it
|
// run it
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = TcpListener::bind("127.0.0.1:3000").await.unwrap();
|
||||||
tracing::debug!("listening on {}", addr);
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
axum::Server::bind(&addr)
|
axum::serve(listener, app).await.unwrap();
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handler() -> Html<&'static str> {
|
async fn handler() -> Html<&'static str> {
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ mod unix {
|
|||||||
tokio::spawn(async {
|
tokio::spawn(async {
|
||||||
let app = Router::new().route("/", get(handler));
|
let app = Router::new().route("/", get(handler));
|
||||||
|
|
||||||
axum::Server::builder(ServerAccept { uds })
|
hyper::Server::builder(ServerAccept { uds })
|
||||||
.serve(app.into_make_service_with_connect_info::<UdsConnectInfo>())
|
.serve(app.into_make_service_with_connect_info::<UdsConnectInfo>())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ use axum::{
|
|||||||
Router,
|
Router,
|
||||||
};
|
};
|
||||||
use serde::{de::DeserializeOwned, Deserialize};
|
use serde::{de::DeserializeOwned, Deserialize};
|
||||||
use std::net::SocketAddr;
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
use tokio::net::TcpListener;
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
|
|
||||||
@@ -38,13 +38,9 @@ async fn main() {
|
|||||||
let app = Router::new().route("/", get(handler));
|
let app = Router::new().route("/", get(handler));
|
||||||
|
|
||||||
// run it
|
// run it
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = TcpListener::bind("127.0.0.1:3000").await.unwrap();
|
||||||
tracing::debug!("listening on {}", addr);
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Validate)]
|
#[derive(Debug, Deserialize, Validate)]
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use axum::{
|
|||||||
routing::get,
|
routing::get,
|
||||||
RequestPartsExt, Router,
|
RequestPartsExt, Router,
|
||||||
};
|
};
|
||||||
use std::{collections::HashMap, net::SocketAddr};
|
use std::collections::HashMap;
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
@@ -29,12 +29,11 @@ async fn main() {
|
|||||||
let app = Router::new().route("/:version/foo", get(handler));
|
let app = Router::new().route("/:version/foo", get(handler));
|
||||||
|
|
||||||
// run it
|
// run it
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
tracing::debug!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handler(version: Version) {
|
async fn handler(version: Version) {
|
||||||
|
|||||||
@@ -66,12 +66,16 @@ async fn main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// run it with hyper
|
// run it with hyper
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
tracing::debug!("listening on {}", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(app.into_make_service_with_connect_info::<SocketAddr>())
|
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
tracing::debug!("listening on {}", listener.local_addr().unwrap());
|
||||||
|
axum::serve(
|
||||||
|
listener,
|
||||||
|
app.into_make_service_with_connect_info::<SocketAddr>(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The handler for the HTTP request (this gets called when the HTTP GET lands at the start
|
/// The handler for the HTTP request (this gets called when the HTTP GET lands at the start
|
||||||
|
|||||||
Reference in New Issue
Block a user