diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 512af468..6c454a04 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -125,6 +125,15 @@ jobs: deny-check: name: cargo-deny check runs-on: ubuntu-latest + continue-on-error: ${{ matrix.checks == 'advisories' }} + strategy: + matrix: + checks: + - advisories + - bans licenses sources steps: - - uses: actions/checkout@v1 - - uses: EmbarkStudios/cargo-deny-action@v1 + - uses: actions/checkout@v2 + - uses: EmbarkStudios/cargo-deny-action@v1 + with: + command: check ${{ matrix.checks }} + arguments: --all-features --manifest-path axum/Cargo.toml diff --git a/CHANGELOG.md b/CHANGELOG.md index b94c87fe..12ca64c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,480 +1 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -# Unreleased - -- None - -# 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: - - ```rust - 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` and `BoxRoute` have been removed as they're no longer - necessary ([#404]) - - **breaking:** `Nested`, `Or` types are now private. They no longer had to be - public because `Router` is internally boxed ([#404]) - - **breaking:** Remove `routing::Layered` as it didn't actually do anything and - thus wasn't necessary - - **breaking:** Vendor `AddExtensionLayer` and `AddExtension` to reduce public - dependencies - - **breaking:** `body::BoxBody` is now a type alias for - `http_body::combinators::UnsyncBoxBody` and thus is no longer `Sync`. This - is because bodies are streams and requiring streams to be `Sync` is - unnecessary. - - **added:** Implement `IntoResponse` for `http_body::combinators::UnsyncBoxBody`. - - **added:** Add `Handler::into_make_service` for serving a handler without a - `Router`. - - **added:** Add `Handler::into_make_service_with_connect_info` for serving a - handler without a `Router`, 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))`. - - **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` - to `axum::routing`. So `axum::handler::get` now lives at `axum::routing::get` - ([#405]) - - **breaking:** Method routing for services has been moved from `axum::service` - to `axum::routing::service_method_routing`. So `axum::service::get` now lives at - `axum::routing::service_method_routing::get`, etc. ([#405]) - - **breaking:** `Router::or` renamed to `Router::merge` and will now panic on - overlapping routes. It now only accepts `Router`s and not general `Service`s. - Use `Router::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 of `nest("/", _)` ([#408]) - - **breaking:** `EmptyRouter` has been renamed to `MethodNotAllowed` 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][proxy] ([#428]) -- Extractors: - - **fixed:** Expand accepted content types for JSON requests ([#378]) - - **fixed:** Support deserializing `i128` and `u128` in `extract::Path` - - **breaking:** Automatically do percent decoding in `extract::Path` - ([#272]) - - **breaking:** Change `Connected::connect_info` to return `Self` and remove - the associated type `ConnectInfo` ([#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: - - ```rust,no_run - 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: - - ```rust - 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| 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: - - `InvalidWebsocketVersionHeader` has been renamed to `InvalidWebSocketVersionHeader` ([#416]) - - `WebsocketKeyHeaderMissing` has been renamed to `WebSocketKeyHeaderMissing` ([#416]) - -[#339]: https://github.com/tokio-rs/axum/pull/339 -[#286]: https://github.com/tokio-rs/axum/pull/286 -[#272]: https://github.com/tokio-rs/axum/pull/272 -[#378]: https://github.com/tokio-rs/axum/pull/378 -[#363]: https://github.com/tokio-rs/axum/pull/363 -[#396]: https://github.com/tokio-rs/axum/pull/396 -[#402]: https://github.com/tokio-rs/axum/pull/402 -[#404]: https://github.com/tokio-rs/axum/pull/404 -[#405]: https://github.com/tokio-rs/axum/pull/405 -[#408]: https://github.com/tokio-rs/axum/pull/408 -[#412]: https://github.com/tokio-rs/axum/pull/412 -[#416]: https://github.com/tokio-rs/axum/pull/416 -[#428]: https://github.com/tokio-rs/axum/pull/428 -[proxy]: https://github.com/tokio-rs/axum/blob/main/examples/http-proxy/src/main.rs - -# 0.2.8 (07. October, 2021) - -- Document debugging handler type errors with "axum-debug" ([#372]) - -[#372]: https://github.com/tokio-rs/axum/pull/372 - -# 0.2.7 (06. October, 2021) - -- Bump minimum version of async-trait ([#370]) - -[#370]: https://github.com/tokio-rs/axum/pull/370 - -# 0.2.6 (02. October, 2021) - -- Clarify that `handler::any` and `service::any` only accepts standard HTTP - methods ([#337]) -- Document how to customize error responses from extractors ([#359]) - -[#337]: https://github.com/tokio-rs/axum/pull/337 -[#359]: https://github.com/tokio-rs/axum/pull/359 - -# 0.2.5 (18. September, 2021) - -- Add accessors for `TypedHeaderRejection` fields ([#317]) -- Improve docs for extractors ([#327]) - -[#317]: https://github.com/tokio-rs/axum/pull/317 -[#327]: https://github.com/tokio-rs/axum/pull/327 - -# 0.2.4 (10. September, 2021) - -- Document using `StreamExt::split` with `WebSocket` ([#291]) -- Document adding middleware to multiple groups of routes ([#293]) - -[#291]: https://github.com/tokio-rs/axum/pull/291 -[#293]: https://github.com/tokio-rs/axum/pull/293 - -# 0.2.3 (26. August, 2021) - -- **fixed:** Fix accidental breaking change introduced by internal refactor. - `BoxRoute` used to be `Sync` but was accidental made `!Sync` ([#273](https://github.com/tokio-rs/axum/pull/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](https://github.com/tokio-rs/axum/pull/264)) -- **fixed:** Remove needless trait bounds from `Router::boxed` ([#269](https://github.com/tokio-rs/axum/pull/269)) - -# 0.2.1 (24. August, 2021) - -- **added:** Add `Redirect::to` constructor ([#255](https://github.com/tokio-rs/axum/pull/255)) -- **added:** Document how to implement `IntoResponse` for custom error type ([#258](https://github.com/tokio-rs/axum/pull/258)) - -# 0.2.0 (23. August, 2021) - -- Overall: - - **fixed:** Overall compile time improvements. If you're having issues with compile time - please file an issue! ([#184](https://github.com/tokio-rs/axum/pull/184)) ([#198](https://github.com/tokio-rs/axum/pull/198)) ([#220](https://github.com/tokio-rs/axum/pull/220)) - - **changed:** Remove `prelude`. Explicit imports are now required ([#195](https://github.com/tokio-rs/axum/pull/195)) -- Routing: - - **added:** Add dedicated `Router` to replace the `RoutingDsl` trait ([#214](https://github.com/tokio-rs/axum/pull/214)) - - **added:** Add `Router::or` for combining routes ([#108](https://github.com/tokio-rs/axum/pull/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 both `GET` and `POST`. Previously only `POST` would be accepted ([#224](https://github.com/tokio-rs/axum/pull/224)) - - **fixed:** `get` routes will now also be called for `HEAD` requests but will always have - the response body removed ([#129](https://github.com/tokio-rs/axum/pull/129)) - - **changed:** Replace `axum::route(...)` with `axum::Router::new().route(...)`. This means - there is now only one way to create a new router. Same goes for - `axum::routing::nest`. ([#215](https://github.com/tokio-rs/axum/pull/215)) - - **changed:** Implement `routing::MethodFilter` via [`bitflags`](https://crates.io/crates/bitflags) ([#158](https://github.com/tokio-rs/axum/pull/158)) - - **changed:** Move `handle_error` from `ServiceExt` to `service::OnMethod` ([#160](https://github.com/tokio-rs/axum/pull/160)) - - With these changes this app using 0.1: - - ```rust - 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 { - route( - "/users", - post(|Extension(state): Extension| async { "hi from nested" }), - ) - .boxed() - } - ``` - - Becomes this in 0.2: - - ```rust - 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 { - Router::new() - .route( - "/users", - post(|Extension(state): Extension| async { "hi from nested" }), - ) - .boxed() - } - ``` -- Extractors: - - **added:** Make `FromRequest` default to being generic over `body::Body` ([#146](https://github.com/tokio-rs/axum/pull/146)) - - **added:** Implement `std::error::Error` for all rejections ([#153](https://github.com/tokio-rs/axum/pull/153)) - - **added:** Add `OriginalUri` for extracting original request URI in nested services ([#197](https://github.com/tokio-rs/axum/pull/197)) - - **added:** Implement `FromRequest` for `http::Extensions` ([#169](https://github.com/tokio-rs/axum/pull/169)) - - **added:** Make `RequestParts::{new, try_into_request}` public so extractors can be used outside axum ([#194](https://github.com/tokio-rs/axum/pull/194)) - - **added:** Implement `FromRequest` for `axum::body::Body` ([#241](https://github.com/tokio-rs/axum/pull/241)) - - **changed:** Removed `extract::UrlParams` and `extract::UrlParamsMap`. Use `extract::Path` instead ([#154](https://github.com/tokio-rs/axum/pull/154)) - - **changed:** `extractor_middleware` now requires `RequestBody: Default` ([#167](https://github.com/tokio-rs/axum/pull/167)) - - **changed:** Convert `RequestAlreadyExtracted` to an enum with each possible error variant ([#167](https://github.com/tokio-rs/axum/pull/167)) - - **changed:** `extract::BodyStream` is no longer generic over the request body ([#234](https://github.com/tokio-rs/axum/pull/234)) - - **changed:** `extract::Body` has been renamed to `extract::RawBody` to avoid conflicting with `body::Body` ([#233](https://github.com/tokio-rs/axum/pull/233)) - - **changed:** `RequestParts` changes ([#153](https://github.com/tokio-rs/axum/pull/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](https://github.com/tokio-rs/axum/pull/153)) ([#154](https://github.com/tokio-rs/axum/pull/154)) -- Responses: - - **added:** Add `Headers` for easily customizing headers on a response ([#193](https://github.com/tokio-rs/axum/pull/193)) - - **added:** Add `Redirect` response ([#192](https://github.com/tokio-rs/axum/pull/192)) - - **added:** Add `body::StreamBody` for easily responding with a stream of byte chunks ([#237](https://github.com/tokio-rs/axum/pull/237)) - - **changed:** Add associated `Body` and `BodyError` types to `IntoResponse`. This is - required for returning responses with bodies other than `hyper::Body` from - handlers. See the docs for advice on how to implement `IntoResponse` ([#86](https://github.com/tokio-rs/axum/pull/86)) - - **changed:** `tower::util::Either` no longer implements `IntoResponse` ([#229](https://github.com/tokio-rs/axum/pull/229)) - - This `IntoResponse` from 0.1: - ```rust - use axum::{http::Response, prelude::*, response::IntoResponse}; - - struct MyResponse; - - impl IntoResponse for MyResponse { - fn into_response(self) -> Response { - Response::new(Body::empty()) - } - } - ``` - - Becomes this in 0.2: - ```rust - use axum::{body::Body, http::Response, response::IntoResponse}; - - struct MyResponse; - - impl IntoResponse for MyResponse { - type Body = Body; - type BodyError = ::Error; - - fn into_response(self) -> Response { - Response::new(Body::empty()) - } - } - ``` -- SSE: - - **added:** Add `response::sse::Sse`. This implements SSE using a response rather than a service ([#98](https://github.com/tokio-rs/axum/pull/98)) - - **changed:** Remove `axum::sse`. Its been replaced by `axum::response::sse` ([#98](https://github.com/tokio-rs/axum/pull/98)) - - Handler using SSE in 0.1: - ```rust - 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: - - ```rust - 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: - - **changed:** Change WebSocket API to use an extractor plus a response ([#121](https://github.com/tokio-rs/axum/pull/121)) - - **changed:** Make WebSocket `Message` an enum ([#116](https://github.com/tokio-rs/axum/pull/116)) - - **changed:** `WebSocket` now uses `Error` as its error type ([#150](https://github.com/tokio-rs/axum/pull/150)) - - Handler using WebSockets in 0.1: - - ```rust - use axum::{ - prelude::*, - ws::{ws, WebSocket}, - }; - - let app = route( - "/", - ws(|socket: WebSocket| async move { - // do stuff with socket - }), - ); - ``` - - Becomes this in 0.2: - - ```rust - 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 exposes `tower`'s `log` feature. ([#218](https://github.com/tokio-rs/axum/pull/218)) - - **changed:** Replace `body::BoxStdError` with `axum::Error`, which supports downcasting ([#150](https://github.com/tokio-rs/axum/pull/150)) - - **changed:** `EmptyRouter` now requires the response body to implement `Send + Sync + 'static'` ([#108](https://github.com/tokio-rs/axum/pull/108)) - - **changed:** `Router::check_infallible` now returns a `CheckInfallible` service. This - is to improve compile times ([#198](https://github.com/tokio-rs/axum/pull/198)) - - **changed:** `Router::into_make_service` now returns `routing::IntoMakeService` rather than - `tower::make::Shared` ([#229](https://github.com/tokio-rs/axum/pull/229)) - - **changed:** All usage of `tower::BoxError` has been replaced with `axum::BoxError` ([#229](https://github.com/tokio-rs/axum/pull/229)) - - **changed:** Several response future types have been moved into dedicated - `future` modules ([#133](https://github.com/tokio-rs/axum/pull/133)) - - **changed:** `EmptyRouter`, `ExtractorMiddleware`, `ExtractorMiddlewareLayer`, - and `QueryStringMissing` no longer implement `Copy` ([#132](https://github.com/tokio-rs/axum/pull/132)) - - **changed:** `service::OnMethod`, `handler::OnMethod`, and `routing::Nested` have new response future types ([#157](https://github.com/tokio-rs/axum/pull/157)) - -# 0.1.3 (06. August, 2021) - -- Fix stripping prefix when nesting services at `/` ([#91](https://github.com/tokio-rs/axum/pull/91)) -- Add support for WebSocket protocol negotiation ([#83](https://github.com/tokio-rs/axum/pull/83)) -- Use `pin-project-lite` instead of `pin-project` ([#95](https://github.com/tokio-rs/axum/pull/95)) -- Re-export `http` crate and `hyper::Server` ([#110](https://github.com/tokio-rs/axum/pull/110)) -- Fix `Query` and `Form` extractors giving bad request error when query string is empty. ([#117](https://github.com/tokio-rs/axum/pull/117)) -- Add `Path` extractor. ([#124](https://github.com/tokio-rs/axum/pull/124)) -- Fixed the implementation of `IntoResponse` of `(HeaderMap, T)` and `(StatusCode, HeaderMap, T)` would ignore headers from `T` ([#137](https://github.com/tokio-rs/axum/pull/137)) -- Deprecate `extract::UrlParams` and `extract::UrlParamsMap`. Use `extract::Path` instead ([#138](https://github.com/tokio-rs/axum/pull/138)) - -# 0.1.2 (01. August, 2021) - -- Implement `Stream` for `WebSocket` ([#52](https://github.com/tokio-rs/axum/pull/52)) -- Implement `Sink` for `WebSocket` ([#52](https://github.com/tokio-rs/axum/pull/52)) -- Implement `Deref` most extractors ([#56](https://github.com/tokio-rs/axum/pull/56)) -- Return `405 Method Not Allowed` for unsupported method for route ([#63](https://github.com/tokio-rs/axum/pull/63)) -- Add extractor for remote connection info ([#55](https://github.com/tokio-rs/axum/pull/55)) -- Improve error message of `MissingExtension` rejections ([#72](https://github.com/tokio-rs/axum/pull/72)) -- Improve documentation for routing ([#71](https://github.com/tokio-rs/axum/pull/71)) -- Clarify required response body type when routing to `tower::Service`s ([#69](https://github.com/tokio-rs/axum/pull/69)) -- Add `axum::body::box_body` to converting an `http_body::Body` to `axum::body::BoxBody` ([#69](https://github.com/tokio-rs/axum/pull/69)) -- Add `axum::sse` for Server-Sent Events ([#75](https://github.com/tokio-rs/axum/pull/75)) -- Mention required dependencies in docs ([#77](https://github.com/tokio-rs/axum/pull/77)) -- Fix WebSockets failing on Firefox ([#76](https://github.com/tokio-rs/axum/pull/76)) - -# 0.1.1 (30. July, 2021) - -- Misc readme fixes. - -# 0.1.0 (30. July, 2021) - -- Initial release. +axum's changelog has moved and now lives [here](https://github.com/tokio-rs/axum/blob/main/axum/CHANGELOG.md). diff --git a/Cargo.toml b/Cargo.toml index d4acebe5..156fa711 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,95 +1,5 @@ -[package] -name = "axum" -version = "0.3.0" -authors = ["David Pedersen "] -categories = ["asynchronous", "network-programming", "web-programming"] -description = "Web framework that focuses on ergonomics and modularity" -edition = "2018" -homepage = "https://github.com/tokio-rs/axum" -keywords = ["http", "web", "framework"] -license = "MIT" -readme = "README.md" -repository = "https://github.com/tokio-rs/axum" - [workspace] -members = ["examples/*"] - -[features] -default = ["http1", "json", "tower-log"] -http1 = ["hyper/http1"] -http2 = ["hyper/http2"] -json = ["serde_json", "mime"] -multipart = ["multer", "mime"] -tower-log = ["tower/log"] -ws = ["tokio-tungstenite", "sha-1", "base64"] - -[dependencies] -async-trait = "0.1.43" -bitflags = "1.0" -bytes = "1.0" -futures-util = { version = "0.3", default-features = false, features = ["alloc"] } -http = "0.2" -http-body = "0.4.4" -hyper = { version = "0.14.14", features = ["server", "tcp", "stream"] } -matchit = "0.4.4" -percent-encoding = "2.1" -pin-project-lite = "0.2.7" -serde = "1.0" -serde_urlencoded = "0.7" -sync_wrapper = "0.1.1" -tokio = { version = "1", features = ["time"] } -tokio-util = "0.6" -tower = { version = "0.4.10", default-features = false, features = ["util", "buffer", "make"] } -tower-http = { version = "0.1", features = ["add-extension", "map-response-body"] } -tower-layer = "0.3" -tower-service = "0.3" - -# optional dependencies -base64 = { optional = true, version = "0.13" } -headers = { optional = true, version = "0.3" } -mime = { optional = true, version = "0.3" } -multer = { optional = true, version = "2.0.0" } -serde_json = { version = "1.0", optional = true } -sha-1 = { optional = true, version = "0.9.6" } -tokio-tungstenite = { optional = true, version = "0.15" } - -[dev-dependencies] -futures = "0.3" -reqwest = { version = "0.11", features = ["json", "stream"] } -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" -tokio = { version = "1.6.1", features = ["macros", "rt", "rt-multi-thread", "net"] } -tokio-stream = "0.1" -tracing = "0.1" -uuid = { version = "0.8", features = ["serde", "v4"] } -anyhow = "1.0" - -[dev-dependencies.tower] -package = "tower" -version = "0.4.10" -features = [ - "util", - "timeout", - "limit", - "load-shed", - "steer", - "filter", -] - -[dev-dependencies.tower-http] -version = "0.1" -features = ["full"] - -[package.metadata.docs.rs] -all-features = true -rustdoc-args = ["--cfg", "docsrs"] - -[package.metadata.playground] -features = [ - "http1", - "http2", - "json", - "multipart", - "tower", - "ws", +members = [ + "axum", + "examples/*", ] diff --git a/README.md b/README.md deleted file mode 100644 index 08e48453..00000000 --- a/README.md +++ /dev/null @@ -1,157 +0,0 @@ -# axum - -`axum` is a web application framework that focuses on ergonomics and modularity. - -[![Build status](https://github.com/tokio-rs/axum/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/tokio-rs/axum/actions/workflows/CI.yml) -[![Crates.io](https://img.shields.io/crates/v/axum)](https://crates.io/crates/axum) -[![Documentation](https://docs.rs/axum/badge.svg)](https://docs.rs/axum) - -More information about this crate can be found in the [crate documentation][docs]. - -## High level features - -- Route requests to handlers with a macro free API. -- Declaratively parse requests using extractors. -- Simple and predictable error handling model. -- Generate responses with minimal boilerplate. -- Take full advantage of the [`tower`] and [`tower-http`] ecosystem of - middleware, services, and utilities. - -In particular the last point is what sets `axum` apart from other frameworks. -`axum` doesn't have its own middleware system but instead uses -[`tower::Service`]. This means `axum` gets timeouts, tracing, compression, -authorization, and more, for free. It also enables you to share middleware with -applications written using [`hyper`] or [`tonic`]. - -## Usage example - -```rust -use axum::{ - routing::{get, post}, - http::StatusCode, - response::IntoResponse, - Json, Router, -}; -use serde::{Deserialize, Serialize}; -use std::net::SocketAddr; - -#[tokio::main] -async fn main() { - // initialize tracing - tracing_subscriber::fmt::init(); - - // build our application with a route - let app = Router::new() - // `GET /` goes to `root` - .route("/", get(root)) - // `POST /users` goes to `create_user` - .route("/users", post(create_user)); - - // run our app with hyper - // `axum::Server` is a re-export of `hyper::Server` - let addr = SocketAddr::from(([127, 0, 0, 1], 3000)); - tracing::debug!("listening on {}", addr); - axum::Server::bind(&addr) - .serve(app.into_make_service()) - .await - .unwrap(); -} - -// basic handler that responds with a static string -async fn root() -> &'static str { - "Hello, World!" -} - -async fn create_user( - // this argument tells axum to parse the request body - // as JSON into a `CreateUser` type - Json(payload): Json, -) -> impl IntoResponse { - // insert your application logic here - let user = User { - id: 1337, - username: payload.username, - }; - - // this will be converted into a JSON response - // with a status code of `201 Created` - (StatusCode::CREATED, Json(user)) -} - -// the input to our `create_user` handler -#[derive(Deserialize)] -struct CreateUser { - username: String, -} - -// the output to our `create_user` handler -#[derive(Serialize)] -struct User { - id: u64, - username: String, -} -``` - -You can find this [example][readme-example] as well as other example projects in -the [example directory][examples]. - -See the [crate documentation][docs] for way more examples. - -## Performance - -`axum` is a relatively thin layer on top of [`hyper`] and adds very little -overhead. So `axum`'s performance is comparable to [`hyper`]. You can find a -benchmark [here](https://github.com/programatik29/rust-web-benchmarks). - -## Safety - -This crate uses `#![forbid(unsafe_code)]` to ensure everything is implemented in -100% safe Rust. - -## Minimum supported Rust version - -axum's MSRV is 1.54. - -## Examples - -The [examples] folder contains various examples of how to use `axum`. The -[docs] also have lots of examples - -## Getting Help - -In the `axum`'s repo we also have a [number of examples][examples] showing how -to put everything together. You're also welcome to ask in the [Discord -channel][chat] or open an [issue] with your question. - -## Community projects - -See [here](ECOSYSTEM.md) for a list of community maintained crates and projects -built with axum. - -## Contributing - -:balloon: Thanks for your help improving the project! We are so happy to have -you! We have a [contributing guide][guide] to help you get involved in the -`axum` project. - -## License - -This project is licensed under the [MIT license](LICENSE). - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in `axum` by you, shall be licensed as MIT, without any -additional terms or conditions. - -[readme-example]: https://github.com/tokio-rs/axum/tree/main/examples/readme -[examples]: https://github.com/tokio-rs/axum/tree/main/examples -[docs]: https://docs.rs/axum -[`tower`]: https://crates.io/crates/tower -[`hyper`]: https://crates.io/crates/hyper -[`tower-http`]: https://crates.io/crates/tower-http -[`tonic`]: https://crates.io/crates/tonic -[guide]: CONTRIBUTING.md -[chat]: https://discord.gg/tokio -[issue]: https://github.com/tokio-rs/axum/issues/new -[`tower::Service`]: https://docs.rs/tower/latest/tower/trait.Service.html diff --git a/README.md b/README.md new file mode 120000 index 00000000..7deece5a --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +axum/README.md \ No newline at end of file diff --git a/axum/CHANGELOG.md b/axum/CHANGELOG.md new file mode 100644 index 00000000..b94c87fe --- /dev/null +++ b/axum/CHANGELOG.md @@ -0,0 +1,480 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +# Unreleased + +- None + +# 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: + + ```rust + 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` and `BoxRoute` have been removed as they're no longer + necessary ([#404]) + - **breaking:** `Nested`, `Or` types are now private. They no longer had to be + public because `Router` is internally boxed ([#404]) + - **breaking:** Remove `routing::Layered` as it didn't actually do anything and + thus wasn't necessary + - **breaking:** Vendor `AddExtensionLayer` and `AddExtension` to reduce public + dependencies + - **breaking:** `body::BoxBody` is now a type alias for + `http_body::combinators::UnsyncBoxBody` and thus is no longer `Sync`. This + is because bodies are streams and requiring streams to be `Sync` is + unnecessary. + - **added:** Implement `IntoResponse` for `http_body::combinators::UnsyncBoxBody`. + - **added:** Add `Handler::into_make_service` for serving a handler without a + `Router`. + - **added:** Add `Handler::into_make_service_with_connect_info` for serving a + handler without a `Router`, 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))`. + - **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` + to `axum::routing`. So `axum::handler::get` now lives at `axum::routing::get` + ([#405]) + - **breaking:** Method routing for services has been moved from `axum::service` + to `axum::routing::service_method_routing`. So `axum::service::get` now lives at + `axum::routing::service_method_routing::get`, etc. ([#405]) + - **breaking:** `Router::or` renamed to `Router::merge` and will now panic on + overlapping routes. It now only accepts `Router`s and not general `Service`s. + Use `Router::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 of `nest("/", _)` ([#408]) + - **breaking:** `EmptyRouter` has been renamed to `MethodNotAllowed` 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][proxy] ([#428]) +- Extractors: + - **fixed:** Expand accepted content types for JSON requests ([#378]) + - **fixed:** Support deserializing `i128` and `u128` in `extract::Path` + - **breaking:** Automatically do percent decoding in `extract::Path` + ([#272]) + - **breaking:** Change `Connected::connect_info` to return `Self` and remove + the associated type `ConnectInfo` ([#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: + + ```rust,no_run + 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: + + ```rust + 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| 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: + - `InvalidWebsocketVersionHeader` has been renamed to `InvalidWebSocketVersionHeader` ([#416]) + - `WebsocketKeyHeaderMissing` has been renamed to `WebSocketKeyHeaderMissing` ([#416]) + +[#339]: https://github.com/tokio-rs/axum/pull/339 +[#286]: https://github.com/tokio-rs/axum/pull/286 +[#272]: https://github.com/tokio-rs/axum/pull/272 +[#378]: https://github.com/tokio-rs/axum/pull/378 +[#363]: https://github.com/tokio-rs/axum/pull/363 +[#396]: https://github.com/tokio-rs/axum/pull/396 +[#402]: https://github.com/tokio-rs/axum/pull/402 +[#404]: https://github.com/tokio-rs/axum/pull/404 +[#405]: https://github.com/tokio-rs/axum/pull/405 +[#408]: https://github.com/tokio-rs/axum/pull/408 +[#412]: https://github.com/tokio-rs/axum/pull/412 +[#416]: https://github.com/tokio-rs/axum/pull/416 +[#428]: https://github.com/tokio-rs/axum/pull/428 +[proxy]: https://github.com/tokio-rs/axum/blob/main/examples/http-proxy/src/main.rs + +# 0.2.8 (07. October, 2021) + +- Document debugging handler type errors with "axum-debug" ([#372]) + +[#372]: https://github.com/tokio-rs/axum/pull/372 + +# 0.2.7 (06. October, 2021) + +- Bump minimum version of async-trait ([#370]) + +[#370]: https://github.com/tokio-rs/axum/pull/370 + +# 0.2.6 (02. October, 2021) + +- Clarify that `handler::any` and `service::any` only accepts standard HTTP + methods ([#337]) +- Document how to customize error responses from extractors ([#359]) + +[#337]: https://github.com/tokio-rs/axum/pull/337 +[#359]: https://github.com/tokio-rs/axum/pull/359 + +# 0.2.5 (18. September, 2021) + +- Add accessors for `TypedHeaderRejection` fields ([#317]) +- Improve docs for extractors ([#327]) + +[#317]: https://github.com/tokio-rs/axum/pull/317 +[#327]: https://github.com/tokio-rs/axum/pull/327 + +# 0.2.4 (10. September, 2021) + +- Document using `StreamExt::split` with `WebSocket` ([#291]) +- Document adding middleware to multiple groups of routes ([#293]) + +[#291]: https://github.com/tokio-rs/axum/pull/291 +[#293]: https://github.com/tokio-rs/axum/pull/293 + +# 0.2.3 (26. August, 2021) + +- **fixed:** Fix accidental breaking change introduced by internal refactor. + `BoxRoute` used to be `Sync` but was accidental made `!Sync` ([#273](https://github.com/tokio-rs/axum/pull/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](https://github.com/tokio-rs/axum/pull/264)) +- **fixed:** Remove needless trait bounds from `Router::boxed` ([#269](https://github.com/tokio-rs/axum/pull/269)) + +# 0.2.1 (24. August, 2021) + +- **added:** Add `Redirect::to` constructor ([#255](https://github.com/tokio-rs/axum/pull/255)) +- **added:** Document how to implement `IntoResponse` for custom error type ([#258](https://github.com/tokio-rs/axum/pull/258)) + +# 0.2.0 (23. August, 2021) + +- Overall: + - **fixed:** Overall compile time improvements. If you're having issues with compile time + please file an issue! ([#184](https://github.com/tokio-rs/axum/pull/184)) ([#198](https://github.com/tokio-rs/axum/pull/198)) ([#220](https://github.com/tokio-rs/axum/pull/220)) + - **changed:** Remove `prelude`. Explicit imports are now required ([#195](https://github.com/tokio-rs/axum/pull/195)) +- Routing: + - **added:** Add dedicated `Router` to replace the `RoutingDsl` trait ([#214](https://github.com/tokio-rs/axum/pull/214)) + - **added:** Add `Router::or` for combining routes ([#108](https://github.com/tokio-rs/axum/pull/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 both `GET` and `POST`. Previously only `POST` would be accepted ([#224](https://github.com/tokio-rs/axum/pull/224)) + - **fixed:** `get` routes will now also be called for `HEAD` requests but will always have + the response body removed ([#129](https://github.com/tokio-rs/axum/pull/129)) + - **changed:** Replace `axum::route(...)` with `axum::Router::new().route(...)`. This means + there is now only one way to create a new router. Same goes for + `axum::routing::nest`. ([#215](https://github.com/tokio-rs/axum/pull/215)) + - **changed:** Implement `routing::MethodFilter` via [`bitflags`](https://crates.io/crates/bitflags) ([#158](https://github.com/tokio-rs/axum/pull/158)) + - **changed:** Move `handle_error` from `ServiceExt` to `service::OnMethod` ([#160](https://github.com/tokio-rs/axum/pull/160)) + + With these changes this app using 0.1: + + ```rust + 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 { + route( + "/users", + post(|Extension(state): Extension| async { "hi from nested" }), + ) + .boxed() + } + ``` + + Becomes this in 0.2: + + ```rust + 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 { + Router::new() + .route( + "/users", + post(|Extension(state): Extension| async { "hi from nested" }), + ) + .boxed() + } + ``` +- Extractors: + - **added:** Make `FromRequest` default to being generic over `body::Body` ([#146](https://github.com/tokio-rs/axum/pull/146)) + - **added:** Implement `std::error::Error` for all rejections ([#153](https://github.com/tokio-rs/axum/pull/153)) + - **added:** Add `OriginalUri` for extracting original request URI in nested services ([#197](https://github.com/tokio-rs/axum/pull/197)) + - **added:** Implement `FromRequest` for `http::Extensions` ([#169](https://github.com/tokio-rs/axum/pull/169)) + - **added:** Make `RequestParts::{new, try_into_request}` public so extractors can be used outside axum ([#194](https://github.com/tokio-rs/axum/pull/194)) + - **added:** Implement `FromRequest` for `axum::body::Body` ([#241](https://github.com/tokio-rs/axum/pull/241)) + - **changed:** Removed `extract::UrlParams` and `extract::UrlParamsMap`. Use `extract::Path` instead ([#154](https://github.com/tokio-rs/axum/pull/154)) + - **changed:** `extractor_middleware` now requires `RequestBody: Default` ([#167](https://github.com/tokio-rs/axum/pull/167)) + - **changed:** Convert `RequestAlreadyExtracted` to an enum with each possible error variant ([#167](https://github.com/tokio-rs/axum/pull/167)) + - **changed:** `extract::BodyStream` is no longer generic over the request body ([#234](https://github.com/tokio-rs/axum/pull/234)) + - **changed:** `extract::Body` has been renamed to `extract::RawBody` to avoid conflicting with `body::Body` ([#233](https://github.com/tokio-rs/axum/pull/233)) + - **changed:** `RequestParts` changes ([#153](https://github.com/tokio-rs/axum/pull/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](https://github.com/tokio-rs/axum/pull/153)) ([#154](https://github.com/tokio-rs/axum/pull/154)) +- Responses: + - **added:** Add `Headers` for easily customizing headers on a response ([#193](https://github.com/tokio-rs/axum/pull/193)) + - **added:** Add `Redirect` response ([#192](https://github.com/tokio-rs/axum/pull/192)) + - **added:** Add `body::StreamBody` for easily responding with a stream of byte chunks ([#237](https://github.com/tokio-rs/axum/pull/237)) + - **changed:** Add associated `Body` and `BodyError` types to `IntoResponse`. This is + required for returning responses with bodies other than `hyper::Body` from + handlers. See the docs for advice on how to implement `IntoResponse` ([#86](https://github.com/tokio-rs/axum/pull/86)) + - **changed:** `tower::util::Either` no longer implements `IntoResponse` ([#229](https://github.com/tokio-rs/axum/pull/229)) + + This `IntoResponse` from 0.1: + ```rust + use axum::{http::Response, prelude::*, response::IntoResponse}; + + struct MyResponse; + + impl IntoResponse for MyResponse { + fn into_response(self) -> Response { + Response::new(Body::empty()) + } + } + ``` + + Becomes this in 0.2: + ```rust + use axum::{body::Body, http::Response, response::IntoResponse}; + + struct MyResponse; + + impl IntoResponse for MyResponse { + type Body = Body; + type BodyError = ::Error; + + fn into_response(self) -> Response { + Response::new(Body::empty()) + } + } + ``` +- SSE: + - **added:** Add `response::sse::Sse`. This implements SSE using a response rather than a service ([#98](https://github.com/tokio-rs/axum/pull/98)) + - **changed:** Remove `axum::sse`. Its been replaced by `axum::response::sse` ([#98](https://github.com/tokio-rs/axum/pull/98)) + + Handler using SSE in 0.1: + ```rust + 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: + + ```rust + 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: + - **changed:** Change WebSocket API to use an extractor plus a response ([#121](https://github.com/tokio-rs/axum/pull/121)) + - **changed:** Make WebSocket `Message` an enum ([#116](https://github.com/tokio-rs/axum/pull/116)) + - **changed:** `WebSocket` now uses `Error` as its error type ([#150](https://github.com/tokio-rs/axum/pull/150)) + + Handler using WebSockets in 0.1: + + ```rust + use axum::{ + prelude::*, + ws::{ws, WebSocket}, + }; + + let app = route( + "/", + ws(|socket: WebSocket| async move { + // do stuff with socket + }), + ); + ``` + + Becomes this in 0.2: + + ```rust + 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 exposes `tower`'s `log` feature. ([#218](https://github.com/tokio-rs/axum/pull/218)) + - **changed:** Replace `body::BoxStdError` with `axum::Error`, which supports downcasting ([#150](https://github.com/tokio-rs/axum/pull/150)) + - **changed:** `EmptyRouter` now requires the response body to implement `Send + Sync + 'static'` ([#108](https://github.com/tokio-rs/axum/pull/108)) + - **changed:** `Router::check_infallible` now returns a `CheckInfallible` service. This + is to improve compile times ([#198](https://github.com/tokio-rs/axum/pull/198)) + - **changed:** `Router::into_make_service` now returns `routing::IntoMakeService` rather than + `tower::make::Shared` ([#229](https://github.com/tokio-rs/axum/pull/229)) + - **changed:** All usage of `tower::BoxError` has been replaced with `axum::BoxError` ([#229](https://github.com/tokio-rs/axum/pull/229)) + - **changed:** Several response future types have been moved into dedicated + `future` modules ([#133](https://github.com/tokio-rs/axum/pull/133)) + - **changed:** `EmptyRouter`, `ExtractorMiddleware`, `ExtractorMiddlewareLayer`, + and `QueryStringMissing` no longer implement `Copy` ([#132](https://github.com/tokio-rs/axum/pull/132)) + - **changed:** `service::OnMethod`, `handler::OnMethod`, and `routing::Nested` have new response future types ([#157](https://github.com/tokio-rs/axum/pull/157)) + +# 0.1.3 (06. August, 2021) + +- Fix stripping prefix when nesting services at `/` ([#91](https://github.com/tokio-rs/axum/pull/91)) +- Add support for WebSocket protocol negotiation ([#83](https://github.com/tokio-rs/axum/pull/83)) +- Use `pin-project-lite` instead of `pin-project` ([#95](https://github.com/tokio-rs/axum/pull/95)) +- Re-export `http` crate and `hyper::Server` ([#110](https://github.com/tokio-rs/axum/pull/110)) +- Fix `Query` and `Form` extractors giving bad request error when query string is empty. ([#117](https://github.com/tokio-rs/axum/pull/117)) +- Add `Path` extractor. ([#124](https://github.com/tokio-rs/axum/pull/124)) +- Fixed the implementation of `IntoResponse` of `(HeaderMap, T)` and `(StatusCode, HeaderMap, T)` would ignore headers from `T` ([#137](https://github.com/tokio-rs/axum/pull/137)) +- Deprecate `extract::UrlParams` and `extract::UrlParamsMap`. Use `extract::Path` instead ([#138](https://github.com/tokio-rs/axum/pull/138)) + +# 0.1.2 (01. August, 2021) + +- Implement `Stream` for `WebSocket` ([#52](https://github.com/tokio-rs/axum/pull/52)) +- Implement `Sink` for `WebSocket` ([#52](https://github.com/tokio-rs/axum/pull/52)) +- Implement `Deref` most extractors ([#56](https://github.com/tokio-rs/axum/pull/56)) +- Return `405 Method Not Allowed` for unsupported method for route ([#63](https://github.com/tokio-rs/axum/pull/63)) +- Add extractor for remote connection info ([#55](https://github.com/tokio-rs/axum/pull/55)) +- Improve error message of `MissingExtension` rejections ([#72](https://github.com/tokio-rs/axum/pull/72)) +- Improve documentation for routing ([#71](https://github.com/tokio-rs/axum/pull/71)) +- Clarify required response body type when routing to `tower::Service`s ([#69](https://github.com/tokio-rs/axum/pull/69)) +- Add `axum::body::box_body` to converting an `http_body::Body` to `axum::body::BoxBody` ([#69](https://github.com/tokio-rs/axum/pull/69)) +- Add `axum::sse` for Server-Sent Events ([#75](https://github.com/tokio-rs/axum/pull/75)) +- Mention required dependencies in docs ([#77](https://github.com/tokio-rs/axum/pull/77)) +- Fix WebSockets failing on Firefox ([#76](https://github.com/tokio-rs/axum/pull/76)) + +# 0.1.1 (30. July, 2021) + +- Misc readme fixes. + +# 0.1.0 (30. July, 2021) + +- Initial release. diff --git a/axum/Cargo.toml b/axum/Cargo.toml new file mode 100644 index 00000000..4f9e8a43 --- /dev/null +++ b/axum/Cargo.toml @@ -0,0 +1,92 @@ +[package] +name = "axum" +version = "0.3.0" +authors = ["David Pedersen "] +categories = ["asynchronous", "network-programming", "web-programming"] +description = "Web framework that focuses on ergonomics and modularity" +edition = "2018" +homepage = "https://github.com/tokio-rs/axum" +keywords = ["http", "web", "framework"] +license = "MIT" +readme = "README.md" +repository = "https://github.com/tokio-rs/axum" + +[features] +default = ["http1", "json", "tower-log"] +http1 = ["hyper/http1"] +http2 = ["hyper/http2"] +json = ["serde_json", "mime"] +multipart = ["multer", "mime"] +tower-log = ["tower/log"] +ws = ["tokio-tungstenite", "sha-1", "base64"] + +[dependencies] +async-trait = "0.1.43" +bitflags = "1.0" +bytes = "1.0" +futures-util = { version = "0.3", default-features = false, features = ["alloc"] } +http = "0.2" +http-body = "0.4.4" +hyper = { version = "0.14.14", features = ["server", "tcp", "stream"] } +matchit = "0.4.4" +percent-encoding = "2.1" +pin-project-lite = "0.2.7" +serde = "1.0" +serde_urlencoded = "0.7" +sync_wrapper = "0.1.1" +tokio = { version = "1", features = ["time"] } +tokio-util = "0.6" +tower = { version = "0.4.10", default-features = false, features = ["util", "buffer", "make"] } +tower-http = { version = "0.1", features = ["add-extension", "map-response-body"] } +tower-layer = "0.3" +tower-service = "0.3" + +# optional dependencies +base64 = { optional = true, version = "0.13" } +headers = { optional = true, version = "0.3" } +mime = { optional = true, version = "0.3" } +multer = { optional = true, version = "2.0.0" } +serde_json = { version = "1.0", optional = true } +sha-1 = { optional = true, version = "0.9.6" } +tokio-tungstenite = { optional = true, version = "0.15" } + +[dev-dependencies] +futures = "0.3" +reqwest = { version = "0.11", features = ["json", "stream"] } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +tokio = { version = "1.6.1", features = ["macros", "rt", "rt-multi-thread", "net"] } +tokio-stream = "0.1" +tracing = "0.1" +uuid = { version = "0.8", features = ["serde", "v4"] } +anyhow = "1.0" + +[dev-dependencies.tower] +package = "tower" +version = "0.4.10" +features = [ + "util", + "timeout", + "limit", + "load-shed", + "steer", + "filter", +] + +[dev-dependencies.tower-http] +version = "0.1" +features = ["full"] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[package.metadata.playground] +features = [ + "http1", + "http2", + "json", + "multipart", + "tower", + "ws", +] diff --git a/LICENSE b/axum/LICENSE similarity index 100% rename from LICENSE rename to axum/LICENSE diff --git a/axum/README.md b/axum/README.md new file mode 100644 index 00000000..defd00eb --- /dev/null +++ b/axum/README.md @@ -0,0 +1,159 @@ +# axum + +`axum` is a web application framework that focuses on ergonomics and modularity. + +[![Build status](https://github.com/tokio-rs/axum/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/tokio-rs/axum/actions/workflows/CI.yml) +[![Crates.io](https://img.shields.io/crates/v/axum)](https://crates.io/crates/axum) +[![Documentation](https://docs.rs/axum/badge.svg)](https://docs.rs/axum) + +More information about this crate can be found in the [crate documentation][docs]. + +## High level features + +- Route requests to handlers with a macro free API. +- Declaratively parse requests using extractors. +- Simple and predictable error handling model. +- Generate responses with minimal boilerplate. +- Take full advantage of the [`tower`] and [`tower-http`] ecosystem of + middleware, services, and utilities. + +In particular the last point is what sets `axum` apart from other frameworks. +`axum` doesn't have its own middleware system but instead uses +[`tower::Service`]. This means `axum` gets timeouts, tracing, compression, +authorization, and more, for free. It also enables you to share middleware with +applications written using [`hyper`] or [`tonic`]. + +## Usage example + +```rust +use axum::{ + routing::{get, post}, + http::StatusCode, + response::IntoResponse, + Json, Router, +}; +use serde::{Deserialize, Serialize}; +use std::net::SocketAddr; + +#[tokio::main] +async fn main() { + // initialize tracing + tracing_subscriber::fmt::init(); + + // build our application with a route + let app = Router::new() + // `GET /` goes to `root` + .route("/", get(root)) + // `POST /users` goes to `create_user` + .route("/users", post(create_user)); + + // run our app with hyper + // `axum::Server` is a re-export of `hyper::Server` + let addr = SocketAddr::from(([127, 0, 0, 1], 3000)); + tracing::debug!("listening on {}", addr); + axum::Server::bind(&addr) + .serve(app.into_make_service()) + .await + .unwrap(); +} + +// basic handler that responds with a static string +async fn root() -> &'static str { + "Hello, World!" +} + +async fn create_user( + // this argument tells axum to parse the request body + // as JSON into a `CreateUser` type + Json(payload): Json, +) -> impl IntoResponse { + // insert your application logic here + let user = User { + id: 1337, + username: payload.username, + }; + + // this will be converted into a JSON response + // with a status code of `201 Created` + (StatusCode::CREATED, Json(user)) +} + +// the input to our `create_user` handler +#[derive(Deserialize)] +struct CreateUser { + username: String, +} + +// the output to our `create_user` handler +#[derive(Serialize)] +struct User { + id: u64, + username: String, +} +``` + +You can find this [example][readme-example] as well as other example projects in +the [example directory][examples]. + +See the [crate documentation][docs] for way more examples. + +## Performance + +`axum` is a relatively thin layer on top of [`hyper`] and adds very little +overhead. So `axum`'s performance is comparable to [`hyper`]. You can find a +benchmark [here](https://github.com/programatik29/rust-web-benchmarks). + +## Safety + +This crate uses `#![forbid(unsafe_code)]` to ensure everything is implemented in +100% safe Rust. + +## Minimum supported Rust version + +axum's MSRV is 1.54. + +## Examples + +The [examples] folder contains various examples of how to use `axum`. The +[docs] also have lots of examples + +## Getting Help + +In the `axum`'s repo we also have a [number of examples][examples] showing how +to put everything together. You're also welcome to ask in the [Discord +channel][chat] or open an [issue] with your question. + +## Community projects + +See [here](ecosystem) for a list of community maintained crates and projects +built with axum. + +## Contributing + +:balloon: Thanks for your help improving the project! We are so happy to have +you! We have a [contributing guide][contributing] to help you get involved in the +`axum` project. + +## License + +This project is licensed under the [MIT license](license). + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in `axum` by you, shall be licensed as MIT, without any +additional terms or conditions. + +[readme-example]: https://github.com/tokio-rs/axum/tree/main/examples/readme +[examples]: https://github.com/tokio-rs/axum/tree/main/examples +[docs]: https://docs.rs/axum +[`tower`]: https://crates.io/crates/tower +[`hyper`]: https://crates.io/crates/hyper +[`tower-http`]: https://crates.io/crates/tower-http +[`tonic`]: https://crates.io/crates/tonic +[contributing]: https://github.com/tokio-rs/axum/blob/main/CONTRIBUTING.md +[chat]: https://discord.gg/tokio +[issue]: https://github.com/tokio-rs/axum/issues/new +[`tower::Service`]: https://docs.rs/tower/latest/tower/trait.Service.html +[ecosystem]: https://github.com/tokio-rs/axum/blob/main/ECOSYSTEM.md +[license]: https://github.com/tokio-rs/axum/blob/main/LICENSE diff --git a/src/add_extension.rs b/axum/src/add_extension.rs similarity index 100% rename from src/add_extension.rs rename to axum/src/add_extension.rs diff --git a/src/body.rs b/axum/src/body.rs similarity index 100% rename from src/body.rs rename to axum/src/body.rs diff --git a/src/body/stream_body.rs b/axum/src/body/stream_body.rs similarity index 100% rename from src/body/stream_body.rs rename to axum/src/body/stream_body.rs diff --git a/src/clone_box_service.rs b/axum/src/clone_box_service.rs similarity index 100% rename from src/clone_box_service.rs rename to axum/src/clone_box_service.rs diff --git a/src/docs/error_handling.md b/axum/src/docs/error_handling.md similarity index 100% rename from src/docs/error_handling.md rename to axum/src/docs/error_handling.md diff --git a/src/docs/extract.md b/axum/src/docs/extract.md similarity index 100% rename from src/docs/extract.md rename to axum/src/docs/extract.md diff --git a/src/docs/handlers_intro.md b/axum/src/docs/handlers_intro.md similarity index 100% rename from src/docs/handlers_intro.md rename to axum/src/docs/handlers_intro.md diff --git a/src/docs/middleware.md b/axum/src/docs/middleware.md similarity index 100% rename from src/docs/middleware.md rename to axum/src/docs/middleware.md diff --git a/src/docs/response.md b/axum/src/docs/response.md similarity index 100% rename from src/docs/response.md rename to axum/src/docs/response.md diff --git a/src/docs/routing/fallback.md b/axum/src/docs/routing/fallback.md similarity index 100% rename from src/docs/routing/fallback.md rename to axum/src/docs/routing/fallback.md diff --git a/src/docs/routing/into_make_service_with_connect_info.md b/axum/src/docs/routing/into_make_service_with_connect_info.md similarity index 100% rename from src/docs/routing/into_make_service_with_connect_info.md rename to axum/src/docs/routing/into_make_service_with_connect_info.md diff --git a/src/docs/routing/layer.md b/axum/src/docs/routing/layer.md similarity index 100% rename from src/docs/routing/layer.md rename to axum/src/docs/routing/layer.md diff --git a/src/docs/routing/merge.md b/axum/src/docs/routing/merge.md similarity index 100% rename from src/docs/routing/merge.md rename to axum/src/docs/routing/merge.md diff --git a/src/docs/routing/nest.md b/axum/src/docs/routing/nest.md similarity index 100% rename from src/docs/routing/nest.md rename to axum/src/docs/routing/nest.md diff --git a/src/docs/routing/route.md b/axum/src/docs/routing/route.md similarity index 100% rename from src/docs/routing/route.md rename to axum/src/docs/routing/route.md diff --git a/src/error.rs b/axum/src/error.rs similarity index 100% rename from src/error.rs rename to axum/src/error.rs diff --git a/src/error_handling/mod.rs b/axum/src/error_handling/mod.rs similarity index 100% rename from src/error_handling/mod.rs rename to axum/src/error_handling/mod.rs diff --git a/src/extract/connect_info.rs b/axum/src/extract/connect_info.rs similarity index 100% rename from src/extract/connect_info.rs rename to axum/src/extract/connect_info.rs diff --git a/src/extract/content_length_limit.rs b/axum/src/extract/content_length_limit.rs similarity index 100% rename from src/extract/content_length_limit.rs rename to axum/src/extract/content_length_limit.rs diff --git a/src/extract/extension.rs b/axum/src/extract/extension.rs similarity index 100% rename from src/extract/extension.rs rename to axum/src/extract/extension.rs diff --git a/src/extract/extractor_middleware.rs b/axum/src/extract/extractor_middleware.rs similarity index 100% rename from src/extract/extractor_middleware.rs rename to axum/src/extract/extractor_middleware.rs diff --git a/src/extract/form.rs b/axum/src/extract/form.rs similarity index 100% rename from src/extract/form.rs rename to axum/src/extract/form.rs diff --git a/src/extract/matched_path.rs b/axum/src/extract/matched_path.rs similarity index 100% rename from src/extract/matched_path.rs rename to axum/src/extract/matched_path.rs diff --git a/src/extract/mod.rs b/axum/src/extract/mod.rs similarity index 100% rename from src/extract/mod.rs rename to axum/src/extract/mod.rs diff --git a/src/extract/multipart.rs b/axum/src/extract/multipart.rs similarity index 100% rename from src/extract/multipart.rs rename to axum/src/extract/multipart.rs diff --git a/src/extract/path/de.rs b/axum/src/extract/path/de.rs similarity index 100% rename from src/extract/path/de.rs rename to axum/src/extract/path/de.rs diff --git a/src/extract/path/mod.rs b/axum/src/extract/path/mod.rs similarity index 100% rename from src/extract/path/mod.rs rename to axum/src/extract/path/mod.rs diff --git a/src/extract/query.rs b/axum/src/extract/query.rs similarity index 100% rename from src/extract/query.rs rename to axum/src/extract/query.rs diff --git a/src/extract/raw_query.rs b/axum/src/extract/raw_query.rs similarity index 100% rename from src/extract/raw_query.rs rename to axum/src/extract/raw_query.rs diff --git a/src/extract/rejection.rs b/axum/src/extract/rejection.rs similarity index 100% rename from src/extract/rejection.rs rename to axum/src/extract/rejection.rs diff --git a/src/extract/request_parts.rs b/axum/src/extract/request_parts.rs similarity index 100% rename from src/extract/request_parts.rs rename to axum/src/extract/request_parts.rs diff --git a/src/extract/tuple.rs b/axum/src/extract/tuple.rs similarity index 100% rename from src/extract/tuple.rs rename to axum/src/extract/tuple.rs diff --git a/src/extract/typed_header.rs b/axum/src/extract/typed_header.rs similarity index 100% rename from src/extract/typed_header.rs rename to axum/src/extract/typed_header.rs diff --git a/src/extract/ws.rs b/axum/src/extract/ws.rs similarity index 100% rename from src/extract/ws.rs rename to axum/src/extract/ws.rs diff --git a/src/handler/future.rs b/axum/src/handler/future.rs similarity index 100% rename from src/handler/future.rs rename to axum/src/handler/future.rs diff --git a/src/handler/into_service.rs b/axum/src/handler/into_service.rs similarity index 100% rename from src/handler/into_service.rs rename to axum/src/handler/into_service.rs diff --git a/src/handler/mod.rs b/axum/src/handler/mod.rs similarity index 100% rename from src/handler/mod.rs rename to axum/src/handler/mod.rs diff --git a/src/json.rs b/axum/src/json.rs similarity index 100% rename from src/json.rs rename to axum/src/json.rs diff --git a/src/lib.rs b/axum/src/lib.rs similarity index 100% rename from src/lib.rs rename to axum/src/lib.rs diff --git a/src/macros.rs b/axum/src/macros.rs similarity index 100% rename from src/macros.rs rename to axum/src/macros.rs diff --git a/src/response/headers.rs b/axum/src/response/headers.rs similarity index 100% rename from src/response/headers.rs rename to axum/src/response/headers.rs diff --git a/src/response/mod.rs b/axum/src/response/mod.rs similarity index 100% rename from src/response/mod.rs rename to axum/src/response/mod.rs diff --git a/src/response/redirect.rs b/axum/src/response/redirect.rs similarity index 100% rename from src/response/redirect.rs rename to axum/src/response/redirect.rs diff --git a/src/response/sse.rs b/axum/src/response/sse.rs similarity index 100% rename from src/response/sse.rs rename to axum/src/response/sse.rs diff --git a/src/routing/future.rs b/axum/src/routing/future.rs similarity index 100% rename from src/routing/future.rs rename to axum/src/routing/future.rs diff --git a/src/routing/handler_method_routing.rs b/axum/src/routing/handler_method_routing.rs similarity index 100% rename from src/routing/handler_method_routing.rs rename to axum/src/routing/handler_method_routing.rs diff --git a/src/routing/into_make_service.rs b/axum/src/routing/into_make_service.rs similarity index 100% rename from src/routing/into_make_service.rs rename to axum/src/routing/into_make_service.rs diff --git a/src/routing/method_filter.rs b/axum/src/routing/method_filter.rs similarity index 100% rename from src/routing/method_filter.rs rename to axum/src/routing/method_filter.rs diff --git a/src/routing/method_not_allowed.rs b/axum/src/routing/method_not_allowed.rs similarity index 100% rename from src/routing/method_not_allowed.rs rename to axum/src/routing/method_not_allowed.rs diff --git a/src/routing/mod.rs b/axum/src/routing/mod.rs similarity index 100% rename from src/routing/mod.rs rename to axum/src/routing/mod.rs diff --git a/src/routing/not_found.rs b/axum/src/routing/not_found.rs similarity index 100% rename from src/routing/not_found.rs rename to axum/src/routing/not_found.rs diff --git a/src/routing/route.rs b/axum/src/routing/route.rs similarity index 100% rename from src/routing/route.rs rename to axum/src/routing/route.rs diff --git a/src/routing/service_method_routing.rs b/axum/src/routing/service_method_routing.rs similarity index 100% rename from src/routing/service_method_routing.rs rename to axum/src/routing/service_method_routing.rs diff --git a/src/routing/strip_prefix.rs b/axum/src/routing/strip_prefix.rs similarity index 100% rename from src/routing/strip_prefix.rs rename to axum/src/routing/strip_prefix.rs diff --git a/src/routing/tests/fallback.rs b/axum/src/routing/tests/fallback.rs similarity index 100% rename from src/routing/tests/fallback.rs rename to axum/src/routing/tests/fallback.rs diff --git a/src/routing/tests/get_to_head.rs b/axum/src/routing/tests/get_to_head.rs similarity index 100% rename from src/routing/tests/get_to_head.rs rename to axum/src/routing/tests/get_to_head.rs diff --git a/src/routing/tests/handle_error.rs b/axum/src/routing/tests/handle_error.rs similarity index 100% rename from src/routing/tests/handle_error.rs rename to axum/src/routing/tests/handle_error.rs diff --git a/src/routing/tests/merge.rs b/axum/src/routing/tests/merge.rs similarity index 100% rename from src/routing/tests/merge.rs rename to axum/src/routing/tests/merge.rs diff --git a/src/routing/tests/mod.rs b/axum/src/routing/tests/mod.rs similarity index 100% rename from src/routing/tests/mod.rs rename to axum/src/routing/tests/mod.rs diff --git a/src/routing/tests/nest.rs b/axum/src/routing/tests/nest.rs similarity index 100% rename from src/routing/tests/nest.rs rename to axum/src/routing/tests/nest.rs diff --git a/src/test_helpers.rs b/axum/src/test_helpers.rs similarity index 100% rename from src/test_helpers.rs rename to axum/src/test_helpers.rs diff --git a/src/util.rs b/axum/src/util.rs similarity index 100% rename from src/util.rs rename to axum/src/util.rs diff --git a/examples/async-graphql/Cargo.toml b/examples/async-graphql/Cargo.toml index f652ece3..cc95ba6f 100644 --- a/examples/async-graphql/Cargo.toml +++ b/examples/async-graphql/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../.." } +axum = { path = "../../axum" } tokio = { version = "1.0", features = ["full"] } tracing = "0.1" tracing-subscriber = "0.2" diff --git a/examples/chat/Cargo.toml b/examples/chat/Cargo.toml index caac5502..cf743ffa 100644 --- a/examples/chat/Cargo.toml +++ b/examples/chat/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../..", features = ["ws"] } +axum = { path = "../../axum", features = ["ws"] } futures = "0.3" tokio = { version = "1", features = ["full"] } tower = { version = "0.4", features = ["util"] } diff --git a/examples/customize-extractor-error/Cargo.toml b/examples/customize-extractor-error/Cargo.toml index 7b558431..f624c5cc 100644 --- a/examples/customize-extractor-error/Cargo.toml +++ b/examples/customize-extractor-error/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../.." } +axum = { path = "../../axum" } tokio = { version = "1.0", features = ["full"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/examples/error-handling-and-dependency-injection/Cargo.toml b/examples/error-handling-and-dependency-injection/Cargo.toml index 2e4aba38..a2632cd0 100644 --- a/examples/error-handling-and-dependency-injection/Cargo.toml +++ b/examples/error-handling-and-dependency-injection/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../.." } +axum = { path = "../../axum" } tokio = { version = "1.0", features = ["full"] } tower = { version = "0.4", features = ["util"] } tracing = "0.1" diff --git a/examples/form/Cargo.toml b/examples/form/Cargo.toml index bb59f213..d2148a0d 100644 --- a/examples/form/Cargo.toml +++ b/examples/form/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../.." } +axum = { path = "../../axum" } tokio = { version = "1.0", features = ["full"] } tracing = "0.1" tracing-subscriber = "0.2" diff --git a/examples/global-404-handler/Cargo.toml b/examples/global-404-handler/Cargo.toml index d4165388..8892180a 100644 --- a/examples/global-404-handler/Cargo.toml +++ b/examples/global-404-handler/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../.." } +axum = { path = "../../axum" } tokio = { version = "1.0", features = ["full"] } tower = { version = "0.4", features = ["util"] } tracing = "0.1" diff --git a/examples/graceful_shutdown/Cargo.toml b/examples/graceful_shutdown/Cargo.toml index ddb9a4d2..87163dc0 100644 --- a/examples/graceful_shutdown/Cargo.toml +++ b/examples/graceful_shutdown/Cargo.toml @@ -5,5 +5,5 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../.." } +axum = { path = "../../axum" } tokio = { version = "1.0", features = ["full"] } diff --git a/examples/hello-world/Cargo.toml b/examples/hello-world/Cargo.toml index ab8f44dd..36b5dfc6 100644 --- a/examples/hello-world/Cargo.toml +++ b/examples/hello-world/Cargo.toml @@ -5,5 +5,5 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../.." } +axum = { path = "../../axum" } tokio = { version = "1.0", features = ["full"] } diff --git a/examples/http-proxy/Cargo.toml b/examples/http-proxy/Cargo.toml index 833068df..ed22e520 100644 --- a/examples/http-proxy/Cargo.toml +++ b/examples/http-proxy/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../.." } +axum = { path = "../../axum" } tokio = { version = "1.0", features = ["full"] } hyper = { version = "0.14", features = ["full"] } tower = { version = "0.4", features = ["make"] } diff --git a/examples/jwt/Cargo.toml b/examples/jwt/Cargo.toml index 201ead4b..a0770dea 100644 --- a/examples/jwt/Cargo.toml +++ b/examples/jwt/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../..", features = ["headers"] } +axum = { path = "../../axum", features = ["headers"] } tokio = { version = "1.0", features = ["full"] } tracing = "0.1" tracing-subscriber = "0.2" diff --git a/examples/key-value-store/Cargo.toml b/examples/key-value-store/Cargo.toml index 0f936de5..4aa6dc70 100644 --- a/examples/key-value-store/Cargo.toml +++ b/examples/key-value-store/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../.." } +axum = { path = "../../axum" } tokio = { version = "1.0", features = ["full"] } tracing = "0.1" tracing-subscriber = "0.2" diff --git a/examples/low-level-rustls/Cargo.toml b/examples/low-level-rustls/Cargo.toml index b9650cfa..7597d71f 100644 --- a/examples/low-level-rustls/Cargo.toml +++ b/examples/low-level-rustls/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../.." } +axum = { path = "../../axum" } hyper = { version = "0.14", features = ["full"] } tokio = { version = "1", features = ["full"] } tokio-rustls = "0.22" diff --git a/examples/multipart-form/Cargo.toml b/examples/multipart-form/Cargo.toml index 5716047d..870ddd6d 100644 --- a/examples/multipart-form/Cargo.toml +++ b/examples/multipart-form/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../..", features = ["multipart"] } +axum = { path = "../../axum", features = ["multipart"] } tokio = { version = "1.0", features = ["full"] } tracing = "0.1" tracing-subscriber = "0.2" diff --git a/examples/oauth/Cargo.toml b/examples/oauth/Cargo.toml index 44e68cd4..f8818e26 100644 --- a/examples/oauth/Cargo.toml +++ b/examples/oauth/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../..", features = ["headers"] } +axum = { path = "../../axum", features = ["headers"] } tokio = { version = "1.0", features = ["full"] } tracing = "0.1" tracing-subscriber = "0.2" diff --git a/examples/print-request-response/Cargo.toml b/examples/print-request-response/Cargo.toml index 8a7f5b59..31dc4bd9 100644 --- a/examples/print-request-response/Cargo.toml +++ b/examples/print-request-response/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../.." } +axum = { path = "../../axum" } tokio = { version = "1.0", features = ["full"] } tracing = "0.1" tracing-subscriber = "0.2" diff --git a/examples/query-params-with-empty-strings/Cargo.toml b/examples/query-params-with-empty-strings/Cargo.toml index ffed6f87..5b360a29 100644 --- a/examples/query-params-with-empty-strings/Cargo.toml +++ b/examples/query-params-with-empty-strings/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../.." } +axum = { path = "../../axum" } tokio = { version = "1.0", features = ["full"] } serde = { version = "1.0", features = ["derive"] } tower = { version = "0.4", features = ["util"] } diff --git a/examples/readme/Cargo.toml b/examples/readme/Cargo.toml index 0fe437b3..84f3c977 100644 --- a/examples/readme/Cargo.toml +++ b/examples/readme/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../.." } +axum = { path = "../../axum" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.68" tokio = { version = "1.0", features = ["full"] } diff --git a/examples/reverse-proxy/Cargo.toml b/examples/reverse-proxy/Cargo.toml index 4a13668f..2d081ab1 100644 --- a/examples/reverse-proxy/Cargo.toml +++ b/examples/reverse-proxy/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2018" [dependencies] -axum = { path = "../.." } +axum = { path = "../../axum" } hyper = { version = "0.14", features = ["full"] } tokio = { version = "1", features = ["full"] } tracing = "0.1" diff --git a/examples/sessions/Cargo.toml b/examples/sessions/Cargo.toml index 967306a4..57402619 100644 --- a/examples/sessions/Cargo.toml +++ b/examples/sessions/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../.." } +axum = { path = "../../axum" } tokio = { version = "1.0", features = ["full"] } tracing = "0.1" tracing-subscriber = "0.2" diff --git a/examples/sse/Cargo.toml b/examples/sse/Cargo.toml index 48c0996d..136ff85f 100644 --- a/examples/sse/Cargo.toml +++ b/examples/sse/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../..", features = ["headers"] } +axum = { path = "../../axum", features = ["headers"] } tokio = { version = "1.0", features = ["full"] } tracing = "0.1" tracing-subscriber = "0.2" diff --git a/examples/static-file-server/Cargo.toml b/examples/static-file-server/Cargo.toml index b9175002..a564248f 100644 --- a/examples/static-file-server/Cargo.toml +++ b/examples/static-file-server/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../.." } +axum = { path = "../../axum" } tokio = { version = "1.0", features = ["full"] } tracing = "0.1" tracing-subscriber = "0.2" diff --git a/examples/templates/Cargo.toml b/examples/templates/Cargo.toml index 332faaef..db1e7b92 100644 --- a/examples/templates/Cargo.toml +++ b/examples/templates/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../.." } +axum = { path = "../../axum" } tokio = { version = "1.0", features = ["full"] } tracing = "0.1" tracing-subscriber = "0.2" diff --git a/examples/testing/Cargo.toml b/examples/testing/Cargo.toml index 7ed1a252..e066f03d 100644 --- a/examples/testing/Cargo.toml +++ b/examples/testing/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../.." } +axum = { path = "../../axum" } tokio = { version = "1.0", features = ["full"] } tracing = "0.1" tracing-subscriber = "0.2" diff --git a/examples/tls-rustls/Cargo.toml b/examples/tls-rustls/Cargo.toml index 2b97ed83..bfd88a05 100644 --- a/examples/tls-rustls/Cargo.toml +++ b/examples/tls-rustls/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../.." } +axum = { path = "../../axum" } axum-server = { version = "0.2", features = ["tls-rustls"] } tokio = { version = "1", features = ["full"] } tracing = "0.1" diff --git a/examples/todos/Cargo.toml b/examples/todos/Cargo.toml index c12acae9..1fd74546 100644 --- a/examples/todos/Cargo.toml +++ b/examples/todos/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../.." } +axum = { path = "../../axum" } tokio = { version = "1.0", features = ["full"] } tracing = "0.1" tracing-subscriber = "0.2" diff --git a/examples/tokio-postgres/Cargo.toml b/examples/tokio-postgres/Cargo.toml index b70476e9..18c6aed8 100644 --- a/examples/tokio-postgres/Cargo.toml +++ b/examples/tokio-postgres/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../.." } +axum = { path = "../../axum" } tokio = { version = "1.0", features = ["full"] } tracing = "0.1" tracing-subscriber = "0.2" diff --git a/examples/tracing-aka-logging/Cargo.toml b/examples/tracing-aka-logging/Cargo.toml index b2811c0f..1949bced 100644 --- a/examples/tracing-aka-logging/Cargo.toml +++ b/examples/tracing-aka-logging/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../.." } +axum = { path = "../../axum" } tokio = { version = "1.0", features = ["full"] } tracing = "0.1" tracing-subscriber = "0.2" diff --git a/examples/unix-domain-socket/Cargo.toml b/examples/unix-domain-socket/Cargo.toml index 45efd623..11d17f8c 100644 --- a/examples/unix-domain-socket/Cargo.toml +++ b/examples/unix-domain-socket/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../.." } +axum = { path = "../../axum" } tokio = { version = "1.0", features = ["full"] } tracing = "0.1" tracing-subscriber = "0.2" diff --git a/examples/validator/Cargo.toml b/examples/validator/Cargo.toml index 4f989f5c..13b4b313 100644 --- a/examples/validator/Cargo.toml +++ b/examples/validator/Cargo.toml @@ -6,7 +6,7 @@ version = "0.1.0" [dependencies] async-trait = "0.1" -axum = { path = "../.." } +axum = { path = "../../axum" } http-body = "0.4.3" serde = { version = "1.0", features = ["derive"] } thiserror = "1.0.29" diff --git a/examples/versioning/Cargo.toml b/examples/versioning/Cargo.toml index 389416d3..317f7eee 100644 --- a/examples/versioning/Cargo.toml +++ b/examples/versioning/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../.." } +axum = { path = "../../axum" } tokio = { version = "1.0", features = ["full"] } tracing = "0.1" tracing-subscriber = "0.2" diff --git a/examples/websockets/Cargo.toml b/examples/websockets/Cargo.toml index 08f51e4d..00907815 100644 --- a/examples/websockets/Cargo.toml +++ b/examples/websockets/Cargo.toml @@ -5,7 +5,7 @@ edition = "2018" publish = false [dependencies] -axum = { path = "../..", features = ["ws", "headers"] } +axum = { path = "../../axum", features = ["ws", "headers"] } tokio = { version = "1.0", features = ["full"] } tracing = "0.1" tracing-subscriber = "0.2"