当前位置:   article > 正文

Rust Web开发actix-web框架响应静态文件和HTML网页文件_actix-web 静态页面

actix-web 静态页面

目录结构

在这里插入图片描述

Cargo.toml

[package]
name = "c01_hello_world"
version = "0.1.0"
edition = "2021"

[dependencies]
actix-files.workspace = "0.6"
actix-session = { workspace = "0.9", features = ["cookie-session"] }
actix-web = "4.4"
async-stream = "0.3"
env_logger = "0.11"
log = "0.4"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

main.rs

use std::{convert::Infallible, io};

use actix_files::{Files, NamedFile};
use actix_session::{storage::CookieSessionStore, Session, SessionMiddleware};
use actix_web::{
    error, get,
    http::{
        header::{self, ContentType},
        Method, StatusCode,
    },
    middleware, web, App, Either, HttpRequest, HttpResponse, HttpServer, Responder, Result,
};
use async_stream::stream;

// 设置session的秘钥
static SESSION_SIGNING_KEY: &[u8] = &[0; 64];

/// 设置网站图标的获取方式
#[get("/favicon")]
async fn favicon() -> Result<impl Responder> {
    Ok(NamedFile::open("static/favicon.ico")?)
}

/// 设置首页的访问方式
#[get("/welcome")]
async fn welcome(req: HttpRequest, session: Session) -> Result<HttpResponse> {
    println!("{req:?}");

    // 记录session
    let mut counter = 1;

    // 从session中获取值,如果存在,则+1
    if let Some(count) = session.get::<i32>("counter")? {
        println!("SESSION value: {count}");
        counter = count + 1;
    }

    // 设置session的值
    session.insert("counter", counter)?;

    // 返回响应
    Ok(HttpResponse::build(StatusCode::OK)
        .content_type(ContentType::plaintext())
        .body(include_str!("../static/welcome.html")))
}

// 默认处理器,处理404错误
async fn default_handler(req_method: Method) -> Result<impl Responder> {
    match req_method {
        // 如果是GET请求
        Method::GET => {
            // 打开404网页
            let file = NamedFile::open("static/404.html")?
                .customize()
                .with_status(StatusCode::NOT_FOUND);
            // 返回网页内容
            Ok(Either::Left(file))
        }
        // 默认,返回不允许的请求方法
        _ => Ok(Either::Right(HttpResponse::MethodNotAllowed().finish())),
    }
}

/// 响应体
async fn response_body(path: web::Path<String>) -> HttpResponse {
    // 获取请求路径
    let name = path.into_inner();

    HttpResponse::Ok()
        // 纯文本类型
        .content_type(ContentType::plaintext())
        // 流式响应
        .streaming(stream! {
            yield Ok::<_, Infallible>(web::Bytes::from("Hello "));
            yield Ok::<_, Infallible>(web::Bytes::from(name));
            yield Ok::<_, Infallible>(web::Bytes::from("!"));
        })
}

/// 处理带路径参数的响应 `/user/{name}/`
async fn with_param(req: HttpRequest, path: web::Path<(String,)>) -> HttpResponse {
    println!("{req:?}");

    HttpResponse::Ok()
        .content_type(ContentType::plaintext())
        .body(format!("Hello {}!", path.0))
}

#[actix_web::main]
async fn main() -> io::Result<()> {
    // 初始化日志
    env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));

    // 随机密钥意味着重新启动服务器将使现有的会话cookie失效
    let key = actix_web::cookie::Key::from(SESSION_SIGNING_KEY);

    log::info!("starting HTTP server at http://localhost:8080");

    HttpServer::new(move || {
        App::new()
            // 启用自动响应压缩-通常先注册这个
            .wrap(middleware::Compress::default())
            // Cookie会话中间件
            .wrap(
                SessionMiddleware::builder(CookieSessionStore::default(), key.clone())
                    .cookie_secure(false)
                    .build(),
            )
            // 启用logger -总是最后注册Actix Web logger中间件
            .wrap(middleware::Logger::default())
            // 图标路由
            .service(favicon)
            // /welcome 欢迎路由
            .service(welcome)
            // /user/zhangdapeng 路径参数路由
            .service(web::resource("/user/{name}").route(web::get().to(with_param)))
            // /async-body/zhangdapeng 异步响应路由
            .service(web::resource("/async-body/{name}").route(web::get().to(response_body)))
            // /test 测试路由
            .service(
                web::resource("/test").to(|req: HttpRequest| match *req.method() {
                    Method::GET => HttpResponse::Ok(),
                    Method::POST => HttpResponse::MethodNotAllowed(),
                    _ => HttpResponse::NotFound(),
                }),
            )
            // /error 错误路由
            .service(web::resource("/error").to(|| async {
                error::InternalError::new(
                    io::Error::new(io::ErrorKind::Other, "test"),
                    StatusCode::INTERNAL_SERVER_ERROR,
                )
            }))
            // 静态文件
            .service(Files::new("/static", "static").show_files_listing())
            // 重定向
            .service(
                web::resource("/").route(web::get().to(|req: HttpRequest| async move {
                    println!("{req:?}");
                    HttpResponse::Found()
                        .insert_header((header::LOCATION, "static/welcome.html"))
                        .finish()
                })),
            )
            // 默认路由
            .default_service(web::to(default_handler))
    })
        .bind(("127.0.0.1", 8080))?
        .workers(2)
        .run()
        .await
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152

404.html

<!DOCTYPE html>
<html>

<head>
  <title>actix - basics</title>
  <link rel="shortcut icon" type="image/x-icon" href="/favicon">
</head>

<body>
  <a href="/static/welcome.html">back to home</a>
  <h1>404</h1>
</body>

</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

welcom.html

<!DOCTYPE html>
<html>

<head>
  <title>actix - basics</title>
  <link rel="shortcut icon" type="image/x-icon" href="/favicon">
</head>

<body>
  <h1>Welcome <img width="30" height="30" src="/static/actixLogo.png"></h1>
</body>

</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

访问:http://localhost:8080/static/actixLogo.png

在这里插入图片描述

访问:http://localhost:8080/

在这里插入图片描述

访问:http://localhost:8080/user/zhangdapeng

在这里插入图片描述

访问:http://localhost:8080/async-body/zhangdapeng

在这里插入图片描述

访问:http://localhost:8080/async-body111/zhangdapeng

在这里插入图片描述

核心代码1:如何响应静态文件

use std::{convert::Infallible, io};

use actix_files::{Files, NamedFile};
use actix_session::{storage::CookieSessionStore, Session, SessionMiddleware};
use actix_web::{
    error, get,
    http::{
        header::{self, ContentType},
        Method, StatusCode,
    },
    middleware, web, App, Either, HttpRequest, HttpResponse, HttpServer, Responder, Result,
};

/// 设置网站图标的获取方式
#[get("/favicon")]
async fn favicon() -> Result<impl Responder> {
    Ok(NamedFile::open("static/favicon.ico")?)
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

核心代码2:如何操作session和响应HTML

/// 设置首页的访问方式
#[get("/welcome")]
async fn welcome(req: HttpRequest, session: Session) -> Result<HttpResponse> {
    println!("{req:?}");

    // 记录session
    let mut counter = 1;

    // 从session中获取值,如果存在,则+1
    if let Some(count) = session.get::<i32>("counter")? {
        println!("SESSION value: {count}");
        counter = count + 1;
    }

    // 设置session的值
    session.insert("counter", counter)?;

    // 返回响应
    Ok(HttpResponse::build(StatusCode::OK)
        .content_type(ContentType::plaintext())
        .body(include_str!("../static/welcome.html")))
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

核心代码3:如何处理404错误

// 默认处理器,处理404错误
async fn default_handler(req_method: Method) -> Result<impl Responder> {
    match req_method {
        // 如果是GET请求
        Method::GET => {
            // 打开404网页
            let file = NamedFile::open("static/404.html")?
                .customize()
                .with_status(StatusCode::NOT_FOUND);
            // 返回网页内容
            Ok(Either::Left(file))
        }
        // 默认,返回不允许的请求方法
        _ => Ok(Either::Right(HttpResponse::MethodNotAllowed().finish())),
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

核心代码4:如何实现异步响应流

// 默认处理器,处理404错误
async fn default_handler(req_method: Method) -> Result<impl Responder> {
    match req_method {
        // 如果是GET请求
        Method::GET => {
            // 打开404网页
            let file = NamedFile::open("static/404.html")?
                .customize()
                .with_status(StatusCode::NOT_FOUND);
            // 返回网页内容
            Ok(Either::Left(file))
        }
        // 默认,返回不允许的请求方法
        _ => Ok(Either::Right(HttpResponse::MethodNotAllowed().finish())),
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

核心代码5:如何处理路径参数

/// 处理带路径参数的响应 `/user/{name}/`
async fn with_param(req: HttpRequest, path: web::Path<(String,)>) -> HttpResponse {
    println!("{req:?}");

    HttpResponse::Ok()
        .content_type(ContentType::plaintext())
        .body(format!("Hello {}!", path.0))
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/889220
推荐阅读
相关标签
  

闽ICP备14008679号