如何使用 Rust 構建基本的 HTTP Web Server?

譯者 | 布加迪

審校 | 重樓

本文介紹瞭如何使用 Rust 的 Actix 或 Rocket 軟件包構建自定義 HTTP Web 服務器。  

HTTP 利用客戶端 / 服務器架構來傳輸信息和數據。Rust 等服務器端編程語言的特性之一是,開發用於與基於 HTTP 的服務交互的服務器和客戶端應用程序。

Rust 因其安全性、性能和可靠性等特性而適合構建 HTTP 服務器系統。Rust 的第三方庫(比如 Actix 和 Rocket)因構建能夠處理高流量的複雜 Web 服務器而大受歡迎。

爲什麼應該使用

Rust 進行 HTTP Web 服務器開發?

Rust 在 Web 服務器開發方面大受歡迎,因爲該語言的一些特性正是構建大多數 Web 服務器所需要的。

使用 Rust 可以確保應用程序有效擴展,使該語言成爲構建高性能應用程序的理想語言。以下是考慮爲 Web 服務器及其他服務器端應用程序使用 Rust 的幾個具體原因。

Rust 的高性能

高性能是 Rust 成爲構建 HTTP Web 服務器絕佳選擇的原因之一。Rust 提供了對系統資源(包括內存和 CPU)的低級訪問,使您能夠編寫比其他服務器端語言使用更少資源運行得更快的代碼。

此外,Rust 的所有權機制不需要編譯時收集垃圾,這是一些服務器端語言速度較慢的原因之一。

安全和保障

Rust 的內存管理所有權機制使得該語言對於 Web 服務器開發而言很安全。您不會遇到可能導致內存泄漏及其他安全漏洞的空指針或懸空指針引用。

Rust 的所有權機制可以防止這些常見錯誤,爲您的服務器和應用程序確保安全。Rust 還專注於防止緩衝區溢出及其他與內存相關的錯誤。

併發性

併發性是指能夠以無序的方式運行程序的多個單元而不影響輸出。併發程序的輸出應該與異步程序的輸出相同。

併發性會顯著影響應用程序的性能,因爲服務器需要同時處理多個請求。Rust 支持與輕量級線程模型共存。

Rust 中併發編程的優勢在於,所有權機制讓您可以編寫線程安全的代碼,不需要鎖及其他同步原語。

Rust 提供現代工具

Rust 標準庫和 Rust 生態系統中的第三方軟件包爲有效的 Web 服務器開發提供了現代工具。

Rust 的軟件包管理器 Cargo 簡化了依賴項管理和構建流程。此外,Rust 還通過 Rust Analyzer 等工具提供了出色的 IDE 支持,這類工具提供了無縫代碼補全、錯誤高亮顯示及其他特性。

Actix 庫和 Rocket 庫概述

Rust 的標準庫擁有構建 Web 服務器所需的大部分實用程序。像 Rocket 和 Actix 這樣的第三方庫簡化了用 Rust 服務器端應用程序的工作。

Actix 和 Rocket 是流行的 Rust Web 框架,但它們的庫在設計和特性上有所不同。

Rocket 是一種高級 Web 框架,注重生產力和易用性。Rocket 爲使用 Rust 構建 Web 應用程序提供了大量的抽象和語法元素。Rocket 也因其強大的類型和直觀的 API 設計而頗受歡迎。

您可以在 Cargo.toml 文件中添加 Rocket 作爲項目依賴項,從而開始使用 Rust 構建 Web 應用程序:

[dependencies]

rocket = "0.4.11"

另一方面,Actix-web 是一個注重性能和可擴展性的低級框架。Actix 利用了基於 actor 的併發模型,提供了非阻塞 I/O,這使得該軟件包成爲構建高性能 Web 應用程序的理想選擇。

在 Cargo.toml 文件的依賴項部分中添加 Actix 作爲項目依賴項:

[dependencies]

actix-web = "4.3.1"

爲項目選擇一個庫將取決於您項目的規範、庫的特性以及您在使用 Rust 和 HTTP 方面的經驗。

使用 Rust 構建簡單的 Web 服務器

在創建 Rust 項目並將任何 Rocket 或 Actix 框架添加到 Cargo.toml 文件中的項目依賴項之後,您已準備好開始使用 Rust 構建 Web 服務器了。

使用 Actix 構建簡單的 Web 服務器

使用 Rust 構建 Web 服務時,您可以爲請求使用序列化器。

Serde 是一個流行的 Rust 庫,用於在 Rust 類型與 JSON、YAML 和 TOML 等數據格式之間序列化和反序列化數據。Serde 提供了一個框架,用於定義 Rust 數據結構與其他數據格式的對應表示之間的數據轉換。

下面是爲您的項目添加 Serde 作爲第三方軟件包的指令。

[dependencies]

serde = { version = "1.0.159" , features = ["derive"] }

左右滑動查看完整代碼

一旦您添加了 Serde 和 Actix 作爲項目依賴項,就可以用 Rust 生成基本的 Web 服務器。下面介紹瞭如何創建一個簡單的 Hello World! Web 服務器,使用 Actix 將字符串寫入到客戶端:

首先,從 actix_web 庫和 serde 庫導入必要的模塊和類型:

use actix_web::{get, web, App, HttpResponse, HttpServer, Responder};

use serde::{Deserialize, Serialize};

左右滑動查看完整代碼

您將使用 serde 用構件(struct)將消息序列化到客戶端。serde 將爲客戶端將構件轉換成 JSON。下面是該消息的構件:

#[derive(Debug, Serialize, Deserialize)]

struct Message {

    message: String,

}

現在您可以爲端點定義處理程序(handler)函數。在處理程序函數的頂部,您可以爲自定義行爲添加裝飾符:

#[get("/")]

async fn hello() -> impl Responder {

    HttpResponse::Ok().json(Message {

        message: "Hello, World!".to_owned(),

    })

}

hello 處理程序函數處理 GET 請求。該函數返回實現來自 Actix 軟件包的 Responder 特徵的類型。

HttpResponse::Ok() 類型的 JSON 方法接受 Serde 在底層處理的構件實例,並將響應返回給客戶端。

定義端點後,您可以啓動服務器實例,並將端點掛載到路由上。

#[actix_web::main]

async fn main() -> std::io::Result<(){

    HttpServer::new(|| App::new().service(hello))

        .bind("127.0.0.1:8080")?

        .run()

        .await

}

HttpServer::new 函數是一個新的服務器實例。main 函數啓動,服務器用新的應用程序實例掛載 hello 處理程序函數。bind 方法將服務器綁定到指定的 URL,run 函數運行服務器。

使用 Rocket 構建簡單的 Web 服務器

Rocket 很簡約,所以您可以構建簡單的 Web 服務器,無需任何依賴項(除了 Rocket 庫外)。

下面介紹如何使用 Rocket 創建帶有 Hello World! 端點的簡單服務器:

首先,爲服務器導入必要的依賴項。

#![feature(proc_macro_hygiene, decl_macro)]

#[macro_use]

extern crate rocket;

// imports from the Rocket crate

use rocket::response::content;

use rocket::State;

#![feature(proc_macro_hygiene, decl_macro)] 屬性爲 Rocket 框架啓用了 Rust 實驗特性。#[macro_use] 屬性從 Rocket 模塊導入宏。

下面是一個處理程序函數,接到請求時提供 HTML:

#[get("/")]

fn hello_world() -> content::Html<&'static str> {

    content::Html("<h1>Hello, world!</h1>")

}

hello_world 函數返回一個 HTML 靜態字符串,含有 content:: HTML 函數。

下面是服務器的配置構件聲明(Rocket 框架約定):

struct Config {

    port: u16,

}

#[get("/port")]

fn port(config: State<Config>) -> String {

    format!("Server running on port {}", config.port)

}

運行服務器時,可以向 / port 端點請求端口狀態。

最後,您將使用 ignite 函數創建一個服務器實例。添加配置、掛載路由,並啓動服務器:

fn main() {

    let config = Config { port: 8000 };

    rocket::ignite()

        .manage(config)

        .mount("/", routes![hello_world, port])

        .launch();

}

config 變量是 config 構件的一個實例。ignite 函數啓動服務器實例,manage 方法爲服務器添加配置,mount 方法在基本路由上掛載處理程序函數。最後,launch 方法啓動服務器以偵聽指定的端口。

藉助 WASM 使用

Rust 構建功能強大的 Web 應用程序

WebAssembly(WASM)是一種二進制指令格式,是爲了在瀏覽器及其他設備上執行而設計的。WASM 提供了一種低級字節碼格式,Rust 等高級編程語言可以將其用作編譯目標。

藉助 WASM,您可以將 Rust 代碼編譯成大多數流行瀏覽器都可以執行的二進制格式。WASM 爲使用 Rust 構建健壯的 Web 應用程序(包括全棧 Web 應用程序)提供了無限的可能。

原文鏈接:

https://www.makeuseof.com/build-http-web-server-in-rust/

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/iH1_TYGdBHA9qLsLkCMsWg