17 个稳定版本 (5 个主要版本)

125.0.1 2024 年 3 月 28 日
123.0.1 2024 年 2 月 1 日
122.0.2 2024 年 1 月 11 日
120.0.2 2023 年 11 月 29 日
96.4.0 2023 年 1 月 31 日

#1202 in 网络编程

598 星 & 48 关注者

MPL-2.0 许可证

66KB
1.5K SLoC

Rust 1K SLoC // 0.1% comments Kotlin 147 SLoC // 0.2% comments Prolog 18 SLoC Swift 11 SLoC // 0.5% comments

桥梁

桥梁是我们的 HTTP 请求库,可以通过基于 Rust 的(reqwest)网络栈(用于 iOS 和本地桌面使用、测试等)或通过 FFI 调用传入函数的栈(用于 Android)来发起请求。

有关使用信息,您可以运行 cargo +nightly doc -p viaduct+nightly 是可选的,但一些文档内的链接需要它),它包含多个示例。

Android/FFI 后端概述

在 Android 上,后端的工作方式如下

  1. 在 Megazord 初始化期间,我们接收一个 Lazy<Client>Client 来自 concept-fetch Android 组件,而 Lazy 来自 Kotlin 标准库)。

    • 它还设置了一个标志,表示即使 FFI 后端从未完全初始化(例如,使用回调),我们也应该报错而不是使用 reqwest 后端(尽管我们过去在确保这一点上遇到过麻烦,尽管到现在我们在 CI 中有检查以确保它不存在)。
  2. 此时,创建了一个 JNA Callback 实例,并将其传递给 Rust。

    • 这用于代理 Rust 发出的请求到 Client
    • Callback 实例不允许被垃圾回收。
    • 对于 Rust 来说,它只是一个存储在原子变量中的 extern "C" 函数指针,并且永远不会被重置。
  3. 当 Rust 发出请求时

    1. 我们将请求信息序列化为 protobuf 记录
    2. 此记录传递到我们此时应该拥有的函数指针(如果尚未设置,则报错)。
    3. 回调(现在在 Java 端)反序列化 protobuf 记录,将其转换为 concept-fetch 请求实例,并将其传递给客户端。
    4. 然后将响应(或错误)转换为 protobuf 记录。Java 代码随后请求 Rust 一个足够大的缓冲区来存储序列化的响应(或错误)。
    5. 将响应写入缓冲区,并返回给 Rust。
    6. Rust 然后解码 protobuf,将其转换为返回给调用者的 viaduct::Response 对象。

一些说明

  • 这个“请求流程”完全是同步的,大大简化了实现。

  • 目前明确不支持 cookies,添加它们需要单独的安全审查。

  • 一般来说,FFI 后端应该以这种方式在任何平台上工作,但我们为了具体说明(以及因为它目前是唯一使用 FFI 后端的一个),我们以 Android 为例进行了说明。

  • viaduct 中的大部分代码是在定义一个易于使用的 HTTP 外观,这与这一点(或 reqwest 后端)无关。这段代码在 Kotlin 层(以及)中主要位于 src/backend/ffi.rs

依赖项

~2.5–9MB
~103K SLoC