#websocket #websocket-client #ja3 #socket-client #web #ja4

rquest

一个快速的异步 Rust Http/WebSocket 客户端,支持 TLS/JA3/JA4/HTTP2 指纹伪装

6 个版本

0.20.50 2024 年 8 月 16 日
0.20.49 2024 年 8 月 16 日
0.11.103 2024 年 8 月 6 日
0.11.98 2024 年 7 月 29 日

#52 in HTTP 客户端

Download history 499/week @ 2024-07-25 938/week @ 2024-08-01 3392/week @ 2024-08-08 1853/week @ 2024-08-15

6,682 每月下载量

Apache-2.0

485KB
10K SLoC

rquest

CI Apache-2.0 Documentation crates.io Crates.io Total Downloads

一个快速的异步 Rust Http/WebSocket 客户端,支持 TLS/JA3/JA4/HTTP2 指纹伪装

  • Async 客户端
  • 纯文本、JSON、表单编码、多部分正文
  • 头部顺序
  • 可定制的重定向策略
  • Cookie 存储
  • HTTP/WebSocket 代理
  • HTTPS/WebSocket 通过 BoringSSL
  • 预配置的 TLS/HTTP2/Headers 设置
  • 变更日志

其他学习资源包括

用法

以下异步示例使用 Tokio 并启用一些可选功能,所以您的 Cargo.toml 可能如下所示

HTTP

[dependencies]
tokio = { version = "1", features = ["full"] }
rquest = "0.20"
use std::error::Error;
use rquest::tls::Impersonate;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    // Build a client to mimic Edge127
    let client = rquest::Client::builder()
        .impersonate(Impersonate::Edge127)
        .enable_ech_grease()
        .permute_extensions()
        .cookie_store(true)
        .build()?;

    // Use the API you're already familiar with
    let resp = client.get("https://tls.peet.ws/api/all").send().await?;
    println!("{}", resp.text().await?);

    Ok(())
}

WebSocket

[dependencies]
tokio = { version = "1", features = ["full"] }
rquest = { version = "0.20", features = ["websocket"] }
use futures_util::{SinkExt, StreamExt, TryStreamExt};
use rquest::{tls::Impersonate, Client, Message};
use std::error::Error;

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn Error>> {
    let websocket = rquest::websocket("wss://echo.websocket.org").await?;

    let (mut tx, mut rx) = websocket.split();

    tokio::spawn(async move {
        for i in 1..11 {
            tx.send(Message::Text(format!("Hello, World! #{i}")))
                .await
                .unwrap();
        }
    });

    while let Some(message) = rx.try_next().await? {
        match message {
            Message::Text(text) => println!("received: {text}"),
            _ => {}
        }
    }

    Ok(())
}

预配置的 TLS/HTTP2

[dependencies]
tokio = { version = "1", features = ["full"] }
rquest = "0.20"
use boring::ssl::{SslConnector, SslMethod};
use http::HeaderValue;
use rquest::{
    tls::{Http2FrameSettings, TlsExtensionSettings, TlsSettings},
    HttpVersionPref,
};
use rquest::{PseudoOrder, SettingsOrder};
use std::error::Error;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    // Create a pre-configured TLS settings
    let settings = TlsSettings::builder()
        .builder(SslConnector::builder(SslMethod::tls_client())?)
        .extension(
            TlsExtensionSettings::builder()
                .tls_sni(true)
                .http_version_pref(HttpVersionPref::All)
                .application_settings(true)
                .pre_shared_key(true)
                .enable_ech_grease(true)
                .permute_extensions(true)
                .build(),
        )
        .http2(
            Http2FrameSettings::builder()
                .initial_stream_window_size(6291456)
                .initial_connection_window_size(15728640)
                .max_concurrent_streams(1000)
                .max_header_list_size(262144)
                .header_table_size(65536)
                .enable_push(None)
                .headers_priority((0, 255, true))
                .headers_pseudo_order([
                    PseudoOrder::Method,
                    PseudoOrder::Scheme,
                    PseudoOrder::Authority,
                    PseudoOrder::Path,
                ])
                .settings_order([
                    SettingsOrder::InitialWindowSize,
                    SettingsOrder::MaxConcurrentStreams,
                ])
                .build(),
        )
        .build();

    // Build a client with pre-configured TLS settings
    let client = rquest::Client::builder()
        .use_preconfigured_tls(settings, |headers| {
            headers.insert("user-agent", HeaderValue::from_static("rquest"));
        })
        .enable_ech_grease()
        .permute_extensions()
        .build()?;

    // Use the API you're already familiar with
    let resp = client.get("https://tls.peet.ws/api/all").send().await?;
    println!("{}", resp.text().await?);

    Ok(())
}

需求

安装构建 BoringSSL 所需的环境

不要使用依赖于 OpenSSL 的包进行编译;它们的符号前缀相同,可能会导致链接 失败

贡献

如果您想提交您的贡献,请打开一个 Pull Request

获取帮助

您的问题可能已经在 issues 中得到解答

许可证

Apache-2.0 LICENSE

荣誉

该项目基于 reqwest 的分支。

依赖

~11–29MB
~579K SLoC