Remove B type param (#1751)

Co-authored-by: Jonas Platte <[email protected]>
Co-authored-by: Michael Scofield <[email protected]>
This commit is contained in:
David Pedersen
2023-04-21 17:45:31 +02:00
co-authored by Jonas Platte Michael Scofield
parent 9be0ea934c
commit 4e4c29175f
100 changed files with 966 additions and 1160 deletions
@@ -6,7 +6,7 @@
use axum::{
async_trait,
body::{self, BoxBody, Bytes, Full},
body::{Body, Bytes},
extract::FromRequest,
http::{Request, StatusCode},
middleware::{self, Next},
@@ -16,7 +16,6 @@ use axum::{
};
use std::net::SocketAddr;
use tower::ServiceBuilder;
use tower_http::ServiceBuilderExt;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
#[tokio::main]
@@ -29,11 +28,9 @@ async fn main() {
.with(tracing_subscriber::fmt::layer())
.init();
let app = Router::new().route("/", post(handler)).layer(
ServiceBuilder::new()
.map_request_body(body::boxed)
.layer(middleware::from_fn(print_request_body)),
);
let app = Router::new()
.route("/", post(handler))
.layer(ServiceBuilder::new().layer(middleware::from_fn(print_request_body)));
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
tracing::debug!("listening on {}", addr);
@@ -45,8 +42,8 @@ async fn main() {
// middleware that shows how to consume the request body upfront
async fn print_request_body(
request: Request<BoxBody>,
next: Next<BoxBody>,
request: Request<Body>,
next: Next<Body>,
) -> Result<impl IntoResponse, Response> {
let request = buffer_request_body(request).await?;
@@ -55,7 +52,7 @@ async fn print_request_body(
// the trick is to take the request apart, buffer the body, do what you need to do, then put
// the request back together
async fn buffer_request_body(request: Request<BoxBody>) -> Result<Request<BoxBody>, Response> {
async fn buffer_request_body(request: Request<Body>) -> Result<Request<Body>, Response> {
let (parts, body) = request.into_parts();
// this wont work if the body is an long running stream
@@ -65,7 +62,7 @@ async fn buffer_request_body(request: Request<BoxBody>) -> Result<Request<BoxBod
do_thing_with_request_body(bytes.clone());
Ok(Request::from_parts(parts, body::boxed(Full::from(bytes))))
Ok(Request::from_parts(parts, Body::from(bytes)))
}
fn do_thing_with_request_body(bytes: Bytes) {
@@ -81,13 +78,13 @@ struct BufferRequestBody(Bytes);
// we must implement `FromRequest` (and not `FromRequestParts`) to consume the body
#[async_trait]
impl<S> FromRequest<S, BoxBody> for BufferRequestBody
impl<S> FromRequest<S> for BufferRequestBody
where
S: Send + Sync,
{
type Rejection = Response;
async fn from_request(req: Request<BoxBody>, state: &S) -> Result<Self, Self::Rejection> {
async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> {
let body = Bytes::from_request(req, state)
.await
.map_err(|err| err.into_response())?;
@@ -6,6 +6,7 @@
//! - Complexity: Manually implementing `FromRequest` results on more complex code
use axum::{
async_trait,
body::Body,
extract::{rejection::JsonRejection, FromRequest, MatchedPath},
http::Request,
http::StatusCode,
@@ -22,15 +23,14 @@ pub async fn handler(Json(value): Json<Value>) -> impl IntoResponse {
pub struct Json<T>(pub T);
#[async_trait]
impl<S, B, T> FromRequest<S, B> for Json<T>
impl<S, T> FromRequest<S> for Json<T>
where
axum::Json<T>: FromRequest<S, B, Rejection = JsonRejection>,
axum::Json<T>: FromRequest<S, Rejection = JsonRejection>,
S: Send + Sync,
B: Send + 'static,
{
type Rejection = (StatusCode, axum::Json<Value>);
async fn from_request(req: Request<B>, state: &S) -> Result<Self, Self::Rejection> {
async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> {
let (mut parts, body) = req.into_parts();
// We can use other extractors to provide better rejection messages.
+2 -1
View File
@@ -37,8 +37,9 @@ async fn main() {
let router_svc = Router::new().route("/", get(|| async { "Hello, World!" }));
let service = tower::service_fn(move |req: Request<Body>| {
let service = tower::service_fn(move |req: Request<_>| {
let router_svc = router_svc.clone();
let req = req.map(Body::new);
async move {
if req.method() == Method::CONNECT {
proxy(req).await
+3 -6
View File
@@ -8,13 +8,11 @@ use axum::{routing::get, Router};
use std::net::SocketAddr;
use tokio::net::TcpListener;
use tower_http::trace::TraceLayer;
use tower_hyper_http_body_compat::{
HttpBody1ToHttpBody04, TowerService03HttpServiceAsHyper1HttpService,
};
use tower_hyper_http_body_compat::TowerService03HttpServiceAsHyper1HttpService;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
// this is hyper 1.0
use hyper::{body::Incoming, server::conn::http1};
use hyper::server::conn::http1;
#[tokio::main]
async fn main() {
@@ -26,8 +24,7 @@ async fn main() {
.with(tracing_subscriber::fmt::layer())
.init();
// you have to use `HttpBody1ToHttpBody04<Incoming>` as the second type parameter to `Router`
let app: Router<_, HttpBody1ToHttpBody04<Incoming>> = Router::new()
let app = Router::new()
.route("/", get(|| async { "Hello, World!" }))
// we can still add regular tower middleware
.layer(TraceLayer::new_for_http());
+2 -2
View File
@@ -1,7 +1,7 @@
use openssl::ssl::{Ssl, SslAcceptor, SslFiletype, SslMethod};
use tokio_openssl::SslStream;
use axum::{extract::ConnectInfo, routing::get, Router};
use axum::{body::Body, extract::ConnectInfo, http::Request, routing::get, Router};
use futures_util::future::poll_fn;
use hyper::server::{
accept::Accept,
@@ -68,7 +68,7 @@ async fn main() {
let protocol = protocol.clone();
let svc = app.make_service(&stream);
let svc = MakeService::<_, Request<Body>>::make_service(&mut app, &stream);
tokio::spawn(async move {
let ssl = Ssl::new(acceptor.context()).unwrap();
+4 -4
View File
@@ -4,7 +4,7 @@
//! cargo run -p example-low-level-rustls
//! ```
use axum::{extract::ConnectInfo, routing::get, Router};
use axum::{body::Body, extract::ConnectInfo, http::Request, routing::get, Router};
use futures_util::future::poll_fn;
use hyper::server::{
accept::Accept,
@@ -24,7 +24,7 @@ use tokio_rustls::{
rustls::{Certificate, PrivateKey, ServerConfig},
TlsAcceptor,
};
use tower::MakeService;
use tower::make::MakeService;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
#[tokio::main]
@@ -53,7 +53,7 @@ async fn main() {
let protocol = Arc::new(Http::new());
let mut app = Router::new()
let mut app = Router::<()>::new()
.route("/", get(handler))
.into_make_service_with_connect_info::<SocketAddr>();
@@ -67,7 +67,7 @@ async fn main() {
let protocol = protocol.clone();
let svc = app.make_service(&stream);
let svc = MakeService::<_, Request<Body>>::make_service(&mut app, &stream);
tokio::spawn(async move {
if let Ok(stream) = acceptor.accept(stream).await {
@@ -8,6 +8,7 @@
use axum::{
async_trait,
body::Body,
extract::FromRequest,
http::{header::CONTENT_TYPE, Request, StatusCode},
response::{IntoResponse, Response},
@@ -51,17 +52,16 @@ async fn handler(JsonOrForm(payload): JsonOrForm<Payload>) {
struct JsonOrForm<T>(T);
#[async_trait]
impl<S, B, T> FromRequest<S, B> for JsonOrForm<T>
impl<S, T> FromRequest<S> for JsonOrForm<T>
where
B: Send + 'static,
S: Send + Sync,
Json<T>: FromRequest<(), B>,
Form<T>: FromRequest<(), B>,
Json<T>: FromRequest<()>,
Form<T>: FromRequest<()>,
T: 'static,
{
type Rejection = Response;
async fn from_request(req: Request<B>, _state: &S) -> Result<Self, Self::Rejection> {
async fn from_request(req: Request<Body>, _state: &S) -> Result<Self, Self::Rejection> {
let content_type_header = req.headers().get(CONTENT_TYPE);
let content_type = content_type_header.and_then(|value| value.to_str().ok());
+7 -5
View File
@@ -8,12 +8,14 @@
//! ```
use axum::{
body::Body,
extract::State,
http::{uri::Uri, Request, Response},
http::{uri::Uri, Request},
response::{IntoResponse, Response},
routing::get,
Router,
};
use hyper::{client::HttpConnector, Body};
use hyper::client::HttpConnector;
use std::net::SocketAddr;
type Client = hyper::client::Client<HttpConnector, Body>;
@@ -22,7 +24,7 @@ type Client = hyper::client::Client<HttpConnector, Body>;
async fn main() {
tokio::spawn(server());
let client = Client::new();
let client: Client = hyper::Client::builder().build(HttpConnector::new());
let app = Router::new().route("/", get(handler)).with_state(client);
@@ -34,7 +36,7 @@ async fn main() {
.unwrap();
}
async fn handler(State(client): State<Client>, mut req: Request<Body>) -> Response<Body> {
async fn handler(State(client): State<Client>, mut req: Request<Body>) -> Response {
let path = req.uri().path();
let path_query = req
.uri()
@@ -46,7 +48,7 @@ async fn handler(State(client): State<Client>, mut req: Request<Body>) -> Respon
*req.uri_mut() = Uri::try_from(uri).unwrap();
client.request(req).await.unwrap()
client.request(req).await.unwrap().into_response()
}
async fn server() {
+4 -1
View File
@@ -71,7 +71,10 @@ fn using_serve_dir_with_handler_as_service() -> Router {
(StatusCode::NOT_FOUND, "Not found")
}
let serve_dir = ServeDir::new("assets").not_found_service(handle_404.into_service());
// you can convert handler function to service
let service = handle_404.into_service();
let serve_dir = ServeDir::new("assets").not_found_service(service);
Router::new()
.route("/foo", get(|| async { "Hi from /foo" }))
+5 -5
View File
@@ -5,9 +5,9 @@
//! ```
use axum::{
body::Bytes,
extract::{BodyStream, Multipart, Path},
http::StatusCode,
body::{Body, Bytes},
extract::{Multipart, Path},
http::{Request, StatusCode},
response::{Html, Redirect},
routing::{get, post},
BoxError, Router,
@@ -52,9 +52,9 @@ async fn main() {
// POST'ing to `/file/foo.txt` will create a file called `foo.txt`.
async fn save_request_body(
Path(file_name): Path<String>,
body: BodyStream,
request: Request<Body>,
) -> Result<(), (StatusCode, String)> {
stream_to_file(&file_name, body).await
stream_to_file(&file_name, request.into_body()).await
}
// Handler that returns HTML for a multipart form.
+21 -4
View File
@@ -148,7 +148,7 @@ mod tests {
.request(
Request::builder()
.uri(format!("http://{}", addr))
.body(Body::empty())
.body(hyper::Body::empty())
.unwrap(),
)
.await
@@ -165,11 +165,21 @@ mod tests {
let mut app = app();
let request = Request::builder().uri("/").body(Body::empty()).unwrap();
let response = app.ready().await.unwrap().call(request).await.unwrap();
let response = ServiceExt::<Request<Body>>::ready(&mut app)
.await
.unwrap()
.call(request)
.await
.unwrap();
assert_eq!(response.status(), StatusCode::OK);
let request = Request::builder().uri("/").body(Body::empty()).unwrap();
let response = app.ready().await.unwrap().call(request).await.unwrap();
let response = ServiceExt::<Request<Body>>::ready(&mut app)
.await
.unwrap()
.call(request)
.await
.unwrap();
assert_eq!(response.status(), StatusCode::OK);
}
@@ -186,7 +196,14 @@ mod tests {
.uri("/requires-connect-into")
.body(Body::empty())
.unwrap();
let response = app.ready().await.unwrap().call(request).await.unwrap();
let response = app
.as_service()
.ready()
.await
.unwrap()
.call(request)
.await
.unwrap();
assert_eq!(response.status(), StatusCode::OK);
}
}
+4 -4
View File
@@ -12,6 +12,7 @@
use async_trait::async_trait;
use axum::{
body::Body,
extract::{rejection::FormRejection, Form, FromRequest},
http::{Request, StatusCode},
response::{Html, IntoResponse, Response},
@@ -61,16 +62,15 @@ async fn handler(ValidatedForm(input): ValidatedForm<NameInput>) -> Html<String>
pub struct ValidatedForm<T>(pub T);
#[async_trait]
impl<T, S, B> FromRequest<S, B> for ValidatedForm<T>
impl<T, S> FromRequest<S> for ValidatedForm<T>
where
T: DeserializeOwned + Validate,
S: Send + Sync,
Form<T>: FromRequest<S, B, Rejection = FormRejection>,
B: Send + 'static,
Form<T>: FromRequest<S, Rejection = FormRejection>,
{
type Rejection = ServerError;
async fn from_request(req: Request<B>, state: &S) -> Result<Self, Self::Rejection> {
async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> {
let Form(value) = Form::<T>::from_request(req, state).await?;
value.validate()?;
Ok(ValidatedForm(value))