• Rust:axum学习笔记(2) response


    上一篇的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。

    最后再补1个返回图片的示例:

    use axum::{
        routing::get, Router,http::header::{HeaderMap,HeaderValue,HeaderName}
    };
    use std::fs::*;
    
    async fn image() -> (HeaderMap, Vec<u8>) {
        let mut headers = HeaderMap::new();
        headers.insert(
            HeaderName::from_static("content-type"),
            HeaderValue::from_static("image/png"),
        );
        (headers, read(String::from("/Users/Downloads/avatar.png")).unwrap())
    }
    

      

    参考链接:

    https://docs.rs/axum/0.4.3/axum/response/trait.IntoResponse.html

    https://docs.rs/axum/0.2.8/axum/#building-responses

  • 相关阅读:
    Http的响应结构
    jQuery ajax
    什么是序列化和反序列化
    Ubuntu 安装 Anaconda3 步骤
    mysql 带换行符的字符串数据插入数据库异常
    Elasticsearch之Analysis(分析器)
    python 使用 xlrd、xlwd读写excel表格
    测试
    elasticsearch中的mapping简介
    Elasticsearch索引的操作,利用kibana 创建/删除一个es的索引及mapping映射
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/axum_tutorial_2_response.html
Copyright © 2020-2023  润新知