Commit graph

443 commits

Author SHA1 Message Date
David Pedersen
ba4d8a2357
Move axum crate into workspace subfolder (#458)
* Move axum crate into workspace subfolder

Over time I imagine we're gonna have other crates in this repo that
provide utilities or integrations for axum. This prepares for that by
moving the main axum crate into its own folder.

The README situation is a bit annoying because we want `./README.md`
for viewing the repo on github but `axum/README.md` for crates.io. For
now I've just copy/pasted it and added CI step to make sure they're
identical.

* update changelog link

* Add licenses to all examples

* is this how you install `diff`?

* or maybe this is how?

* fix readme links

* like this?

* fix cargo-deny step

* Try making root readme a symlink

* remove compare readme step

not needed since readme in repo root is now a symlink

* Revert "Add licenses to all examples"

This reverts commit ab321b7fb9.
2021-11-03 12:38:48 +01:00
David Pedersen
b60bfd7f34 Mention "axum-typed-websockets" in community ecosystem 2021-11-03 10:26:20 +01:00
David Pedersen
0f1f28062d
Reorganize tests (#456)
* Reorganize tests

This breaks up the large `crate::tests` module by moving some of the
tests into a place that makes more sense. For example tests of JSON
serialization are moved to the `crate::json` module. The remaining routing
tests have been moved to `crate::routing::tests`.

I generally prefer having tests close to the code they're testing. Makes
it easier to see how/if something is tested.

* Try pinning to older version of async-graphql

* Revert "Try pinning to older version of async-graphql"

This reverts commit 2e2cae7d12f5e433a16d6607497d587863f04384.

* don't test examples on 1.54 on CI

* move ci steps around a bit
2021-11-03 10:22:31 +01:00
David Pedersen
420918a53a Clarify change to handling multiple HTTP methods 2021-11-03 09:58:59 +01:00
arctic-alpaca
a442920ba3
Restructure community showcase (#454) 2021-11-03 09:20:01 +01:00
David Pedersen
5367bc65d1 Fix typo 2021-11-03 08:26:13 +01:00
David Pedersen
708988bfae Fix readme example link 2021-11-03 08:25:31 +01:00
Jordan Gould
1c60255b9f
Add readme example project (#450)
* Add project based on the readme example

* Add readme project link to README.md

* Typo correction

* Update examples/readme-example/Cargo.toml

Use tracing-subscriber 0.2 to match other the other examples

Co-authored-by: David Pedersen <david.pdrsn@gmail.com>

* Update README.md

Use original readme phrasing for crate docs

Co-authored-by: David Pedersen <david.pdrsn@gmail.com>

* Rename readme-exmaple to readme

* Revert tracing call to debug from info

Co-authored-by: Jordan Gould <jordan@tineye.com>
Co-authored-by: David Pedersen <david.pdrsn@gmail.com>
2021-11-03 07:23:28 +00:00
Jonas Platte
2ba9cdce45
Fix typos in CHANGELOG.md (#449) 2021-11-02 20:12:27 +00:00
David Pedersen
baefa47634 0.3.0 is out! 2021-11-02 18:41:29 +01:00
David Pedersen
35dba50b32 Fix typo in changelog 2021-11-02 18:40:57 +01:00
David Pedersen
85731a4f1d
Version 0.3.0 (#448)
- 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. Its 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 support rust version is not 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 increase.
  - **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 trailing a slash.
  - **breaking:** Method routing for handlers have been moved from `axum::handler`
    to `axum::routing`. So `axum::handler::get` now lives at `axum::routing::get`
    ([#405])
  - **breaking:** Method routing for services have been moved from `axum::service`
    to `axum::routing`. So `axum::service::get` now lives at, etc.
    `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 its 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<Body>| async {
                let contents = tokio::fs::read_to_string("some_file").await?;
                Ok::<_, io::Error>(Response::new(Body::from(contents)))
            }))
            .handle_error(handle_io_error),
        );

    fn handle_io_error(error: io::Error) -> impl IntoResponse {
        // ...
    }
    ```
- Misc:
  - `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
2021-11-02 18:14:41 +01:00
David Pedersen
394d4b14f6 Mention handling extractor failures in error handling docs 2021-11-02 18:02:09 +01:00
David Pedersen
2957f48ace Mention MSRV bump in changelog 2021-11-02 17:58:21 +01:00
David Pedersen
6b69368895 Small changelog fixes 2021-11-02 17:55:42 +01:00
David Pedersen
9512d14c99
Add Handler::{into_make_service, into_make_service_with_connect_info} (#444)
* Make `IntoMakeService(WithConnectInfo)?` work with any Service

* Add `Handler::{into_make_service, into_make_service_with_connect_info}`

These are useful if you want to run a handler without a `Router`, for
example to make a proxy.
2021-11-02 17:11:18 +01:00
David Pedersen
98907b8887
Add example showing how to handle empty vs missing query params (#443) 2021-11-02 14:42:47 +01:00
David Pedersen
a048d6443b Revert hello-world example
Was accidentally changed in another PR
2021-11-02 13:07:49 +01:00
Michael Grigoryan
5e44295a82
Fix typo in CHANGELOG (#442) 2021-11-02 07:50:10 +01:00
David Pedersen
1b98328dc8
Clean up some todos (#441) 2021-11-01 22:36:17 +00:00
David Pedersen
3d07d40e02
Remove Sync requirement from response bodies (#440)
As we learned [in Tonic] bodies don't need to be `Sync` because they can
only be polled from one thread at a time.

This changes axum's bodies to no longer require `Sync` and makes
`BoxBody` an alias for `UnsyncBoxBody<Bytes, axum::Error>`.

[in Tonic]: https://github.com/hyperium/tonic/issues/117
2021-11-01 22:37:16 +01:00
David Pedersen
9465128f3e
Rework docs (#437)
This reworks axum's docs in an attempt to make things easier to find. Previously I wasn't a fan of those docs for the same topic were spread across the root module docs and more specific places like types and methods.

This changes it such that the root module docs only gives a high level introduction to a topic, perhaps with a small example, and then link to other places where all the details are. This means `Router` is now the single place to learn about routing, and etc for the topics like handlers and error handling.
2021-11-01 21:13:37 +00:00
David Pedersen
1c6038c09f
Depend on tower 0.4.10 (#439)
axum uses `impl Layer for ServiceBuilder` internally which requires
tower 0.4.10. Making that explicit should help users updating to axum
0.3 without also having to manually bump their tower dependency.
2021-11-01 13:15:34 +00:00
David Pedersen
2b8494a576
Make MethodNotAllowed public (#436)
Not sure why this wasn't caught by `#![deny(unreachable_pub, private_in_public)]`
2021-10-31 20:57:32 +01:00
David Pedersen
857ecd7314
Break root module docs into separate files (#432)
For 0.3 I'm thinking about some changes I wanna make to the docs. I
don't like how information is currently spread over so many places.
Still thinking about how I wanna re-organize it.

However I do think it makes sense to break the root module docs into
separate files that get included with `#![doc = include_str!("file")]`.
Makes working on a single section easier and more focused. It looks the
same for the user reading the docs.

This means axum's MSRV is now 1.54 but since thats two releases ago I'm
fine with that.
2021-10-31 20:37:56 +01:00
Paul Butler
9145c0e396
Add notify.run to community showcase (#435) 2021-10-31 08:22:46 +01:00
david-perez
be62f49b7e
Fix typo in sealed trait used in Handler (#430) 2021-10-28 16:44:04 +00:00
david-perez
21e5b654ab
Fix NotFound docs (#431) 2021-10-28 16:41:52 +00:00
David Pedersen
2d1635a6d7
Fix sse and ws examples (#429)
* Fix sse example

* Fix websockets example
2021-10-27 15:52:41 +00:00
David Pedersen
a3822cb175 Add test for wildcards with trailing slashes
Its already working, just to make sure we don't regress in the future
2021-10-27 09:32:14 +02:00
David Pedersen
a2627e9084
Remove support for CONNECT (#428)
Given how different `CONNECT` requests are I think its fine to require
users to handle them manually. Since they don't contain paths you
probably don't need a full routing framework 🤷

An example can be found [here](https://github.com/tokio-rs/axum/blob/main/examples/http-proxy/src/main.rs)

Fixes #418
2021-10-26 21:11:33 +00:00
David Pedersen
94330b7796
Panic if routing to router (#427)
This panics if you pass a `Router` to `Router::route`. Thats invalid and
will result in unreachable routes.

Unfortunately I don't think we can make it a type error while supporting
general `Service`s. So I think this is a decent workaround.

Fixes https://github.com/tokio-rs/axum/issues/174
2021-10-26 20:44:16 +00:00
David Pedersen
92f96a201c
Implement nesting as regular wildcard routes (#426)
When fixing bugs with `MatchedPath` (introduced to fix https://github.com/tokio-rs/axum/issues/386) I realized nesting could basically be implemented using regular routes, if we can detect that the service passed to `nest` is in fact a `Router`. Then we can transfer over all its routes and add the prefix.

This makes nesting much simpler in general and should also be slightly faster since we're no longer nesting routers.
2021-10-26 20:31:22 +00:00
David Pedersen
fc9bfb8a50
Add HTTP proxy example (#425) 2021-10-26 20:46:40 +02:00
David Pedersen
302a720271
Breakup routing module (#424)
The routing module had gotten quite hard to navigate so this breaks it
into smaller modules. No user facing changes.
2021-10-26 17:51:22 +00:00
David Pedersen
91981db8c7
Fix middleware not seeing the full URI for nested routes (#423)
We stripped the prefix before calling any middleware. Instead the prefix
should be stripped just before calling the actual route. This way
middleware still see the full URI, as it used to work in 0.2.

Fixes #419
2021-10-26 19:29:59 +02:00
David Pedersen
8fe4eaf1d5
Run middleware for requests with no matching route (#422)
While thinking about #419 I realized that `main` had a bug where
middleware wouldn't be called if no route matched the incoming request.
`Router` would just directly return a 404 without calling any
middleware.

This fixes by making the fallback default to a service that always
returns 404 and always calling that if no route matches.

Layers applied to the router is then also applied to the fallback.

Unfortunately this breaks #380 but I don't currently see a way to
support both. Auth middleware need to run _after_ routing because you
don't care about auth for unknown paths, but logging middleware need to
run _before_ routing because they do care about seeing requests for
unknown paths so they can log them...

Part of #419
2021-10-26 18:39:05 +02:00
David Pedersen
e9533c566f
Don't allow empty paths (#421) 2021-10-26 15:37:25 +00:00
David Pedersen
9b17d86b92
Update to matchit 0.4.4 (#417)
- Static vs dynamic paths are now supported meaning `/foo` and `/:key`
  are not considered to overlap.
- A bug we hit regarding trailing slashes is fixed.
2021-10-25 23:35:33 +00:00
David Pedersen
efdd197643 More consistent poll_ready usage
The `#[inline]`s probably aren't necessary but are consistent with other
parts of the code and tower in general.
2021-10-26 01:24:57 +02:00
David Pedersen
e949c47df6
Fix inconsistent naming of WebSocket rejections (#416) 2021-10-25 23:09:47 +00:00
David Pedersen
040f63b8e2
Clean up constructors for future newtypes (#415) 2021-10-25 23:03:16 +00:00
David Pedersen
68e44fa9da
Vendor AddExtensionLayer and AddExtension (#414)
This remove tower-http from axum's public API. I would like to be able
to make breaking releases of tower-http without also having to ship a
breaking release of axum.
2021-10-25 22:08:59 +00:00
David Pedersen
0a3f69af0d
Reorganize changelog (#413)
* Reorganize changelog

When it starts growing this big I think grouping it into topics is nice.

* misc fixes
2021-10-25 23:52:22 +02:00
David Pedersen
02a035fb14
Add MatchedPath extractor (#412)
Fixes #386
2021-10-25 21:38:29 +00:00
David Pedersen
e43bdf0ecf
Rename EmptyRouter to MethodNotAllowed (#411)
It is no longer needed in `Router` so can be changed to always return
`403 Method Not Allowed`.
2021-10-25 23:28:22 +02:00
David Pedersen
59819e42bf
Correctly handle trailing slashes in routes (#410) 2021-10-25 20:42:49 +00:00
David Pedersen
baf7cabfe1
Add test for middleware that return early (#409)
* Add test for middleware that return early

Turns out #408 fixed #380.

* changelog
2021-10-25 19:46:49 +00:00
David Pedersen
85f5511313 Small routing cleanup
Storing the paths like this should be slightly more efficient.
2021-10-25 21:30:35 +02:00
David Pedersen
3626facbda Update changelog 2021-10-25 20:51:07 +02:00