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"