Its a convenient way to extract everything from a request except the body. Also makes sense for axum to provide this since other crates can't.
22 KiB
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Unreleased
- Implement
FromRequest
forhttp::request::Parts
so it can be used an extractor (#489) - Implement
IntoResponse
forhttp::response::Parts
(#490)
0.3.2 (08. November, 2021)
- added: Add
Router::route_layer
for applying middleware that will only run on requests that match a route. This is useful for middleware that return early, such as authorization (#474)
0.3.1 (06. November, 2021)
- fixed: Implement
Clone
forIntoMakeServiceWithConnectInfo
(#471)
0.3.0 (02. November, 2021)
- Overall:
-
fixed: All known compile time issues are resolved, including those with
boxed
and those introduced by Rust 1.56 (#404) -
breaking: The router's type is now always
Router
regardless of how many routes or middleware are applied (#404)This means router types are all always nameable:
fn my_routes() -> Router { Router::new().route( "/users", post(|| async { "Hello, World!" }), ) }
-
breaking: Added feature flags for HTTP1 and JSON. This enables removing a few dependencies if your app only uses HTTP2 or doesn't use JSON. This is only a breaking change if you depend on axum with
default_features = false
. (#286) -
breaking:
Route::boxed
andBoxRoute
have been removed as they're no longer necessary (#404) -
breaking:
Nested
,Or
types are now private. They no longer had to be public becauseRouter
is internally boxed (#404) -
breaking: Remove
routing::Layered
as it didn't actually do anything and thus wasn't necessary -
breaking: Vendor
AddExtensionLayer
andAddExtension
to reduce public dependencies -
breaking:
body::BoxBody
is now a type alias forhttp_body::combinators::UnsyncBoxBody
and thus is no longerSync
. This is because bodies are streams and requiring streams to beSync
is unnecessary. -
added: Implement
IntoResponse
forhttp_body::combinators::UnsyncBoxBody
. -
added: Add
Handler::into_make_service
for serving a handler without aRouter
. -
added: Add
Handler::into_make_service_with_connect_info
for serving a handler without aRouter
, and storing info about the incoming connection. -
breaking: axum's minimum supported rust version is now 1.54
-
- Routing:
- Big internal refactoring of routing leading to several improvements (#363)
- added: Wildcard routes like
.route("/api/users/*rest", service)
are now supported. - fixed: The order routes are added in no longer matters.
- fixed: Adding a conflicting route will now cause a panic instead of silently making a route unreachable.
- fixed: Route matching is faster as number of routes increases.
- breaking: Handlers for multiple HTTP methods must be added in the same
Router::route
call. So.route("/", get(get_handler).post(post_handler))
and not.route("/", get(get_handler)).route("/", post(post_handler))
.
- added: Wildcard routes like
- fixed: Correctly handle trailing slashes in routes:
- If a route with a trailing slash exists and a request without a trailing slash is received, axum will send a 301 redirection to the route with the trailing slash.
- Or vice versa if a route without a trailing slash exists and a request with a trailing slash is received.
- This can be overridden by explicitly defining two routes: One with and one without a trailing slash.
- breaking: Method routing for handlers has been moved from
axum::handler
toaxum::routing
. Soaxum::handler::get
now lives ataxum::routing::get
(#405) - breaking: Method routing for services has been moved from
axum::service
toaxum::routing::service_method_routing
. Soaxum::service::get
now lives ataxum::routing::service_method_routing::get
, etc. (#405) - breaking:
Router::or
renamed toRouter::merge
and will now panic on overlapping routes. It now only acceptsRouter
s and not generalService
s. UseRouter::fallback
for adding fallback routes (#408) - added:
Router::fallback
for adding handlers for request that didn't match any routes.Router::fallback
must be use instead ofnest("/", _)
(#408) - breaking:
EmptyRouter
has been renamed toMethodNotAllowed
as it's only used in method routers and not in path routers (Router
) - breaking: Remove support for routing based on the
CONNECT
method. An example of combining axum with and HTTP proxy can be found here (#428)
- Big internal refactoring of routing leading to several improvements (#363)
- Extractors:
- fixed: Expand accepted content types for JSON requests (#378)
- fixed: Support deserializing
i128
andu128
inextract::Path
- breaking: Automatically do percent decoding in
extract::Path
(#272) - breaking: Change
Connected::connect_info
to returnSelf
and remove the associated typeConnectInfo
(#396) - added: Add
extract::MatchedPath
for accessing path in router that matched the request (#412)
- Error handling:
-
breaking: Simplify error handling model (#402):
- All services part of the router are now required to be infallible.
- Error handling utilities have been moved to an
error_handling
module. Router::check_infallible
has been removed since routers are always infallible with the error handling changes.- Error handling closures must now handle all errors and thus always return
something that implements
IntoResponse
.
With these changes handling errors from fallible middleware is done like so:
use axum::{ routing::get, http::StatusCode, error_handling::HandleErrorLayer, response::IntoResponse, Router, BoxError, }; use tower::ServiceBuilder; use std::time::Duration; let middleware_stack = ServiceBuilder::new() // Handle errors from middleware // // This middleware most be added above any fallible // ones if you're using `ServiceBuilder`, due to how ordering works .layer(HandleErrorLayer::new(handle_error)) // Return an error after 30 seconds .timeout(Duration::from_secs(30)); let app = Router::new() .route("/", get(|| async { /* ... */ })) .layer(middleware_stack); fn handle_error(_error: BoxError) -> impl IntoResponse { StatusCode::REQUEST_TIMEOUT }
And handling errors from fallible leaf services is done like so:
use axum::{ Router, service, body::Body, routing::service_method_routing::get, response::IntoResponse, http::{Request, Response}, error_handling::HandleErrorExt, // for `.handle_error` }; use std::{io, convert::Infallible}; use tower::service_fn; let app = Router::new() .route( "/", get(service_fn(|_req: Request<Body>| async { let contents = tokio::fs::read_to_string("some_file").await?; Ok::<_, io::Error>(Response::new(Body::from(contents))) })) .handle_error(handle_io_error), ); fn handle_io_error(error: io::Error) -> impl IntoResponse { // ... }
-
- Misc:
0.2.8 (07. October, 2021)
- Document debugging handler type errors with "axum-debug" (#372)
0.2.7 (06. October, 2021)
- Bump minimum version of async-trait (#370)
0.2.6 (02. October, 2021)
- Clarify that
handler::any
andservice::any
only accepts standard HTTP methods (#337) - Document how to customize error responses from extractors (#359)
0.2.5 (18. September, 2021)
0.2.4 (10. September, 2021)
- Document using
StreamExt::split
withWebSocket
(#291) - Document adding middleware to multiple groups of routes (#293)
0.2.3 (26. August, 2021)
- fixed: Fix accidental breaking change introduced by internal refactor.
BoxRoute
used to beSync
but was accidental made!Sync
(#273)
0.2.2 (26. August, 2021)
- fixed: Fix URI captures matching empty segments. This means requests with
URI
/
will no longer be matched by/:key
(#264) - fixed: Remove needless trait bounds from
Router::boxed
(#269)
0.2.1 (24. August, 2021)
- added: Add
Redirect::to
constructor (#255) - added: Document how to implement
IntoResponse
for custom error type (#258)
0.2.0 (23. August, 2021)
-
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. So
Router::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 foraxum::routing::nest
. (#215) - changed: Implement
routing::MethodFilter
viabitflags
(#158) - changed: Move
handle_error
fromServiceExt
toservice::OnMethod
(#160)
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() }
- added: Add dedicated
-
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 removeduri
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)
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()) } }
- added: Add
-
SSE:
- added: Add
response::sse::Sse
. This implements SSE using a response rather than a service (#98) - changed: Remove
axum::sse
. It has been replaced byaxum::response::sse
(#98)
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) }), );
- added: Add
-
WebSockets:
- changed: Change WebSocket API to use an extractor plus a response (#121)
- changed: Make WebSocket
Message
an enum (#116) - changed:
WebSocket
now usesError
as its error type (#150)
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 thantower::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
0.1.3 (06. August, 2021)
- Fix stripping prefix when nesting services at
/
(#91) - Add support for WebSocket protocol negotiation (#83)
- Use
pin-project-lite
instead ofpin-project
(#95) - Re-export
http
crate andhyper::Server
(#110) - Fix
Query
andForm
extractors giving bad request error when query string is empty. (#117) - Add
Path
extractor. (#124) - Fixed the implementation of
IntoResponse
of(HeaderMap, T)
and(StatusCode, HeaderMap, T)
would ignore headers fromT
(#137) - Deprecate
extract::UrlParams
andextract::UrlParamsMap
. Useextract::Path
instead (#138)
0.1.2 (01. August, 2021)
- Implement
Stream
forWebSocket
(#52) - Implement
Sink
forWebSocket
(#52) - Implement
Deref
most extractors (#56) - Return
405 Method Not Allowed
for unsupported method for route (#63) - Add extractor for remote connection info (#55)
- Improve error message of
MissingExtension
rejections (#72) - Improve documentation for routing (#71)
- Clarify required response body type when routing to
tower::Service
s (#69) - Add
axum::body::box_body
to converting anhttp_body::Body
toaxum::body::BoxBody
(#69) - Add
axum::sse
for Server-Sent Events (#75) - Mention required dependencies in docs (#77)
- Fix WebSockets failing on Firefox (#76)
0.1.1 (30. July, 2021)
- Misc readme fixes.
0.1.0 (30. July, 2021)
- Initial release.