Ntex是一個功能強大、實用且速度極快的 Rust 可組合Web服務框架。它是 Rust 中最快的 Web 框架之一,為 Web 伺服器開發提供了強大的抽象。
為什麼選擇 ntex?
以下是我使用 ntex 的主要原因:
- 效能:Ntex 是 Rust 中最快的 Web 框架之一。
- 符合人體工程學:Ntex 為 Web 伺服器開發提供了強大的抽象。
- 可組合:Ntex 設計為可組合,允許您使用簡單的元件構建複雜的 Web 伺服器。
- 生態系統:Ntex 擁有豐富的中介軟體、擴充套件和庫生態系統。
- 內建 http 客戶端:Ntex 提供內建的 http 客戶端,用於向其他伺服器發出請求。
- 執行時:Ntex 允許您在不同的執行時之間進行選擇,包括 tokio和 async-std。
設定專案
讓我們首先用 Cargo 建立一個新專案:
cargo new ntex-http-proxy cd ntex-http-proxy
|
新增 ntex 作為依賴項:
cargo add ntex --features tokio
從基本的 http 處理程式開始
讓我們首先建立一個Hello, World!以純文字格式返回的基本 http 處理程式:
use ntex::{http, web};
async fn forward() -> Result<web::HttpResponse, web::Error> { Ok( web::HttpResponse::Ok() .content_type(<font>"text/plain") .body("Hello, world!"), ) }
#[ntex::main] async fn main() -> std::io::Result<()> { web::server(move || { web::App::new() .state(http::Client::new()) .wrap(web::middleware::Logger::default()) .default_service(web::route().to(forward)) }) .bind(("0.0.0.0", 9090))? .run() .await }
|
讓我們分解一下程式碼:
- forward 是一個非同步函式,返回 web::HttpResponse 或 web::Error。
- main 是應用程式的入口點。 它是一個返回 std::io::Result<()> 的非同步函式。
- 我們使用 web::server 建立一個新的 ntex 網路伺服器,並傳遞一個返回 web::App 的閉包。
- 我們建立一個新的 http::Client 並將其新增到應用程式狀態。
- 我們為應用程式新增一個日誌中介軟體。
- 我們定義一個預設服務,將所有請求轉發到 forward 處理程式。 我們將伺服器繫結到 0.0.0.0:9090 並執行它。
執行程式碼:
cargo run curl http:<font>//localhost:9090<i>
|
新增代理處理程式
我們首先將url和futures_util新增到我們的依賴項中,以便能夠解析 URL 並將響應轉換為流:
cargo add url futures-util
然後我們更改程式碼以將請求轉發到另一臺伺服器:
use futures_util::TryStreamExt; use ntex::{http, web};
async fn forward( req: web::HttpRequest, body: ntex::util::Bytes, client: web::types::State<http::Client>, forward_url: web::types::State<url::Url>, ) -> Result<web::HttpResponse, web::Error> { let mut new_url = forward_url.get_ref().clone(); new_url.set_path(req.uri().path()); new_url.set_query(req.uri().query()); let forwarded_req = client.request_from(new_url.as_str(), req.head()); let res = forwarded_req .send_body(body) .await .map_err(web::Error::from)?; let mut client_resp = web::HttpResponse::build(res.status()); let stream = res.into_stream(); Ok(client_resp.streaming(stream)) }
#[ntex::main] async fn main() -> std::io::Result<()> { let forward_url = <font>"https://www.rust-lang.org".to_owned(); let forward_url = url::Url::parse(&forward_url) .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err))?; web::server(move || { web::App::new() .state(http::Client::new()) .state(forward_url.clone()) .wrap(web::middleware::Logger::default()) .default_service(web::route().to(forward)) }) .bind(("0.0.0.0", 9090))? .run() .await }
|
讓我們分解一下程式碼:
- 我們將url和futures_util新增到我們的依賴項中。
- 我們改變forward函式以將請求、主體、客戶端和 forward_url 作為引數。
- 我們透過克隆forward_url並從請求中設定路徑和查詢來建立一個新的url。
- 我們使用客戶端和新的 URL 建立一個新請求。
- 我們傳送請求的主體並等待響應。
- 我們用響應的狀態程式碼構建一個新的響應。
- 我們將響應轉換為流並返回它。
執行:
cargo run curl http:<font>//localhost:9090<i>
|
您應該在響應中看到 rust-lang.org 主頁。
結論
在本教程中,我們使用 ntex 建立了一個基本的 http 代理伺服器。 我們首先建立了一個簡單的 http 處理程式,以純文字格式返回 Hello, World! 然後,我們新增了一個代理處理程式,將請求轉發到另一臺伺服器。
我們使用 url 和 futures_util 板塊來解析 urls 並將響應轉換為流。 我們透過執行伺服器並向其發出請求來測試伺服器。
我們看到,伺服器成功地將請求轉發到目標伺服器,並返回了響應。
我們幾乎不需要編寫程式碼,就能編寫一個基本的 http 代理伺服器(不到 50 行程式碼),而且我們可以很容易地擴充套件它,增加更多的功能,如快取、速率限制、身份驗證等。