[rust-axum] fix: let the implementation set the status of default responses
Fixes #25283
Related: #25294 changes the same rust-axum response templates (range status codes); whichever lands second needs a rebase.
A default response generated a variant with no status code, and the handler called Response::builder().status(0). With a body, the following headers_mut().unwrap() panicked; without one, the client got a 500. So default responses could not be returned at all, including the petstore user operations whose only response is default.
Changes
response.mustache: adefaultresponse variant now carries au16status code chosen by the implementation:Status0_UnexpectedError(u16)when there is no body;Status0_UnexpectedError(u16, models::Error)with a body (same for plain text, bytes and SSE bodies);- a
status: u16field when the variant is a struct because of response headers.
server-operation.mustache: destructure that status, validate it withStatusCode::from_u16and use it instead of0. An invalid code is logged (with the rejected value) and answered with 500, like other serialization errors in the handler. This applies to SSE bodies too.- Responses with an explicit status code are unchanged.
This changes the shape of default variants. Code that constructs them stops compiling. Such code could not send a correct response before (it either panicked or returned 500).
Not covered
- Range responses (
2XX, ...) still go through the existing{{#range}}branch, which is unchanged. - rust-server has a similar issue (
StatusCode::from_u16(0).expect(..)). Left for a separate PR.
Testing
- New
RustAxumServerCodegenTest#testDefaultResponseCarriesStatuswithsrc/test/resources/3_0/rust-axum/rust-axum-default-response.yaml. The spec has default responses with a JSON body, with no body, with a body and a header, with a header and no body, and with an SSE body. The test fails without the template change. - New sample
rust-axum-default-response(configbin/configs/manual/rust-axum-default-response.yaml). It builds with--all-featuresand--no-default-featureswithout warnings, and thepetstoresample tests pass. - I drove the generated router with
tower::ServiceExt::oneshot. Status codes chosen by the implementation (503/404/418/409, and 202 for SSE) come back with the expected headers and bodies, and an invalid code (1000) gives 500, SSE included. On master the same calls panic when there is a body, return 500 when there is none, and always return 200 for SSE.
PR checklist
- Read the contribution guidelines.
- Run the following to build the project and update samples:
Only the rust-axum samples were regenerated:./mvnw clean package || exit ./bin/generate-samples.sh ./bin/configs/*.yaml || exit ./bin/utils/export_docs_generators.sh || exitRUST_POST_PROCESS_FILE=$PWD/samples/server/petstore/rust-axum/rustfmt-2021.sh ./bin/generate-samples.sh bin/configs/manual/rust-axum*. That covers all rust-axum configs plus the newrust-axum-default-responsesample. The change is template-only and limited to rust-axum. No generator options changed, so the docs are unaffected.
Commit all changed files. - If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.
cc @frol @farcaller @richardwhiuk @paladinzh @jacob-pro @dsteeley
Summary by cubic
Fixes the rust-axum generator so default responses no longer panic or return 500: the generated server now requires implementation-provided status codes for default response variants. Invalid codes are logged and answered with 500, SSE bodies included.
Breaking change
- Default response variants now include a
u16status code that the implementation must supply; existing code constructing these variants will not compile.