上一篇的hello world里,示例过于简单,仅仅只是返回了一个字符串,实际上axum的response能返回各种格式,包括:
plain_text
html
json
http StatusCode
...
web开发中需要的各种格式,都能返回。talk is cheap ,show me the code! 直接上代码:
axum = "0.4.3"
tokio = { version="1", features = ["full"] }
serde = { version="1", features = ["derive"] }
serde_json = "1"
http = "0.2.1"
这是依赖项,下面的代码主要来自官方文档,在此基础上补充了中文及“自定义错误”及“自定义结构”的返回示例(包括了web开发中大部分的常用返回格式)
use axum::{
body::{self,Body},
http::header::{HeaderMap, HeaderName, HeaderValue},
response::{Headers, Html, IntoResponse, Json,Response},
routing::get,
Router,
};
use http::{ StatusCode, Uri};
use serde::Serialize;
use serde_json::{json, Value};
// We've already seen returning &'static str
async fn plain_text() -> &'static str {
"foo"
}
// String works too and will get a `text/plain; charset=utf-8` content-type
async fn plain_text_string(uri: Uri) -> String {
format!("Hi from {}", uri.path())
}
// Bytes will get a `application/octet-stream` content-type
async fn bytes() -> Vec<u8> {
vec![1, 2, 3, 4]
}
// `()` gives an empty response
async fn empty() {}
// `StatusCode` gives an empty response with that status code
async fn empty_with_status() -> StatusCode {
StatusCode::NOT_FOUND
}
// A tuple of `StatusCode` and something that implements `IntoResponse` can
// be used to override the status code
async fn with_status() -> (StatusCode, &'static str) {
(StatusCode::INTERNAL_SERVER_ERROR, "Something went wrong")
}
// A tuple of `HeaderMap` and something that implements `IntoResponse` can
// be used to override the headers
async fn with_headers() -> (HeaderMap, &'static str) {
let mut headers = HeaderMap::new();
headers.insert(
HeaderName::from_static("x-foo"),
HeaderValue::from_static("foo"),
);
(headers, "foo")
}
// You can also override both status and headers at the same time
async fn with_headers_and_status() -> (StatusCode, HeaderMap, &'static str) {
let mut headers = HeaderMap::new();
headers.insert(
HeaderName::from_static("x-foo"),
HeaderValue::from_static("foo"),
);
(StatusCode::INTERNAL_SERVER_ERROR, headers, "foo")
}
// `Headers` makes building the header map easier and `impl Trait` is easier
// so you don't have to write the whole type
async fn with_easy_headers() -> impl IntoResponse {
Headers(vec![("x-foo", "foo")])
}
// `Html` gives a content-type of `text/html`
async fn html() -> Html<&'static str> {
Html("<h1>Hello, World!</h1>")
}
// `Json` gives a content-type of `application/json` and works with any type
// that implements `serde::Serialize`
async fn json() -> Json<Value> {
Json(json!({ "data": 42 }))
}
// `Result<T, E>` where `T` and `E` implement `IntoResponse` is useful for
// returning errors
async fn result() -> Result<&'static str, StatusCode> {
Ok("all good")
}
// `Response` gives full control
async fn response() -> Response<Body> {
Response::builder().body(Body::empty()).unwrap()
}
#[derive(Serialize)]
struct Blog {
title: String,
author: String,
summary: String,
}
async fn blog_struct() -> Json<Blog> {
let blog = Blog {
title: "axum笔记(2)-response".to_string(),
author: "菩提树下的杨过".to_string(),
summary: "response各种示例".to_string(),
};
Json(blog)
}
async fn blog_struct_cn() -> (HeaderMap, Json<Blog>) {
let blog = Blog {
title: "axum笔记(2)-response".to_string(),
author: "菩提树下的杨过".to_string(),
summary: "response各种示例".to_string(),
};
let mut headers = HeaderMap::new();
headers.insert(
HeaderName::from_static("content-type"),
HeaderValue::from_static("application/json;charset=utf-8"),
);
(headers, Json(blog))
}
struct CustomError {
msg: String,
}
impl IntoResponse for CustomError {
fn into_response(self) -> Response {
let body= body::boxed(body::Full::from(self.msg));
Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.body(body)
.unwrap()
}
}
async fn custom_error() -> Result<&'static str, CustomError> {
Err(CustomError {
msg: "Opps!".to_string(),
})
}
#[tokio::main]
async fn main() {
// our router
let app = Router::new()
.route("/plain_text", get(plain_text))
.route("/plain_text_string", get(plain_text_string))
.route("/bytes", get(bytes))
.route("/empty", get(empty))
.route("/empty_with_status", get(empty_with_status))
.route("/with_status", get(with_status))
.route("/with_headers", get(with_headers))
.route("/with_headers_and_status", get(with_headers_and_status))
.route("/with_easy_headers", get(with_easy_headers))
.route("/html", get(html))
.route("/json", get(json))
.route("/result", get(result))
.route("/response", get(response))
.route("/blog", get(blog_struct))
.route("/blog_cn", get(blog_struct_cn))
.route("/custom_error", get(custom_error));
// run it with hyper on localhost:3000
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
.serve(app.into_make_service())
.await
.unwrap();
}
部分url的访问效果如上图,其它的就留给朋友们自己去尝试吧。注:网上传说的中文乱码问题,0.4.3新版本并没有出现,输出时已经自带了chatset=utf-8。
参考链接:
https://docs.rs/axum/0.4.3/axum/response/trait.IntoResponse.html