You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否用NewType惯用法适配跨Crate类型?rustls适配worker::Socket遇阻

在Cloudflare Worker中为worker::Socket添加TLS/HTTPS支持(适配rustls)

问题核心

worker::Socket未实现std::io::Read/Write同步IO trait,且本身是异步API;而rustls的同步Stream依赖同步IO,同时Cloudflare Worker的WASM环境不允许阻塞式同步IO,因此必须适配异步IO接口来解决问题。

解决方案:rustls异步API + Socket适配器

1. 实现AsyncRead/AsyncWrite适配器

worker::Socket原生已实现异步读写的底层逻辑,只需创建适配器将其转换为futures_io::AsyncRead和AsyncWrite(rustls异步API依赖的trait):

use futures_io::{AsyncRead, AsyncWrite};
use worker::Socket;
use std::pin::Pin;
use std::task::{Context, Poll};

// 包装worker::Socket的适配器
pub struct SocketAdapter(Socket);

impl SocketAdapter {
    pub fn new(socket: Socket) -> Self {
        Self(socket)
    }
}

// 转发异步read调用
impl AsyncRead for SocketAdapter {
    fn poll_read(
        mut self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &mut [u8],
    ) -> Poll<std::io::Result<usize>> {
        Pin::new(&mut self.0).poll_read(cx, buf)
    }
}

// 转发异步write/flush/close调用
impl AsyncWrite for SocketAdapter {
    fn poll_write(
        mut self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &[u8],
    ) -> Poll<std::io::Result<usize>> {
        Pin::new(&mut self.0).poll_write(cx, buf)
    }

    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
        Pin::new(&mut self.0).poll_flush(cx)
    }

    fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
        Pin::new(&mut self.0).poll_close(cx)
    }
}

2. 使用rustls异步流包装Socket

用rustls::StreamAsync替代同步Stream,配合异步客户端连接完成TLS握手:

use rustls::client::ClientConnection;
use rustls::StreamAsync;
use std::sync::Arc;
use futures_util::io::{AsyncReadExt, AsyncWriteExt};

async fn establish_tls_connection(res: /* 你的目标地址结构体 */) -> worker::Result<()> {
    // 构建rustls客户端配置
    let root_store = rustls::RootCertStore::from_iter(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
    let config = rustls::ClientConfig::builder_with_provider(rustls_rustcrypto::provider().into())
        .with_safe_default_protocol_versions()
        .unwrap()
        .with_root_certificates(root_store)
        .with_no_client_auth();

    // 创建客户端TLS连接
    let server_name = res.host.clone().try_into().unwrap();
    let conn = ClientConnection::new(Arc::new(config), server_name).unwrap();

    // 连接Worker Socket并包装适配器
    let sock = Socket::builder().connect(res.host, res.port).await?;
    let mut tls_stream = StreamAsync::new(conn, SocketAdapter::new(sock));

    // 示例:发送HTTP请求并读取响应
    tls_stream.write_all(b"GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n").await?;
    
    let mut buf = Vec::new();
    tls_stream.read_to_end(&mut buf).await?;
    console_log!("Response: {}", String::from_utf8_lossy(&buf));

    Ok(())
}

关键说明

  • 适配器仅转发worker::Socket原生的异步方法,无需额外逻辑,代码量极小。
  • 必须使用rustls的异步StreamAsync,因为Cloudflare Worker runtime是纯异步环境,不支持阻塞式同步IO。
  • 确保依赖中包含futures-io、futures-util、rustls、rustls-rustcrypto和webpki-roots。

内容的提问来源于stack exchange,提问作者lopass

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 13:40:03