- Overall:
- Routing:
- added: Add dedicated
Router
to replace theRoutingDsl
trait (#214)
- added: Add
Router::or
for combining routes (#108)
- fixed: Support matching different HTTP methods for the same route that aren't defined
together. SoRouter::new().route("/", get(...)).route("/", post(...))
now
accepts bothGET
andPOST
. Previously onlyPOST
would be accepted (#224)
- fixed:
get
routes will now also be called forHEAD
requests but will always have
the response body removed (#129)
- changed: Replace
axum::route(...)
withaxum::Router::new().route(...)
. This means
there is now only one way to create a new router. Same goes for
axum::routing::nest
. (#215)
- changed: Implement
routing::MethodFilter
viabitflags
(#158)
- changed: Move
handle_error
fromServiceExt
toservice::OnMethod
(#160)
- added: Add dedicated
With these changes this app using 0.1:
use axum::{extract::Extension, prelude::*, routing::BoxRoute, AddExtensionLayer};
let app = route("/", get(|| async { "hi" }))
.nest("/api", api_routes())
.layer(AddExtensionLayer::new(state));
fn api_routes() -> BoxRoute<Body> {
route(
"/users",
post(|Extension(state): Extension<State>| async { "hi from nested" }),
)
.boxed()
}
Becomes this in 0.2:
use axum::{
extract::Extension,
handler::{get, post},
routing::BoxRoute,
Router,
};
let app = Router::new()
.route("/", get(|| async { "hi" }))
.nest("/api", api_routes());
fn api_routes() -> Router<BoxRoute> {
Router::new()
.route(
"/users",
post(|Extension(state): Extension<State>| async { "hi from nested" }),
)
.boxed()
}
- Extractors:
- added: Make
FromRequest
default to being generic overbody::Body
(#146)
- added: Implement
std::error::Error
for all rejections (#153)
- added: Add
OriginalUri
for extracting original request URI in nested services (#197)
- added: Implement
FromRequest
forhttp::Extensions
(#169)
- added: Make
RequestParts::{new, try_into_request}
public so extractors can be used outside axum (#194)
- added: Implement
FromRequest
foraxum::body::Body
(#241)
- changed: Removed
extract::UrlParams
andextract::UrlParamsMap
. Useextract::Path
instead (#154)
- changed:
extractor_middleware
now requiresRequestBody: Default
(#167)
- changed: Convert
RequestAlreadyExtracted
to an enum with each possible error variant (#167)
- changed:
extract::BodyStream
is no longer generic over the request body (#234)
- changed:
extract::Body
has been renamed toextract::RawBody
to avoid conflicting withbody::Body
(#233)
- changed:
RequestParts
changes (#153)
method
new returns an&http::Method
method_mut
new returns an&mut http::Method
take_method
has been removed
uri
new returns an&http::Uri
uri_mut
new returns an&mut http::Uri
take_uri
has been removed
- changed: Remove several rejection types that were no longer used (#153) (#154)
- added: Make
- Responses:
- added: Add
Headers
for easily customizing headers on a response (#193)
- added: Add
Redirect
response (#192)
- added: Add
body::StreamBody
for easily responding with a stream of byte chunks (#237)
- changed: Add associated
Body
andBodyError
types toIntoResponse
. This is
required for returning responses with bodies other thanhyper::Body
from
handlers. See the docs for advice on how to implementIntoResponse
(#86)
- changed:
tower::util::Either
no longer implementsIntoResponse
(#229)
- added: Add
This IntoResponse
from 0.1:
use axum::{http::Response, prelude::*, response::IntoResponse};
struct MyResponse;
impl IntoResponse for MyResponse {
fn into_response(self) -> Response<Body> {
Response::new(Body::empty())
}
}
Becomes this in 0.2:
use axum::{body::Body, http::Response, response::IntoResponse};
struct MyResponse;
impl IntoResponse for MyResponse {
type Body = Body;
type BodyError = <Self::Body as axum::body::HttpBody>::Error;
fn into_response(self) -> Response<Self::Body> {
Response::new(Body::empty())
}
}
- SSE:
Handler using SSE in 0.1:
use axum::{
prelude::*,
sse::{sse, Event},
};
use std::convert::Infallible;
let app = route(
"/",
sse(|| async {
let stream = futures::stream::iter(vec![Ok::<_, Infallible>(
Event::default().data("hi there!"),
)]);
Ok::<_, Infallible>(stream)
}),
);
Becomes this in 0.2:
use axum::{
handler::get,
response::sse::{Event, Sse},
Router,
};
use std::convert::Infallible;
let app = Router::new().route(
"/",
get(|| async {
let stream = futures::stream::iter(vec![Ok::<_, Infallible>(
Event::default().data("hi there!"),
)]);
Sse::new(stream)
}),
);
- WebSockets:
Handler using WebSockets in 0.1:
use axum::{
prelude::*,
ws::{ws, WebSocket},
};
let app = route(
"/",
ws(|socket: WebSocket| async move {
// do stuff with socket
}),
);
Becomes this in 0.2:
use axum::{
extract::ws::{WebSocket, WebSocketUpgrade},
handler::get,
Router,
};
let app = Router::new().route(
"/",
get(|ws: WebSocketUpgrade| async move {
ws.on_upgrade(|socket: WebSocket| async move {
// do stuff with socket
})
}),
);
- Misc
- added: Add default feature
tower-log
which exposestower
'slog
feature. (#218)
- changed: Replace
body::BoxStdError
withaxum::Error
, which supports downcasting (#150)
- changed:
EmptyRouter
now requires the response body to implementSend + Sync + 'static'
(#108)
- changed:
Router::check_infallible
now returns aCheckInfallible
service. This
is to improve compile times (#198)
- changed:
Router::into_make_service
now returnsrouting::IntoMakeService
rather than
tower::make::Shared
(#229)
- changed: All usage of
tower::BoxError
has been replaced withaxum::BoxError
(#229)
- changed: Several response future types have been moved into dedicated
future
modules (#133)
- changed:
EmptyRouter
,ExtractorMiddleware
,ExtractorMiddlewareLayer
,
andQueryStringMissing
no longer implementCopy
(#132)
- changed:
service::OnMethod
,handler::OnMethod
, androuting::Nested
have new response future types (#157)
- added: Add default feature