大数跨境

使用 ntex 在 rust 中实现基本 http 代理

使用 ntex 在 rust 中实现基本 http 代理 索引目录
2024-12-18
2

什么是 ntex?

Ntex是一个功能强大、实用且速度极快的 Rust 可组合网络服务框架。
它是 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("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))? .stop_runtime() .run() .await
}

让我们分解一下代码:

  • forwardweb::HttpResponse是一个返回 a或 a 的异步函数web::Error

  • main是我们应用程序的入口点。它是一个返回 的异步函数std::io::Result<()>

  • 我们创建一个新的 ntex 网络服务器web::server并传递一个返回的闭包web::App

  • 我们创建一个新的http::Client并将其添加到应用程序状态。

  • 我们向应用程序添加了一个记录器中间件。

  • 我们定义一个默认服务,将所有请求转发给forward处理程序。

  • 我们绑定服务器0.0.0.0:9090并运行它。

让我们运行该服务器来测试它:

cargo run
curl http://localhost:9090

您应该Hello, world!在回应中看到。

添加代理处理程序

我们首先将urlfutures_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 = "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}


让我们分解一下代码:

  • 我们将urlfutures_util板条箱添加到我们的依赖项中。

  • 我们改变forward函数以将请求、主体、客户端和 forward_url 作为参数。

  • 我们通过克隆forward_url并从请求中设置路径和查询来创建一个新的url。

  • 我们使用客户端和新的 URL 创建一个新请求。

  • 我们发送请求的主体并等待响应。

  • 我们用响应的状态代码构建一个新的响应。

  • 我们将响应转换为流并返回它。

让我们运行该服务器来测试它:

cargo run
curl http://localhost:9090

您应该在响应中看到 rust-lang.org 主页。

结论

在本教程中,我们使用 ntex 创建了一个基本的 http 代理服务器。我们首先创建一个Hello, World!以纯文本格式返回的简单 http 处理程序。然后,我们添加了一个将请求转发到另一台服务器的代理处理程序。我们使用urlfutures_utilcrate 来解析 URL 并将响应转换为流。我们通过运行服务器并向其发出请求来测试服务器。我们看到服务器成功将请求转发到目标服务器并返回响应。
我们几乎没有代码来编写一个基本的 http 代理服务器(不到 50 行代码),我们可以轻松地使用更多功能(如缓存、速率限制、身份验证等)对其进行扩展。



【声明】内容源于网络
0
0
索引目录
索引目录是一家专注于医疗、技术开发、物联网应用等领域的创新型公司。我们致力于为客户提供高质量的服务和解决方案,推动技术与行业发展。
内容 444
粉丝 0
索引目录 索引目录是一家专注于医疗、技术开发、物联网应用等领域的创新型公司。我们致力于为客户提供高质量的服务和解决方案,推动技术与行业发展。
总阅读12
粉丝0
内容444