Responses and status codes
Choose the right contract for JSON, plain text, binary data, and custom HTTP responses.
An action's return type determines how its body is represented. Pay particular attention to the difference between returning a value directly and returning Result<T, E>.
Return types#
| Action return type | Representation / status |
|---|---|
Result<Dto, E> |
Dto: Serialize; JSON |
Json<Dto> / Result<Json<Dto>, E> |
Explicit JSON |
Direct String / &str |
Plain text |
Result<String, E> |
JSON string |
Direct Vec<u8> |
Binary |
Result<Vec<u8>, E> |
JSON array |
PlainText / BinaryData and their Result forms |
Explicit text / binary |
NoContent |
204, no body |
Created<T> |
201, optional Location, DTO as JSON |
Accepted<T> |
202, optional Location, DTO as JSON |
Created::empty() / Accepted::empty() |
201/202, no body |
Created<()> / Accepted<()> |
JSON null; not the same as empty |
() / Result<(), E> |
Manual/no-representation success; not automatically 204 |
ResponseBuilder |
Complete response contract |
StreamingResponse, SseResponse, StaticFileResponse |
Lazy/specialized response contract |
Creation and empty responses#
Created::new("/users/42", dto) produces 201, Location, and a JSON body. NoContent explicitly selects 204. Created::empty() does not create a body, whereas Created<()> produces JSON null.
#[delete("/:id")]
async fn remove(&self) -> Result<NoContent, HttpApiError> {
// In a real application, complete the deletion through the domain service first.
Ok(NoContent)
}This snippet only demonstrates response selection; it does not delete any record. Result<(), E> does not automatically mean 204.
Add headers and cookies#
Use PassthroughResponseContext to write additional metadata while preserving the typed body. Staged metadata is discarded if the action or serialization fails. The cookie example demonstrates this path in a complete controller.
Do not use passthrough to arbitrarily change the status of responses that own their status, such as Created, Accepted, NoContent, streaming responses, or ResponseBuilder.
Manual responses#
If you use raw &mut Response, the action must take the manual/unit return path. Do not combine a raw response with a typed return value. Use ResponseBuilder for a complete response contract, StaticFileResponse for files, or SseResponse for events.
Error conversion#
An action's error type can implement IntoResponse + Send; not every domain error has to be HttpApiError. Successfully writing an application error as an HTTP response is not a technical response-write failure. The next page shows a custom error contract.
Sources for this page v0.1.0
This guide is based on the reviewed framework commit.