Skip to main content
The Html response type wraps any response body and automatically sets the Content-Type: text/html; charset=utf-8 header.

Basic usage

Wrap a string or any type that implements IntoResponse:
use axum::{response::Html, routing::get, Router};

async fn handler() -> Html<&'static str> {
    Html("<h1>Hello, World!</h1>")
}

let app = Router::new().route("/", get(handler));

How it works

IntoResponse implementation

The Html type is a simple wrapper that sets the content-type header:
impl<T> IntoResponse for Html<T>
where
    T: IntoResponse,
{
    fn into_response(self) -> Response {
        (
            [(header::CONTENT_TYPE, HeaderValue::from_static("text/html; charset=utf-8"))],
            self.0,
        )
            .into_response()
    }
}
See implementation in axum/src/response/mod.rs:32-53.

Type definition

pub struct Html<T>(pub T);
The inner value is public, allowing direct access and construction.

Response fields

Content-Type
header
Automatically set to text/html; charset=utf-8
body
T
The inner response body (must implement IntoResponse)

Common patterns

Serving static HTML

async fn index() -> Html<&'static str> {
    Html(
        r#"
        <!DOCTYPE html>
        <html>
            <head><title>My App</title></head>
            <body><h1>Welcome!</h1></body>
        </html>
        "#,
    )
}

With template rendering

use askama::Template;

#[derive(Template)]
#[template(path = "index.html")]
struct IndexTemplate {
    name: String,
}

async fn index() -> Html<String> {
    let template = IndexTemplate {
        name: "Alice".to_string(),
    };
    Html(template.render().unwrap())
}

Serving multipart forms

async fn show_form() -> Html<&'static str> {
    Html(
        r#"
        <!doctype html>
        <html>
            <head><title>Upload</title></head>
            <body>
                <form action="/upload" method="post" enctype="multipart/form-data">
                    <input type="file" name="file" multiple>
                    <input type="submit" value="Upload">
                </form>
            </body>
        </html>
        "#,
    )
}
Example from examples/stream-to-file/src/main.rs:60-85.

With custom status codes

use axum::http::StatusCode;

async fn not_found() -> (StatusCode, Html<&'static str>) {
    (
        StatusCode::NOT_FOUND,
        Html("<h1>404 - Page Not Found</h1>"),
    )
}

Using From trait

// Html implements From<T>
async fn handler() -> Html<String> {
    let html = String::from("<p>Hello</p>");
    html.into() // Calls Html::from()
}

See also