Response

In a Handler, the Response is passed as a parameter:

  • The Response struct encapsulates all components of an HTTP response, providing a comprehensive API for constructing and manipulating HTTP responses.
  • It supports a fluent, chainable style (e.g., res.status_code(200).body("Hello")), facilitating the smooth construction of responses.
  • Core functionalities include:
    • Setting status codes and headers
    • Manipulating the response body (supporting strings, bytes, files, and streaming data)
    • Managing Cookies
    • Multiple content rendering methods
  • This struct employs a mutable reference pattern, returning a reference to itself via &mut self, allowing handlers to conveniently build and customize HTTP responses to meet various web service requirements.
#[handler]
async fn hello_world(res: &mut Response) {
    res.render("Hello world!");
}

After the server receives a client request, any matched Handler or middleware can write data into the Response. In certain scenarios, such as when a middleware wishes to prevent the execution of subsequent middleware and Handlers, you can use FlowCtrl:

#[handler]
async fn hello_world(res: &mut Response, ctrl: &mut FlowCtrl) {
    ctrl.skip_rest();
    res.render("Hello world!");
}

Writing Content

Writing data to a Response is straightforward:

  • Writing plain text data

    res.render("Hello world!");
  • Writing JSON serialized data

    use serde::Serialize;
    use salvo::prelude::Json;
    
    #[derive(Serialize, Debug)]
    struct User {
        name: String,
    }
    let user = User{name: "jobs".to_string()};
    res.render(Json(user));
Warning

If the render method is called multiple times to write JSON data, these pieces of data will not be merged into a single JSON object. Instead, they will be concatenated sequentially as independent text fragments, potentially resulting in invalid JSON format. If multiple data items need to be returned, they should be combined into a single object before serialization, or the logic should be handled manually.

  • Writing HTML

    res.render(Text::Html("<html><body>hello</body></html>"));

Writing HTTP Errors

  • Using render allows writing detailed error information to the Response.

    use salvo::http::errors::*;
    res.render(StatusError::internal_server_error().brief("error when serialize object to json"))
  • If custom error information is not needed, you can directly call set_http_code.

    use salvo::http::StatusCode;
    res.status_code(StatusCode::BAD_REQUEST);

Redirecting to Another URL

  • Using the render method, you can write a redirect response to the Response, navigating to a new URL. When you call Redirect::found, it sets the HTTP status code to 302 (Found), indicating a temporary redirect.
    use salvo::prelude::*;
    
    #[handler]
    async fn redirect(res: &mut Response) {
        res.render(Redirect::found("https://salvo.rs/"));
    }

ResBody

The Body type returned by Response is ResBody, which is an enum. In case of an error, it is set to ResBody::Error, containing error information for deferred error handling. Notably, StatusError does not implement Writer; this design allows you to customize its display in the Catcher.

Overview of Response Struct Methods

CategoryMethodDescription
Creationnew() / with_cookies()Create a new response
Status Codestatus_code()Set the status code
Headersheaders()/headers_mut()Get headers
set_headers()/add_header()Set/Add headers
content_type()Get content type
HTTP Versionversion()/version_mut()Get/Modify HTTP version
Response Bodybody()/body_mut()Set/Get the response body
replace_body()/take_body()Replace/Extract the response body
write_body()Write data to the response body
stream()/channel()Stream response / Create a sending channel
Cookie Handlingcookies()/cookie()Get cookies / Get a specific cookie
add_cookie()/remove_cookie()Add/Remove a cookie
Content Responserender()Render content
stuff()Set status code and render content
send_file()Send a file
Status Queryis_stamped()Check if the response is ready to be written back