With https://github.com/tokio-rs/axum/pull/404 and https://github.com/tokio-rs/axum/pull/402 all routes now have the same types and thus we don't need to nest them but can instead store them all in a map. This simplifies the routing quite a bit and is faster as well.
High level changes:
- Routes are now stored in a `HashMap<RouteId, Route<B>>`.
- `Router::or` is renamed to `Router::merge` because thats what it does now. It copies all routes from one router to another. This also means overlapping routes will cause a panic which is nice win.
- `Router::merge` now only accepts `Router`s so added `Router::fallback` for adding a global 404 handler.
- The `Or` service has been removed.
- `Router::layer` now only adds layers to the routes you actually have meaning middleware runs _after_ routing. I believe that addresses https://github.com/tokio-rs/axum/issues/380 but will test that on another branch.
In #363 I added `MaybeSharedNode` which makes `Router` faster to clone
_if_ you're using `into_make_service`. However I would like instead like
to find a solution that works even when you're not using
`into_make_service`.
Using an `Arc<RwLock<Node<_>>>` is probably the only solution but would
like to experiment. For now I'm gonna rollback `MaybeSharedNode`.
Changing it wont require user facing changes.
* "matchit" based router
* Update changelog
* Remove dependency on `regex`
* Docs
* Fix typos
* Also mention route order in root module docs
* Update CHANGELOG.md
Co-authored-by: Jonas Platte <jplatte@users.noreply.github.com>
* Document that `/:key` and `/foo` overlaps
* Provide good error message for wildcards in routes
* minor clean ups
* Make `Router` cheaper to clone
* Ensure middleware still only applies to routes above
* Remove call to issues from changelog
We're aware of the short coming :)
* Fix tests on 1.51
Co-authored-by: Jonas Platte <jplatte@users.noreply.github.com>
I've been thinking that having an associated type probably isn't
necessary. I imagine most users are either using `SocketAddr` to the
remote connection IP, or writing their own connection struct.
* Expand accepted content types for JSON requests
Fixes https://github.com/tokio-rs/axum/issues/375
* changelog
* add test for content type without spaces
* Don't accept `text/json`
* small clean up
* Document debugging handler type errors with "axum-debug"
* Apply suggestions from code review
Co-authored-by: Jonas Platte <jplatte@users.noreply.github.com>
Co-authored-by: Jonas Platte <jplatte@users.noreply.github.com>
* Percent decode automatically in `extract::Path`
Fixes https://github.com/tokio-rs/axum/issues/261
* return an error if path param contains invalid utf-8
* Mention automatic decoding in the docs
* Update changelog: This is a breaking change
* cleanup
* fix tests
* Improve performance of `BoxRoute`
This is based on #315 but slightly shorter.
It removes the need for a `tower::buffer::Buffer` in `BoxRoute` which
improves performance.
* changelog
Co-authored-by: Programatik <programatik29@gmail.com>
This changes the test setup to use our own client rather than using
reqwest directly. Allows us to add several quality of life features like
always unwrapping results.
* Improve extractor docs
- Moves things from the `extract` module docs to the root module docs to
make them more discoverable
- Adds section showing commonly used extractors
- More clarity around multiple extractors that mutate the request
* english...
Boxing a service normally means using `tower::util::BoxService`. That
doesn't implement `Clone` however so normally I had been combining it
with `Buffer` to get that.
But recently I discovered https://github.com/dtolnay/dyn-clone which
makes it possible to clone trait objects. So this adds a new internal
utility called `CloneBoxService` which replaces the previous
`BoxService` + `Buffer` combo in `BoxRoute`.
I'll investigate upstreaming that to tower. I think it makes sense there
since box + clone is quite a common need.
I just had a thought: Why should `response::Headers` be generic, but
`body::StreamBody` should not? `StreamBody` previously boxed the stream
to erase the generics. So we had `response::Headers<T>` but
`body::StreamBody`, without generics.
After thinking about it I think it actually makes sense for responses to
remain generic because you're able to use `impl IntoResponse` so you
don't have to name the generics.
Whereas in the case of `BodyStream` (an extractor) you cannot use `impl Trait`
so it makes sense to box the inner body to make the type easier to name. Besides,
`BodyStream` is mostly useful when the request body isn't `hyper::Body`, as
that already implements `Stream`.
This adds `StreamBody` which converts a `Stream` of `Bytes` into a `http_body::Body`.
---
As suggested by Kestrer on Discord it would make sense for axum to provide different kinds of body types other than `Empty`, `Full`, and `hyper::Body`. There is also some talk about [splitting up `hyper::Body`](https://github.com/hyperium/hyper/issues/2345) so this can be seen as getting started on that effort. axum's body types could be moved to hyper or http-body if thats the direction we decide on.
The types I'm thinking about adding are:
- `StreamBody`- added in this PR
- `AsyncReadBody` - similar to [http-body#41](https://github.com/hyperium/http-body/pull/41/files)
- `ChannelBody` - similar to `hyper::Body::channel`
I think `BodyStream` is more useful without being generic over the
request body.
I'm also looking into adding a response body from a stream called
`StreamBody` which will work pretty much opposite to this.
I haven't been able to find a proper solution for #89 so for now I think
we should document the issue and move on with shipping 0.2.
Part of https://github.com/tokio-rs/axum/issues/89