WEBKT

Rust Web 开发实战:手把手教你构建支持 JSON 响应的 HTTP 服务器

149 0 0 0

本文将带你使用 Rust 构建一个简单的 HTTP 服务器,它可以处理 GET 和 POST 请求,并返回 JSON 格式的数据。我们将使用 tokio 作为异步运行时,hyper 作为 HTTP 库,serdeserde_json 用于 JSON 序列化和反序列化。

准备工作

确保你已经安装了 Rust 和 Cargo。如果还没有安装,可以访问 https://www.rust-lang.org/ 获取安装指南。

创建项目

首先,创建一个新的 Rust 项目:

cargo new json_http_server
cd json_http_server

添加依赖

接下来,我们需要添加必要的依赖项到 Cargo.toml 文件中:

[dependencies]
hyper = { version = "0.14", features = ["full"] }
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
futures = "0.3"
  • hyper: 用于处理 HTTP 请求和响应。
  • tokio: 提供异步运行时环境。
  • serdeserde_json: 用于 JSON 序列化和反序列化。
  • futures: 用于异步编程。

编写代码

现在,让我们开始编写 src/main.rs 文件:

use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Request, Response, Server, Method, StatusCode};
use serde::{Serialize, Deserialize};
use serde_json::json;
use std::convert::Infallible;
use std::net::SocketAddr;
use futures::executor::block_on;

// 定义一个用于序列化和反序列化的结构体
#[derive(Serialize, Deserialize)]
struct User {
    id: u32,
    name: String,
}

// 处理 GET 请求
async fn handle_get() -> Result<Response<Body>, Infallible> {
    let user = User { id: 1, name: "Alice".to_string() };
    let json_body = serde_json::to_string(&user).unwrap();
    Ok(Response::builder()
        .status(StatusCode::OK)
        .header("Content-Type", "application/json")
        .body(Body::from(json_body))
        .unwrap())
}

// 处理 POST 请求
async fn handle_post(req: Request<Body>) -> Result<Response<Body>, Infallible> {
    // 读取请求体
    let body = hyper::body::to_bytes(req.into_body()).await.unwrap();
    let body_str = String::from_utf8(body.to_vec()).unwrap();

    // 尝试将请求体反序列化为 User 结构体
    match serde_json::from_str::<User>(&body_str) {
        Ok(user) => {
            println!("Received user: {:?}", user);
            // 返回一个包含接收到的用户信息的 JSON 响应
            let response_json = json!({ "message": format!("User received: {}", user.name) }).to_string();
            Ok(Response::builder()
                .status(StatusCode::OK)
                .header("Content-Type", "application/json")
                .body(Body::from(response_json))
                .unwrap())
        }
        Err(e) => {
            eprintln!("Error deserializing user: {:?}", e);
            Ok(Response::builder()
                .status(StatusCode::BAD_REQUEST)
                .body(Body::from("Invalid JSON"))
                .unwrap())
        }
    }
}

// 处理请求的函数
async fn handle_request(req: Request<Body>) -> Result<Response<Body>, Infallible> {
    match (req.method(), req.uri().path()) {
        (&Method::GET, "/") => {
            handle_get().await
        }
        (&Method::POST, "/") => {
            handle_post(req).await
        }
        _ => {
            // 返回 404 状态码
            let mut not_found = Response::default();
            *not_found.status_mut() = StatusCode::NOT_FOUND;
            Ok(not_found)
        }
    }
}

#[tokio::main]
async fn main() {
    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));

    let make_svc = make_service_fn(|_conn| {
        async {
            Ok::<_, Infallible>(service_fn(handle_request))
        }
    });

    let server = Server::bind(&addr).serve(make_svc);

    println!("Server listening on http://{}", addr);

    // 运行服务器
    if let Err(e) = server.await {
        eprintln!("server error: {}", e);
    }
}

代码解释

  • User 结构体: 定义了一个简单的 User 结构体,用于表示用户信息,并使用 serdeSerializeDeserialize trait 来支持 JSON 序列化和反序列化。
  • handle_get 函数: 处理 GET 请求,创建一个 User 实例,将其序列化为 JSON 字符串,并返回包含 JSON 数据的响应。
  • handle_post 函数: 处理 POST 请求,从请求体中读取数据,尝试将其反序列化为 User 结构体,如果成功,则打印用户信息并返回包含接收到的用户信息的 JSON 响应;如果失败,则返回一个包含错误信息的 400 状态码响应。
  • handle_request 函数: 路由请求,根据请求的方法和路径调用相应的处理函数。如果请求的方法和路径不匹配,则返回 404 状态码。
  • main 函数: 创建一个 HTTP 服务器,监听 3000 端口,并使用 handle_request 函数处理所有请求。

运行服务器

使用以下命令运行服务器:

cargo run

你将会看到类似以下的输出:

Server listening on http://127.0.0.1:3000

测试服务器

使用 curl 测试 GET 请求

curl http://127.0.0.1:3000/

你应该会看到以下 JSON 响应:

{"id":1,"name":"Alice"}

使用 curl 测试 POST 请求

curl -X POST -H "Content-Type: application/json" -d '{"id":2,"name":"Bob"}' http://127.0.0.1:3000/

你应该会看到以下 JSON 响应:

{"message":"User received: Bob"}

同时,在服务器的控制台中,你将会看到以下输出:

Received user: User { id: 2, name: "Bob" }

总结

本文介绍了如何使用 Rust 构建一个简单的 HTTP 服务器,它可以处理 GET 和 POST 请求,并返回 JSON 格式的数据。通过这个例子,你可以学习到如何使用 tokiohyperserdeserde_json 等库进行 Web 开发。希望这篇文章能够帮助你快速上手 Rust Web 开发。

RustyCrab RustWeb 开发HTTP 服务器

评论点评