Update all dependencies #9

Merged
kjuulh merged 1 commits from renovate/all into main 2022-12-18 12:41:01 +01:00
Owner

This PR contains the following updates:

Package Type Update Change
anyhow dependencies patch 1.0.66 -> 1.0.67
axum dependencies minor 0.5 -> 0.6
serde_json dependencies patch 1.0.89 -> 1.0.90
tokio (source) dependencies minor 1.22 -> 1.23

Release Notes

dtolnay/anyhow

v1.0.67

Compare Source

  • Improve the backtrace captured when context() is used on an Option (#​280)
tokio-rs/axum

v0.6.1: axum - v0.6.1

Compare Source

  • added: Expand the docs for Router::with_state (#​1580)

v0.6.0: axum - v0.6.0

Compare Source

Routing

  • fixed: Nested routers are now allowed to have fallbacks (#​1521):

    let api_router = Router::new()
        .route("/users", get(|| { ... }))
        .fallback(api_fallback);
    
    let app = Router::new()
        // this would panic in 0.5 but in 0.6 it just works
        //
        // requests starting with `/api` but not handled by `api_router`
        // will go to `/api_fallback`
        .nest("/api", api_router);
    

    The outer router's fallback will still apply if a nested router doesn't have
    its own fallback:

    // this time without a fallback
    let api_router = Router::new().route("/users", get(|| { ... }));
    
    let app = Router::new()
        .nest("/api", api_router)
        // `api_fallback` will inherit this fallback
        .fallback(app_fallback);
    
  • breaking: The request /foo/ no longer matches /foo/*rest. If you want
    to match /foo/ you have to add a route specifically for that (#​1086)

    For example:

    use axum::{Router, routing::get, extract::Path};
    
    let app = Router::new()
        // this will match `/foo/bar/baz`
        .route("/foo/*rest", get(handler))
        // this will match `/foo/`
        .route("/foo/", get(handler))
        // if you want `/foo` to match you must also add an explicit route for it
        .route("/foo", get(handler));
    
    async fn handler(
        // use an `Option` because `/foo/` and `/foo` don't have any path params
        params: Option<Path<String>>,
    ) {}
    
  • breaking: Path params for wildcard routes no longer include the prefix
    /. e.g. /foo.js will match /*filepath with a value of foo.js, not
    /foo.js (#​1086)

    For example:

    use axum::{Router, routing::get, extract::Path};
    
    let app = Router::new().route("/foo/*rest", get(handler));
    
    async fn handler(
        Path(params): Path<String>,
    ) {
        // for the request `/foo/bar/baz` the value of `params` will be `bar/baz`
        //
        // on 0.5 it would be `/bar/baz`
    }
    
  • fixed: Routes like /foo and /*rest are no longer considered
    overlapping. /foo will take priority (#​1086)

    For example:

    use axum::{Router, routing::get};
    
    let app = Router::new()
        // this used to not be allowed but now just works
        .route("/foo/*rest", get(foo))
        .route("/foo/bar", get(bar));
    
    async fn foo() {}
    
    async fn bar() {}
    
  • breaking: Automatic trailing slash redirects have been removed.
    Previously if you added a route for /foo, axum would redirect calls to
    /foo/ to /foo (or vice versa for /foo/):

    use axum::{Router, routing::get};
    
    let app = Router::new()
        // a request to `GET /foo/` will now get `404 Not Found`
        // whereas in 0.5 axum would redirect to `/foo`
        //
        // same goes the other way if you had the route `/foo/`
        // axum will no longer redirect from `/foo` to `/foo/`
        .route("/foo", get(handler));
    
    async fn handler() {}
    

    Either explicitly add routes for /foo and /foo/ or use
    axum_extra::routing::RouterExt::route_with_tsr if you want the old behavior
    (#​1119)

  • breaking: Router::fallback now only accepts Handlers (similarly to
    what get, post, etc. accept). Use the new Router::fallback_service for
    setting any Service as the fallback (#​1155)

    This fallback on 0.5:

    use axum::{Router, handler::Handler};
    
    let app = Router::new().fallback(fallback.into_service());
    
    async fn fallback() {}
    

    Becomes this in 0.6

    use axum::Router;
    
    let app = Router::new().fallback(fallback);
    
    async fn fallback() {}
    
  • changed: Router::nest now only accepts Routers, the general-purpose
    Service nesting method has been renamed to nest_service (#​1368)

  • breaking: Allow Error: Into<Infallible> for Route::{layer, route_layer} (#​924)

  • breaking: MethodRouter now panics on overlapping routes (#​1102)

  • breaking: Router::route now only accepts MethodRouters created with
    get, post, etc. Use the new Router::route_service for routing to
    any Services (#​1155)

  • breaking: Adding a .route_layer onto a Router or MethodRouter
    without any routes will now result in a panic. Previously, this just did
    nothing. #​1327

  • breaking: RouterService has been removed since Router now implements
    Service when the state is (). Use Router::with_state to provide the
    state and get a Router<()>. Note that RouterService only existed in the
    pre-releases, not 0.5 (#​1552)

Extractors

  • added: Added new type safe State extractor. This can be used with
    Router::with_state and gives compile errors for missing states, whereas
    Extension would result in runtime errors (#​1155)

    We recommend migrating from Extension to State for sharing application state since that is more type
    safe and faster. That is done by using Router::with_state and State.

    This setup in 0.5

    use axum::{routing::get, Extension, Router};
    
    let app = Router::new()
        .route("/", get(handler))
        .layer(Extension(AppState {}));
    
    async fn handler(Extension(app_state): Extension<AppState>) {}
    
    #[derive(Clone)]
    struct AppState {}
    

    Becomes this in 0.6 using State:

    use axum::{routing::get, extract::State, Router};
    
    let app = Router::new()
        .route("/", get(handler))
        .with_state(AppState {});
    
    async fn handler(State(app_state): State<AppState>) {}
    
    #[derive(Clone)]
    struct AppState {}
    

    If you have multiple extensions, you can use fields on AppState and implement
    FromRef:

    use axum::{extract::{State, FromRef}, routing::get, Router};
    
    let state = AppState {
        client: HttpClient {},
        database: Database {},
    };
    
    let app = Router::new().route("/", get(handler)).with_state(state);
    
    async fn handler(
        State(client): State<HttpClient>,
        State(database): State<Database>,
    ) {}
    
    // the derive requires enabling the "macros" feature
    #[derive(Clone, FromRef)]
    struct AppState {
        client: HttpClient,
        database: Database,
    }
    
    #[derive(Clone)]
    struct HttpClient {}
    
    #[derive(Clone)]
    struct Database {}
    
  • breaking: It is now only possible for one extractor per handler to consume
    the request body. In 0.5 doing so would result in runtime errors but in 0.6 it
    is a compile error (#​1272)

    axum enforces this by only allowing the last extractor to consume the
    request.

    For example:

    use axum::{Json, http::HeaderMap};
    
    // This wont compile on 0.6 because both `Json` and `String` need to consume
    // the request body. You can use either `Json` or `String`, but not both.
    async fn handler_1(
        json: Json<serde_json::Value>,
        string: String,
    ) {}
    
    // This won't work either since `Json` is not the last extractor.
    async fn handler_2(
        json: Json<serde_json::Value>,
        headers: HeaderMap,
    ) {}
    
    // This works!
    async fn handler_3(
        headers: HeaderMap,
        json: Json<serde_json::Value>,
    ) {}
    

    This is done by reworking the FromRequest trait and introducing a new
    FromRequestParts trait.

    If your extractor needs to consume the request body then you should implement
    FromRequest, otherwise implement FromRequestParts.

    This extractor in 0.5:

    struct MyExtractor { /* ... */ }
    
    #[async_trait]
    impl<B> FromRequest<B> for MyExtractor
    where
        B: Send,
    {
        type Rejection = StatusCode;
    
        async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
            // ...
        }
    }
    

    Becomes this in 0.6:

    use axum::{
        extract::{FromRequest, FromRequestParts},
        http::{StatusCode, Request, request::Parts},
        async_trait,
    };
    
    struct MyExtractor { /* ... */ }
    
    // implement `FromRequestParts` if you don't need to consume the request body
    #[async_trait]
    impl<S> FromRequestParts<S> for MyExtractor
    where
        S: Send + Sync,
    {
        type Rejection = StatusCode;
    
        async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
            // ...
        }
    }
    
    // implement `FromRequest` if you do need to consume the request body
    #[async_trait]
    impl<S, B> FromRequest<S, B> for MyExtractor
    where
        S: Send + Sync,
        B: Send + 'static,
    {
        type Rejection = StatusCode;
    
        async fn from_request(req: Request<B>, state: &S) -> Result<Self, Self::Rejection> {
            // ...
        }
    }
    

    For an example of how to write an extractor that accepts different
    Content-Types see the [parse-body-based-on-content-type][parse-body-based-on-content-type] example.

  • added: FromRequest and FromRequestParts derive macro re-exports from
    [axum-macros][axum-macros] behind the macros feature (#​1352)

  • added: Add RequestExt and RequestPartsExt which adds convenience
    methods for running extractors to http::Request and http::request::Parts (#​1301)

  • added: JsonRejection now displays the path at which a deserialization
    error occurred (#​1371)

  • added: Add extract::RawForm for accessing raw urlencoded query bytes or request body (#​1487)

  • fixed: Used 400 Bad Request for FailedToDeserializeQueryString
    rejections, instead of 422 Unprocessable Entity (#​1387)

  • changed: The inner error of a JsonRejection is now
    serde_path_to_error::Error<serde_json::Error>. Previously it was
    serde_json::Error (#​1371)

  • changed: The default body limit now applies to the Multipart extractor (#​1420)

  • breaking: ContentLengthLimit has been removed. Use DefaultBodyLimit instead (#​1400)

  • breaking: RequestParts has been removed as part of the FromRequest
    rework (#​1272)

  • breaking: BodyAlreadyExtracted has been removed (#​1272)

  • breaking: The following types or traits have a new S type param
    which represents the state (#​1155):

    • Router, defaults to ()
    • MethodRouter, defaults to ()
    • FromRequest, no default
    • Handler, no default
  • breaking: MatchedPath can now no longer be extracted in middleware for
    nested routes. In previous versions it returned invalid data when extracted
    from a middleware applied to a nested router. MatchedPath can still be
    extracted from handlers and middleware that aren't on nested routers (#​1462)

  • breaking: Rename FormRejection::FailedToDeserializeQueryString to
    FormRejection::FailedToDeserializeForm (#​1496)

Middleware

  • added: Support running extractors on middleware::from_fn functions (#​1088)
  • added: Add middleware::from_fn_with_state to enable running extractors that require
    state (#​1342)
  • added: Add middleware::from_extractor_with_state (#​1396)
  • added: Add map_request, map_request_with_state for transforming the
    request with an async function (#​1408)
  • added: Add map_response, map_response_with_state for transforming the
    response with an async function (#​1414)
  • added: Support any middleware response that implements IntoResponse (#​1152)
  • breaking: Remove extractor_middleware which was previously deprecated.
    Use axum::middleware::from_extractor instead (#​1077)
  • breaking: Require middleware added with Handler::layer to have
    Infallible as the error type (#​1152)

Misc

  • added: Support compiling to WASM. See the simple-router-wasm example
    for more details (#​1382)
  • added: Add ServiceExt with methods for turning any Service into a
    MakeService similarly to Router::into_make_service (#​1302)
  • added: String and binary From impls have been added to extract::ws::Message
    to be more inline with tungstenite (#​1421)
  • added: Add #[derive(axum::extract::FromRef)] (#​1430)
  • added: Add accept_unmasked_frames setting in WebSocketUpgrade (#​1529)
  • added: Add WebSocketUpgrade::on_failed_upgrade to customize what to do
    when upgrading a connection fails (#​1539)
  • fixed: Annotate panicking functions with #[track_caller] so the error
    message points to where the user added the invalid route, rather than
    somewhere internally in axum (#​1248)
  • changed: axum's MSRV is now 1.60 (#​1239)
  • changed: For methods that accept some S: Service, the bounds have been
    relaxed so the response type must implement IntoResponse rather than being a
    literal Response
  • breaking: New tokio default feature needed for WASM support. If you
    don't need WASM support but have default_features = false for other reasons
    you likely need to re-enable the tokio feature (#​1382)
  • breaking: handler::{WithState, IntoService} are merged into one type,
    named HandlerService (#​1418)

v0.5.17: axum - v0.5.17

Compare Source

  • fixed: Annotate panicking functions with #[track_caller] so the error
    message points to where the user added the invalid router, rather than
    somewhere internally in axum (#​1248)
  • fixed: Make Multipart extractor work with RequestBodyLimit middleware (#​1379)
  • added: Add DefaultBodyLimit::max for changing the default body limit (#​1397)
  • added: Various documentation improvements

v0.5.16: axum - v0.5.16

Compare Source

Security

  • breaking: Added default limit to how much data Bytes::from_request will
    consume. Previously it would attempt to consume the entire request body
    without checking its length. This meant if a malicious peer sent an large (or
    infinite) request body your server might run out of memory and crash.

    The default limit is at 2 MB and can be disabled by adding the new
    DefaultBodyLimit::disable() middleware. See its documentation for more
    details.

    This also applies to these extractors which used Bytes::from_request
    internally:

    • Form
    • Json
    • String

    Thanks to Shachar Menashe for reporting this vulnerability.

    (#​1346)

v0.5.15: axum - v0.5.15

Compare Source

Note: This is a re-release of 0.5.14 that fixes an accidental breaking change.

  • fixed: Don't expose internal type names in QueryRejection response. (#​1171)
  • fixed: Improve performance of JSON serialization (#​1178)
  • fixed: Improve build times by generating less IR (#​1192)

v0.5.14: axum - v0.5.14

Compare Source

Yanked, as it contained an accidental breaking change.

v0.5.13: axum - v0.5.13

Compare Source

  • fixed: If WebSocketUpgrade cannot upgrade the connection it will return a
    WebSocketUpgradeRejection::ConnectionNotUpgradable rejection (#​1135)
  • changed: WebSocketUpgradeRejection has a new variant ConnectionNotUpgradable
    variant (#​1135)

v0.5.12: axum - v0.5.12

Compare Source

  • added: Added debug_handler which is an attribute macro that improves
    type errors when applied to handler function. It is re-exported from
    axum-macros (#​1144)

v0.5.11: axum - v0.5.11

Compare Source

  • added: Implement TryFrom<http:: Method> for MethodFilter and use new
    NoMatchingMethodFilter error in case of failure (#​1130)
  • added: Document how to run extractors from middleware (#​1140)

v0.5.10: axum - v0.5.10

Compare Source

  • fixed: Make Router cheaper to clone (#​1123)
  • fixed: Fix possible panic when doing trailing slash redirect (#​1124)

v0.5.9: axum - v0.5.9

Compare Source

  • fixed: Fix compile error when the headers is enabled and the form
    feature is disabled (#​1107)

v0.5.8: axum - v0.5.8

Compare Source

  • added: Support resolving host name via Forwarded header in Host
    extractor (#​1078)
  • added: Implement IntoResponse for Form (#​1095)
  • change: axum's MSRV is now 1.56 (#​1098)

v0.5.7: axum - v0.5.7

Compare Source

  • added: Implement Default for Extension (#​1043)
  • fixed: Support deserializing Vec<(String, String)> in extract::Path<_> to get vector of
    key/value pairs (#​1059)
  • added: Add extract::ws::close_code which contains constants for close codes (#​1067)
  • fixed: Use impl IntoResponse less in docs (#​1049)

v0.5.6: axum - v0.5.6

Compare Source

  • added: Add WebSocket::protocol to return the selected WebSocket subprotocol, if there is one. (#​1022)
  • fixed: Improve error message for PathRejection::WrongNumberOfParameters to hint at using
    Path<(String, String)> or Path<SomeStruct> (#​1023)
  • fixed: PathRejection::WrongNumberOfParameters now uses 500 Internal Server Error since
    it's a programmer error and not a client error (#​1023)
  • fixed: Fix InvalidFormContentType mentioning the wrong content type

v0.5.5: axum - v0.5.5

Compare Source

  • fixed: Correctly handle GET, HEAD, and OPTIONS requests in ContentLengthLimit.
    Request with these methods are now accepted if they do not have a Content-Length header, and
    the request body will not be checked. If they do have a Content-Length header they'll be
    rejected. This allows ContentLengthLimit to be used as middleware around several routes,
    including GET routes (#​989)
  • added: Add MethodRouter::{into_make_service, into_make_service_with_connect_info} (#​1010)

v0.5.4: axum - v0.5.4

Compare Source

  • added: Add response::ErrorResponse and response::Result for
    IntoResponse-based error handling (#​921)
  • added: Add middleware::from_extractor and deprecate extract::extractor_middleware (#​957)
  • changed: Update to tower-http 0.3 (#​965)

v0.5.3: axum - v0.5.3

Compare Source

  • added: Add AppendHeaders for appending headers to a response rather than overriding them (#​927)
  • added: Add axum::extract::multipart::Field::chunk method for streaming a single chunk from
    the field (#​901)
  • fixed: Fix trailing slash redirection with query parameters (#​936)

v0.5.2: axum - v0.5.2

Compare Source

Yanked, as it contained an accidental breaking change.

v0.5.1: axum - v0.5.1

Compare Source

  • added: Add RequestParts::extract which allows applying an extractor as a method call ([#​897)
serde-rs/json

v1.0.90

Compare Source

  • Documentation improvements
tokio-rs/tokio

v1.23.0: Tokio v1.23.0

Compare Source

Fixed
  • net: fix Windows named pipe connect (#​5208)
  • io: support vectored writes for ChildStdin (#​5216)
  • io: fix async fn ready() false positive for OS-specific events (#​5231)
Changed
  • runtime: yield_now defers task until after driver poll (#​5223)
  • runtime: reduce amount of codegen needed per spawned task (#​5213)
  • windows: replace winapi dependency with windows-sys (#​5204)

Configuration

📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 Automerge: Enabled.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

👻 Immortal: This PR will be recreated if closed unmerged. Get config help if that's undesired.


  • If you want to rebase/retry this PR, check this box

This PR has been generated by Renovate Bot.

This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [anyhow](https://github.com/dtolnay/anyhow) | dependencies | patch | `1.0.66` -> `1.0.67` | | [axum](https://github.com/tokio-rs/axum) | dependencies | minor | `0.5` -> `0.6` | | [serde_json](https://github.com/serde-rs/json) | dependencies | patch | `1.0.89` -> `1.0.90` | | [tokio](https://tokio.rs) ([source](https://github.com/tokio-rs/tokio)) | dependencies | minor | `1.22` -> `1.23` | --- ### Release Notes <details> <summary>dtolnay/anyhow</summary> ### [`v1.0.67`](https://github.com/dtolnay/anyhow/releases/tag/1.0.67) [Compare Source](https://github.com/dtolnay/anyhow/compare/1.0.66...1.0.67) - Improve the backtrace captured when `context()` is used on an `Option` ([#&#8203;280](https://github.com/dtolnay/anyhow/issues/280)) </details> <details> <summary>tokio-rs/axum</summary> ### [`v0.6.1`](https://github.com/tokio-rs/axum/releases/tag/axum-v0.6.1): axum - v0.6.1 [Compare Source](https://github.com/tokio-rs/axum/compare/axum-v0.6.0...axum-v0.6.1) - **added:** Expand the docs for `Router::with_state` ([#&#8203;1580]) [#&#8203;1580]: https://github.com/tokio-rs/axum/pull/1580 ### [`v0.6.0`](https://github.com/tokio-rs/axum/releases/tag/axum-v0.6.0): axum - v0.6.0 [Compare Source](https://github.com/tokio-rs/axum/compare/axum-v0.5.17...axum-v0.6.0) #### Routing - **fixed:** Nested routers are now allowed to have fallbacks ([#&#8203;1521]): ```rust let api_router = Router::new() .route("/users", get(|| { ... })) .fallback(api_fallback); let app = Router::new() // this would panic in 0.5 but in 0.6 it just works // // requests starting with `/api` but not handled by `api_router` // will go to `/api_fallback` .nest("/api", api_router); ``` The outer router's fallback will still apply if a nested router doesn't have its own fallback: ```rust // this time without a fallback let api_router = Router::new().route("/users", get(|| { ... })); let app = Router::new() .nest("/api", api_router) // `api_fallback` will inherit this fallback .fallback(app_fallback); ``` - **breaking:** The request `/foo/` no longer matches `/foo/*rest`. If you want to match `/foo/` you have to add a route specifically for that ([#&#8203;1086]) For example: ```rust use axum::{Router, routing::get, extract::Path}; let app = Router::new() // this will match `/foo/bar/baz` .route("/foo/*rest", get(handler)) // this will match `/foo/` .route("/foo/", get(handler)) // if you want `/foo` to match you must also add an explicit route for it .route("/foo", get(handler)); async fn handler( // use an `Option` because `/foo/` and `/foo` don't have any path params params: Option<Path<String>>, ) {} ``` - **breaking:** Path params for wildcard routes no longer include the prefix `/`. e.g. `/foo.js` will match `/*filepath` with a value of `foo.js`, *not* `/foo.js` ([#&#8203;1086]) For example: ```rust use axum::{Router, routing::get, extract::Path}; let app = Router::new().route("/foo/*rest", get(handler)); async fn handler( Path(params): Path<String>, ) { // for the request `/foo/bar/baz` the value of `params` will be `bar/baz` // // on 0.5 it would be `/bar/baz` } ``` - **fixed:** Routes like `/foo` and `/*rest` are no longer considered overlapping. `/foo` will take priority ([#&#8203;1086]) For example: ```rust use axum::{Router, routing::get}; let app = Router::new() // this used to not be allowed but now just works .route("/foo/*rest", get(foo)) .route("/foo/bar", get(bar)); async fn foo() {} async fn bar() {} ``` - **breaking:** Automatic trailing slash redirects have been removed. Previously if you added a route for `/foo`, axum would redirect calls to `/foo/` to `/foo` (or vice versa for `/foo/`): ```rust use axum::{Router, routing::get}; let app = Router::new() // a request to `GET /foo/` will now get `404 Not Found` // whereas in 0.5 axum would redirect to `/foo` // // same goes the other way if you had the route `/foo/` // axum will no longer redirect from `/foo` to `/foo/` .route("/foo", get(handler)); async fn handler() {} ``` Either explicitly add routes for `/foo` and `/foo/` or use `axum_extra::routing::RouterExt::route_with_tsr` if you want the old behavior ([#&#8203;1119]) - **breaking:** `Router::fallback` now only accepts `Handler`s (similarly to what `get`, `post`, etc. accept). Use the new `Router::fallback_service` for setting any `Service` as the fallback ([#&#8203;1155]) This fallback on 0.5: ```rust use axum::{Router, handler::Handler}; let app = Router::new().fallback(fallback.into_service()); async fn fallback() {} ``` Becomes this in 0.6 ```rust use axum::Router; let app = Router::new().fallback(fallback); async fn fallback() {} ``` - **changed:** `Router::nest` now only accepts `Router`s, the general-purpose `Service` nesting method has been renamed to `nest_service` ([#&#8203;1368]) - **breaking:** Allow `Error: Into<Infallible>` for `Route::{layer, route_layer}` ([#&#8203;924]) - **breaking:** `MethodRouter` now panics on overlapping routes ([#&#8203;1102]) - **breaking:** `Router::route` now only accepts `MethodRouter`s created with `get`, `post`, etc. Use the new `Router::route_service` for routing to any `Service`s ([#&#8203;1155]) - **breaking:** Adding a `.route_layer` onto a `Router` or `MethodRouter` without any routes will now result in a panic. Previously, this just did nothing. [#&#8203;1327] - **breaking:** `RouterService` has been removed since `Router` now implements `Service` when the state is `()`. Use `Router::with_state` to provide the state and get a `Router<()>`. Note that `RouterService` only existed in the pre-releases, not 0.5 ([#&#8203;1552]) #### Extractors - **added:** Added new type safe `State` extractor. This can be used with `Router::with_state` and gives compile errors for missing states, whereas `Extension` would result in runtime errors ([#&#8203;1155]) We recommend migrating from `Extension` to `State` for sharing application state since that is more type safe and faster. That is done by using `Router::with_state` and `State`. This setup in 0.5 ```rust use axum::{routing::get, Extension, Router}; let app = Router::new() .route("/", get(handler)) .layer(Extension(AppState {})); async fn handler(Extension(app_state): Extension<AppState>) {} #[derive(Clone)] struct AppState {} ``` Becomes this in 0.6 using `State`: ```rust use axum::{routing::get, extract::State, Router}; let app = Router::new() .route("/", get(handler)) .with_state(AppState {}); async fn handler(State(app_state): State<AppState>) {} #[derive(Clone)] struct AppState {} ``` If you have multiple extensions, you can use fields on `AppState` and implement `FromRef`: ```rust use axum::{extract::{State, FromRef}, routing::get, Router}; let state = AppState { client: HttpClient {}, database: Database {}, }; let app = Router::new().route("/", get(handler)).with_state(state); async fn handler( State(client): State<HttpClient>, State(database): State<Database>, ) {} // the derive requires enabling the "macros" feature #[derive(Clone, FromRef)] struct AppState { client: HttpClient, database: Database, } #[derive(Clone)] struct HttpClient {} #[derive(Clone)] struct Database {} ``` - **breaking:** It is now only possible for one extractor per handler to consume the request body. In 0.5 doing so would result in runtime errors but in 0.6 it is a compile error ([#&#8203;1272]) axum enforces this by only allowing the *last* extractor to consume the request. For example: ```rust use axum::{Json, http::HeaderMap}; // This wont compile on 0.6 because both `Json` and `String` need to consume // the request body. You can use either `Json` or `String`, but not both. async fn handler_1( json: Json<serde_json::Value>, string: String, ) {} // This won't work either since `Json` is not the last extractor. async fn handler_2( json: Json<serde_json::Value>, headers: HeaderMap, ) {} // This works! async fn handler_3( headers: HeaderMap, json: Json<serde_json::Value>, ) {} ``` This is done by reworking the `FromRequest` trait and introducing a new `FromRequestParts` trait. If your extractor needs to consume the request body then you should implement `FromRequest`, otherwise implement `FromRequestParts`. This extractor in 0.5: ```rust struct MyExtractor { /* ... */ } #[async_trait] impl<B> FromRequest<B> for MyExtractor where B: Send, { type Rejection = StatusCode; async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> { // ... } } ``` Becomes this in 0.6: ```rust use axum::{ extract::{FromRequest, FromRequestParts}, http::{StatusCode, Request, request::Parts}, async_trait, }; struct MyExtractor { /* ... */ } // implement `FromRequestParts` if you don't need to consume the request body #[async_trait] impl<S> FromRequestParts<S> for MyExtractor where S: Send + Sync, { type Rejection = StatusCode; async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> { // ... } } // implement `FromRequest` if you do need to consume the request body #[async_trait] impl<S, B> FromRequest<S, B> for MyExtractor where S: Send + Sync, B: Send + 'static, { type Rejection = StatusCode; async fn from_request(req: Request<B>, state: &S) -> Result<Self, Self::Rejection> { // ... } } ``` For an example of how to write an extractor that accepts different `Content-Types` see the [`parse-body-based-on-content-type`][parse-body-based-on-content-type] example. - **added:** `FromRequest` and `FromRequestParts` derive macro re-exports from [`axum-macros`][axum-macros] behind the `macros` feature ([#&#8203;1352]) - **added:** Add `RequestExt` and `RequestPartsExt` which adds convenience methods for running extractors to `http::Request` and `http::request::Parts` ([#&#8203;1301]) - **added**: `JsonRejection` now displays the path at which a deserialization error occurred ([#&#8203;1371]) - **added:** Add `extract::RawForm` for accessing raw urlencoded query bytes or request body ([#&#8203;1487]) - **fixed:** Used `400 Bad Request` for `FailedToDeserializeQueryString` rejections, instead of `422 Unprocessable Entity` ([#&#8203;1387]) - **changed**: The inner error of a `JsonRejection` is now `serde_path_to_error::Error<serde_json::Error>`. Previously it was `serde_json::Error` ([#&#8203;1371]) - **changed:** The default body limit now applies to the `Multipart` extractor ([#&#8203;1420]) - **breaking:** `ContentLengthLimit` has been removed. Use `DefaultBodyLimit` instead ([#&#8203;1400]) - **breaking:** `RequestParts` has been removed as part of the `FromRequest` rework ([#&#8203;1272]) - **breaking:** `BodyAlreadyExtracted` has been removed ([#&#8203;1272]) - **breaking:** The following types or traits have a new `S` type param which represents the state ([#&#8203;1155]): - `Router`, defaults to `()` - `MethodRouter`, defaults to `()` - `FromRequest`, no default - `Handler`, no default - **breaking:** `MatchedPath` can now no longer be extracted in middleware for nested routes. In previous versions it returned invalid data when extracted from a middleware applied to a nested router. `MatchedPath` can still be extracted from handlers and middleware that aren't on nested routers ([#&#8203;1462]) - **breaking:** Rename `FormRejection::FailedToDeserializeQueryString` to `FormRejection::FailedToDeserializeForm` ([#&#8203;1496]) #### Middleware - **added:** Support running extractors on `middleware::from_fn` functions ([#&#8203;1088]) - **added**: Add `middleware::from_fn_with_state` to enable running extractors that require state ([#&#8203;1342]) - **added:** Add `middleware::from_extractor_with_state` ([#&#8203;1396]) - **added:** Add `map_request`, `map_request_with_state` for transforming the request with an async function ([#&#8203;1408]) - **added:** Add `map_response`, `map_response_with_state` for transforming the response with an async function ([#&#8203;1414]) - **added:** Support any middleware response that implements `IntoResponse` ([#&#8203;1152]) - **breaking:** Remove `extractor_middleware` which was previously deprecated. Use `axum::middleware::from_extractor` instead ([#&#8203;1077]) - **breaking:** Require middleware added with `Handler::layer` to have `Infallible` as the error type ([#&#8203;1152]) #### Misc - **added:** Support compiling to WASM. See the `simple-router-wasm` example for more details ([#&#8203;1382]) - **added:** Add `ServiceExt` with methods for turning any `Service` into a `MakeService` similarly to `Router::into_make_service` ([#&#8203;1302]) - **added:** String and binary `From` impls have been added to `extract::ws::Message` to be more inline with `tungstenite` ([#&#8203;1421]) - **added:** Add `#[derive(axum::extract::FromRef)]` ([#&#8203;1430]) - **added:** Add `accept_unmasked_frames` setting in WebSocketUpgrade ([#&#8203;1529]) - **added:** Add `WebSocketUpgrade::on_failed_upgrade` to customize what to do when upgrading a connection fails ([#&#8203;1539]) - **fixed:** Annotate panicking functions with `#[track_caller]` so the error message points to where the user added the invalid route, rather than somewhere internally in axum ([#&#8203;1248]) - **changed:** axum's MSRV is now 1.60 ([#&#8203;1239]) - **changed:** For methods that accept some `S: Service`, the bounds have been relaxed so the response type must implement `IntoResponse` rather than being a literal `Response` - **breaking:** New `tokio` default feature needed for WASM support. If you don't need WASM support but have `default_features = false` for other reasons you likely need to re-enable the `tokio` feature ([#&#8203;1382]) - **breaking:** `handler::{WithState, IntoService}` are merged into one type, named `HandlerService` ([#&#8203;1418]) [#&#8203;924]: https://github.com/tokio-rs/axum/pull/924 [#&#8203;1077]: https://github.com/tokio-rs/axum/pull/1077 [#&#8203;1086]: https://github.com/tokio-rs/axum/pull/1086 [#&#8203;1088]: https://github.com/tokio-rs/axum/pull/1088 [#&#8203;1102]: https://github.com/tokio-rs/axum/pull/1102 [#&#8203;1119]: https://github.com/tokio-rs/axum/pull/1119 [#&#8203;1152]: https://github.com/tokio-rs/axum/pull/1152 [#&#8203;1155]: https://github.com/tokio-rs/axum/pull/1155 [#&#8203;1239]: https://github.com/tokio-rs/axum/pull/1239 [#&#8203;1248]: https://github.com/tokio-rs/axum/pull/1248 [#&#8203;1272]: https://github.com/tokio-rs/axum/pull/1272 [#&#8203;1301]: https://github.com/tokio-rs/axum/pull/1301 [#&#8203;1302]: https://github.com/tokio-rs/axum/pull/1302 [#&#8203;1327]: https://github.com/tokio-rs/axum/pull/1327 [#&#8203;1342]: https://github.com/tokio-rs/axum/pull/1342 [#&#8203;1346]: https://github.com/tokio-rs/axum/pull/1346 [#&#8203;1352]: https://github.com/tokio-rs/axum/pull/1352 [#&#8203;1368]: https://github.com/tokio-rs/axum/pull/1368 [#&#8203;1371]: https://github.com/tokio-rs/axum/pull/1371 [#&#8203;1382]: https://github.com/tokio-rs/axum/pull/1382 [#&#8203;1387]: https://github.com/tokio-rs/axum/pull/1387 [#&#8203;1389]: https://github.com/tokio-rs/axum/pull/1389 [#&#8203;1396]: https://github.com/tokio-rs/axum/pull/1396 [#&#8203;1397]: https://github.com/tokio-rs/axum/pull/1397 [#&#8203;1400]: https://github.com/tokio-rs/axum/pull/1400 [#&#8203;1408]: https://github.com/tokio-rs/axum/pull/1408 [#&#8203;1414]: https://github.com/tokio-rs/axum/pull/1414 [#&#8203;1418]: https://github.com/tokio-rs/axum/pull/1418 [#&#8203;1420]: https://github.com/tokio-rs/axum/pull/1420 [#&#8203;1421]: https://github.com/tokio-rs/axum/pull/1421 [#&#8203;1430]: https://github.com/tokio-rs/axum/pull/1430 [#&#8203;1462]: https://github.com/tokio-rs/axum/pull/1462 [#&#8203;1487]: https://github.com/tokio-rs/axum/pull/1487 [#&#8203;1496]: https://github.com/tokio-rs/axum/pull/1496 [#&#8203;1521]: https://github.com/tokio-rs/axum/pull/1521 [#&#8203;1529]: https://github.com/tokio-rs/axum/pull/1529 [#&#8203;1532]: https://github.com/tokio-rs/axum/pull/1532 [#&#8203;1539]: https://github.com/tokio-rs/axum/pull/1539 [#&#8203;1552]: https://github.com/tokio-rs/axum/pull/1552 [`axum-macros`]: https://docs.rs/axum-macros/latest/axum_macros/ [`parse-body-based-on-content-type`]: https://github.com/tokio-rs/axum/blob/main/examples/parse-body-based-on-content-type/src/main.rs ### [`v0.5.17`](https://github.com/tokio-rs/axum/releases/tag/axum-v0.5.17): axum - v0.5.17 [Compare Source](https://github.com/tokio-rs/axum/compare/axum-v0.5.16...axum-v0.5.17) - **fixed:** Annotate panicking functions with `#[track_caller]` so the error message points to where the user added the invalid router, rather than somewhere internally in axum ([#&#8203;1248]) - **fixed:** Make `Multipart` extractor work with `RequestBodyLimit` middleware ([#&#8203;1379]) - **added:** Add `DefaultBodyLimit::max` for changing the default body limit ([#&#8203;1397]) - **added:** Various documentation improvements [#&#8203;1248]: https://github.com/tokio-rs/axum/pull/1248 [#&#8203;1379]: https://github.com/tokio-rs/axum/pull/1379 [#&#8203;1397]: https://github.com/tokio-rs/axum/pull/1397 ### [`v0.5.16`](https://github.com/tokio-rs/axum/releases/tag/axum-v0.5.16): axum - v0.5.16 [Compare Source](https://github.com/tokio-rs/axum/compare/axum-v0.5.15...axum-v0.5.16) #### Security - **breaking:** Added default limit to how much data `Bytes::from_request` will consume. Previously it would attempt to consume the entire request body without checking its length. This meant if a malicious peer sent an large (or infinite) request body your server might run out of memory and crash. The default limit is at 2 MB and can be disabled by adding the new `DefaultBodyLimit::disable()` middleware. See its documentation for more details. This also applies to these extractors which used `Bytes::from_request` internally: - `Form` - `Json` - `String` Thanks to Shachar Menashe for reporting this vulnerability. ([#&#8203;1346]) [#&#8203;1346]: https://github.com/tokio-rs/axum/pull/1346 ### [`v0.5.15`](https://github.com/tokio-rs/axum/releases/tag/axum-v0.5.15): axum - v0.5.15 [Compare Source](https://github.com/tokio-rs/axum/compare/axum-v0.5.14...axum-v0.5.15) Note: This is a re-release of 0.5.14 that fixes an accidental breaking change. - **fixed:** Don't expose internal type names in `QueryRejection` response. ([#&#8203;1171]) - **fixed:** Improve performance of JSON serialization ([#&#8203;1178]) - **fixed:** Improve build times by generating less IR ([#&#8203;1192]) [#&#8203;1171]: https://github.com/tokio-rs/axum/pull/1171 [#&#8203;1178]: https://github.com/tokio-rs/axum/pull/1178 [#&#8203;1192]: https://github.com/tokio-rs/axum/pull/1192 ### [`v0.5.14`](https://github.com/tokio-rs/axum/releases/tag/axum-v0.5.14): axum - v0.5.14 [Compare Source](https://github.com/tokio-rs/axum/compare/axum-v0.5.13...axum-v0.5.14) Yanked, as it contained an accidental breaking change. ### [`v0.5.13`](https://github.com/tokio-rs/axum/releases/tag/axum-v0.5.13): axum - v0.5.13 [Compare Source](https://github.com/tokio-rs/axum/compare/axum-v0.5.12...axum-v0.5.13) - **fixed:** If `WebSocketUpgrade` cannot upgrade the connection it will return a `WebSocketUpgradeRejection::ConnectionNotUpgradable` rejection ([#&#8203;1135]) - **changed:** `WebSocketUpgradeRejection` has a new variant `ConnectionNotUpgradable` variant ([#&#8203;1135]) [#&#8203;1135]: https://github.com/tokio-rs/axum/pull/1135 ### [`v0.5.12`](https://github.com/tokio-rs/axum/releases/tag/axum-v0.5.12): axum - v0.5.12 [Compare Source](https://github.com/tokio-rs/axum/compare/axum-v0.5.11...axum-v0.5.12) - **added:** Added `debug_handler` which is an attribute macro that improves type errors when applied to handler function. It is re-exported from `axum-macros` ([#&#8203;1144]) [#&#8203;1144]: https://github.com/tokio-rs/axum/pull/1144 ### [`v0.5.11`](https://github.com/tokio-rs/axum/releases/tag/axum-v0.5.11): axum - v0.5.11 [Compare Source](https://github.com/tokio-rs/axum/compare/axum-v0.5.10...axum-v0.5.11) - **added:** Implement `TryFrom<http:: Method>` for `MethodFilter` and use new `NoMatchingMethodFilter` error in case of failure ([#&#8203;1130]) - **added:** Document how to run extractors from middleware ([#&#8203;1140]) [#&#8203;1130]: https://github.com/tokio-rs/axum/pull/1130 [#&#8203;1140]: https://github.com/tokio-rs/axum/pull/1140 ### [`v0.5.10`](https://github.com/tokio-rs/axum/releases/tag/axum-v0.5.10): axum - v0.5.10 [Compare Source](https://github.com/tokio-rs/axum/compare/axum-v0.5.9...axum-v0.5.10) - **fixed:** Make `Router` cheaper to clone ([#&#8203;1123]) - **fixed:** Fix possible panic when doing trailing slash redirect ([#&#8203;1124]) [#&#8203;1123]: https://github.com/tokio-rs/axum/pull/1123 [#&#8203;1124]: https://github.com/tokio-rs/axum/pull/1124 ### [`v0.5.9`](https://github.com/tokio-rs/axum/releases/tag/axum-v0.5.9): axum - v0.5.9 [Compare Source](https://github.com/tokio-rs/axum/compare/axum-v0.5.8...axum-v0.5.9) - **fixed:** Fix compile error when the `headers` is enabled and the `form` feature is disabled ([#&#8203;1107]) [#&#8203;1107]: https://github.com/tokio-rs/axum/pull/1107 ### [`v0.5.8`](https://github.com/tokio-rs/axum/releases/tag/axum-v0.5.8): axum - v0.5.8 [Compare Source](https://github.com/tokio-rs/axum/compare/axum-v0.5.7...axum-v0.5.8) - **added:** Support resolving host name via `Forwarded` header in `Host` extractor ([#&#8203;1078]) - **added:** Implement `IntoResponse` for `Form` ([#&#8203;1095]) - **change:** axum's MSRV is now 1.56 ([#&#8203;1098]) [#&#8203;1078]: https://github.com/tokio-rs/axum/pull/1078 [#&#8203;1095]: https://github.com/tokio-rs/axum/pull/1095 [#&#8203;1098]: https://github.com/tokio-rs/axum/pull/1098 ### [`v0.5.7`](https://github.com/tokio-rs/axum/releases/tag/axum-v0.5.7): axum - v0.5.7 [Compare Source](https://github.com/tokio-rs/axum/compare/axum-v0.5.6...axum-v0.5.7) - **added:** Implement `Default` for `Extension` ([#&#8203;1043]) - **fixed:** Support deserializing `Vec<(String, String)>` in `extract::Path<_>` to get vector of key/value pairs ([#&#8203;1059]) - **added:** Add `extract::ws::close_code` which contains constants for close codes ([#&#8203;1067]) - **fixed:** Use `impl IntoResponse` less in docs ([#&#8203;1049]) [#&#8203;1043]: https://github.com/tokio-rs/axum/pull/1043 [#&#8203;1049]: https://github.com/tokio-rs/axum/pull/1049 [#&#8203;1059]: https://github.com/tokio-rs/axum/pull/1059 [#&#8203;1067]: https://github.com/tokio-rs/axum/pull/1067 ### [`v0.5.6`](https://github.com/tokio-rs/axum/releases/tag/axum-v0.5.6): axum - v0.5.6 [Compare Source](https://github.com/tokio-rs/axum/compare/axum-v0.5.5...axum-v0.5.6) - **added:** Add `WebSocket::protocol` to return the selected WebSocket subprotocol, if there is one. ([#&#8203;1022]) - **fixed:** Improve error message for `PathRejection::WrongNumberOfParameters` to hint at using `Path<(String, String)>` or `Path<SomeStruct>` ([#&#8203;1023]) - **fixed:** `PathRejection::WrongNumberOfParameters` now uses `500 Internal Server Error` since it's a programmer error and not a client error ([#&#8203;1023]) - **fixed:** Fix `InvalidFormContentType` mentioning the wrong content type [#&#8203;1022]: https://github.com/tokio-rs/axum/pull/1022 [#&#8203;1023]: https://github.com/tokio-rs/axum/pull/1023 ### [`v0.5.5`](https://github.com/tokio-rs/axum/releases/tag/axum-v0.5.5): axum - v0.5.5 [Compare Source](https://github.com/tokio-rs/axum/compare/axum-v0.5.4...axum-v0.5.5) - **fixed:** Correctly handle `GET`, `HEAD`, and `OPTIONS` requests in `ContentLengthLimit`. Request with these methods are now accepted if they *do not* have a `Content-Length` header, and the request body will not be checked. If they do have a `Content-Length` header they'll be rejected. This allows `ContentLengthLimit` to be used as middleware around several routes, including `GET` routes ([#&#8203;989]) - **added:** Add `MethodRouter::{into_make_service, into_make_service_with_connect_info}` ([#&#8203;1010]) [#&#8203;989]: https://github.com/tokio-rs/axum/pull/989 [#&#8203;1010]: https://github.com/tokio-rs/axum/pull/1010 ### [`v0.5.4`](https://github.com/tokio-rs/axum/releases/tag/axum-v0.5.4): axum - v0.5.4 [Compare Source](https://github.com/tokio-rs/axum/compare/axum-v0.5.3...axum-v0.5.4) - **added:** Add `response::ErrorResponse` and `response::Result` for `IntoResponse`-based error handling ([#&#8203;921]) - **added:** Add `middleware::from_extractor` and deprecate `extract::extractor_middleware` ([#&#8203;957]) - **changed:** Update to tower-http 0.3 ([#&#8203;965]) [#&#8203;921]: https://github.com/tokio-rs/axum/pull/921 [#&#8203;957]: https://github.com/tokio-rs/axum/pull/957 [#&#8203;965]: https://github.com/tokio-rs/axum/pull/965 ### [`v0.5.3`](https://github.com/tokio-rs/axum/releases/tag/axum-v0.5.3): axum - v0.5.3 [Compare Source](https://github.com/tokio-rs/axum/compare/axum-v0.5.2...axum-v0.5.3) - **added:** Add `AppendHeaders` for appending headers to a response rather than overriding them ([#&#8203;927]) - **added:** Add `axum::extract::multipart::Field::chunk` method for streaming a single chunk from the field ([#&#8203;901]) - **fixed:** Fix trailing slash redirection with query parameters ([#&#8203;936]) [#&#8203;901]: https://github.com/tokio-rs/axum/pull/901 [#&#8203;927]: https://github.com/tokio-rs/axum/pull/927 [#&#8203;936]: https://github.com/tokio-rs/axum/pull/936 ### [`v0.5.2`](https://github.com/tokio-rs/axum/releases/tag/axum-v0.5.2): axum - v0.5.2 [Compare Source](https://github.com/tokio-rs/axum/compare/axum-v0.5.1...axum-v0.5.2) Yanked, as it contained an accidental breaking change. ### [`v0.5.1`](https://github.com/tokio-rs/axum/releases/tag/axum-v0.5.1): axum - v0.5.1 [Compare Source](https://github.com/tokio-rs/axum/compare/axum-v0.5.0...axum-v0.5.1) - **added:** Add `RequestParts::extract` which allows applying an extractor as a method call (\[[#&#8203;897](https://github.com/tokio-rs/axum/issues/897)) [#&#8203;897]: https://github.com/tokio-rs/axum/pull/897 </details> <details> <summary>serde-rs/json</summary> ### [`v1.0.90`](https://github.com/serde-rs/json/releases/tag/v1.0.90) [Compare Source](https://github.com/serde-rs/json/compare/v1.0.89...v1.0.90) - Documentation improvements </details> <details> <summary>tokio-rs/tokio</summary> ### [`v1.23.0`](https://github.com/tokio-rs/tokio/releases/tag/tokio-1.23.0): Tokio v1.23.0 [Compare Source](https://github.com/tokio-rs/tokio/compare/tokio-1.22.0...tokio-1.23.0) ##### Fixed - net: fix Windows named pipe connect ([#&#8203;5208]) - io: support vectored writes for `ChildStdin` ([#&#8203;5216]) - io: fix `async fn ready()` false positive for OS-specific events ([#&#8203;5231]) ##### Changed - runtime: `yield_now` defers task until after driver poll ([#&#8203;5223]) - runtime: reduce amount of codegen needed per spawned task ([#&#8203;5213]) - windows: replace `winapi` dependency with `windows-sys` ([#&#8203;5204]) [#&#8203;5208]: https://github.com/tokio-rs/tokio/pull/5208 [#&#8203;5216]: https://github.com/tokio-rs/tokio/pull/5216 [#&#8203;5213]: https://github.com/tokio-rs/tokio/pull/5213 [#&#8203;5204]: https://github.com/tokio-rs/tokio/pull/5204 [#&#8203;5223]: https://github.com/tokio-rs/tokio/pull/5223 [#&#8203;5231]: https://github.com/tokio-rs/tokio/pull/5231 </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNC4yMy4xIiwidXBkYXRlZEluVmVyIjoiMzQuNTguMSJ9-->
kjuulh force-pushed renovate/all from c2796247ce to 8f2544deb0 2022-12-06 19:56:24 +01:00 Compare
kjuulh changed title from Update Rust crate axum to 0.6 to Update all dependencies 2022-12-06 19:56:27 +01:00
kjuulh force-pushed renovate/all from 8f2544deb0 to 06ae52717d 2022-12-18 12:18:55 +01:00 Compare
kjuulh merged commit 06ae52717d into main 2022-12-18 12:41:01 +01:00
Sign in to join this conversation.
No reviewers
No Label
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: kjuulh/prae#9
No description provided.