跳到内容

OkHttp 4.x 变更日志

版本 4.12.0

2023-10-16

  • 修复:处理 HTTP 103 响应的头部时不再挂起。

  • 修复:当缓存条目的证书损坏时,能优雅地恢复。

  • 修复:加载捆绑的公共后缀数据库失败时,永久性地失败。这是为 HttpUrl.topPrivateDomain() 提供支持的数据集。

  • 修复:立即更新连接的流量控制窗口,而不是等待接收流处理它。

    此更改可能会增加 OkHttp 在并发 HTTP 调用较多且接收数据速度快于处理速度的应用中的内存使用量。以前,OkHttp 将 HTTP/2 的每个连接的未确认数据限制为 16 MiB。此修复后,每个流的未确认数据限制为 16 MiB,但没有每连接限制。

  • 修复:连接返回连接池后,不再对其进行操作。此竞态条件发生在失败的 WebSocket 连接尝试中。

  • 升级:Okio 3.6.0

  • 升级:Kotlin 1.8.21

版本 4.11.0

2023-04-22

  • 修复:当响应码是 ‘HTTP 102 Processing’ 或 ‘HTTP 103 Early Hints’ 时,不导致调用失败。
  • 修复:即使写入请求失败,也会读取响应。这意味着即使服务器拒绝了您的请求体,您仍然会收到正确的 HTTP 响应。
  • 修复:直接使用字面量 IP 地址,而不是将它们传递给 DnsOverHttps
  • 修复:嵌入 Proguard 规则以防止 DexGuard 和 R8 等工具发出警告。这些警告是由 OkHttp 对 org.conscryptorg.bouncycastleorg.openjsse 等 TLS 包进行特性检测时触发的。
  • 升级:明确依赖 kotlin-stdlib-jdk8。这修复了依赖锁定中的一个问题。这是一个潜在的安全漏洞,追踪编号为 CVE-2022-24329
  • 升级:publicsuffix.org 数据。这为 HttpUrl.topPrivateDomain() 提供支持。OkHttp 也通过它知道哪些域可以相互共享 cookie。
  • 升级:Okio 3.2.0

版本 4.10.0

2022-06-12

  • 升级:Kotlin 1.6.20
  • 升级:Okio 3.0.0
  • 修复:当 Android 的 NativeCrypto 崩溃并显示 "ssl == null" 时,能优雅地恢复。这发生在 OkHttp 在关闭的连接上检索 ALPN 状态时。

版本 4.9.3

2021-11-21

  • 修复:如果 HTTP/2 响应在发送 RST_STREAM 之前完成,则不导致失败。

版本 4.9.2

2021-09-30

  • 修复:不在 Headers.toString() 或异常中包含潜在敏感的头部值。这适用于 AuthorizationCookieProxy-AuthorizationSet-Cookie 头部。
  • 修复:在 JDK17+ 上启用强封装时,不会因 InaccessibleObjectException 而崩溃。
  • 修复:严格验证与 OkHttp 的 HostnameVerifier 一起使用的主机名。如果传入的主机名不是严格的 ASCII,则直接手动调用 HostnameVerifier 的程序可能会被攻破。此问题追踪编号为 CVE-2021-0341

版本 4.9.1

2021-01-30

  • 修复:解决 Android 10 和 11 中的一个崩溃问题,该问题可能在两个线程并发关闭 SSL socket 时触发。这在崩溃日志中会显示为 NullPointerException: bio == null

版本 4.9.0

2020-09-11

从本版本开始,okhttp-tls 不再依赖 Bouncy Castle 并且不安装 Bouncy Castle 安全提供者。 如果您仍然需要它,可以自行完成。

Security.addProvider(BouncyCastleProvider())

您还需要配置此依赖。

dependencies {
  implementation "org.bouncycastle:bcprov-jdk15on:1.65"
}
  • 升级:Kotlin 1.4.10。我们现在对 AuthenticatorInterceptor 等使用 Kotlin 1.4.x 的函数式接口
  • 升级:使用 Conscrypt 2.5.1 构建。

版本 4.8.1

2020-08-06

  • 修复:在较旧的 Android 版本(包括 Android 6)上创建证书时,HeldCertificate.Builder 中不会崩溃。我们使用了一个 SimpleDateFormat 的特性,而该特性在这些版本中不可用!

版本 4.8.0

2020-07-11

  • 新增:更改 HeldCertificate.Builder 以使用自己的 ASN.1 证书编码器。这是我们移除 okhttp-tls 模块对 Bouncy Castle 依赖的一部分努力。我们认为 Bouncy Castle 很棒!但它是一个庞大的依赖(6.5 MiB),并且其安全提供者特性会影响 VM 范围的行为。

  • 新增:减少并发请求量非常高的应用中的争用。以前,OkHttp 在修改连接和调用时,会使用连接池作为锁。此更改后,每个连接独立锁定。

  • 升级:Okio 2.7.0

    implementation("com.squareup.okio:okio:2.7.0")
    
  • 修复:在检测宿主平台的 TLS 能力时,避免出现“Didn’t find class org.conscrypt.ConscryptHostnameVerifier”之类的日志消息。

  • 修复:当主机名格式错误时,HttpUrl.topPrivateDomain() 中不会崩溃。

  • 修复:如果响应体为空,则不尝试进行 Brotli 解压缩。

版本 4.7.2

2020-05-20

  • 修复:在检查宿主平台是 JVM 还是 Android 时不会崩溃。在 4.7.0 和 4.7.1 版本中,我们由于依赖伴生对象的初始化顺序,曾出现 IllegalArgumentException: Not a Conscrypt trust manager 的崩溃。

版本 4.7.1

2020-05-18

  • 修复:在为 addInsecureHost() 创建的信任管理器中传递正确的参数。如果没有此修复,不安全的主机将在 Android 上因 IllegalArgumentException 而崩溃。

版本 4.7.0

2020-05-17

  • 新增:HandshakeCertificates.Builder.addInsecureHost() 使在只包含测试数据的私有开发环境中轻松关闭安全性。优先使用此方法而非创建完全信任的 TrustManager,因为只有允许列表中的主机才是不安全的。来自我们的 DevServer 示例

    val clientCertificates = HandshakeCertificates.Builder()
        .addPlatformTrustedCertificates()
        .addInsecureHost("localhost")
        .build()
    
    val client = OkHttpClient.Builder()
        .sslSocketFactory(clientCertificates.sslSocketFactory(), clientCertificates.trustManager)
        .build()
    
  • 新增:向 EventListener 添加 cacheHitcacheMisscacheConditionalHit() 事件。在日志、指标甚至测试用例中使用这些事件,以确认您的缓存头部已按预期配置。

  • 新增:常量字符串 okhttp3.VERSION。这是一个类似于“4.5.0-RC1”、“4.5.0”或“4.6.0-SNAPSHOT”的字符串,指示当前运行时的 OkHttp 版本。使用此常量可在自定义 User-Agent 头部中包含 OkHttp 版本。

  • 修复:在 Android Studio Canary 4.1 中作为插件运行时不会崩溃。为了启用特定于平台的 TLS 特性,OkHttp 必须检测它是在 JVM 中运行还是在 Android 中运行。即将发布的 Android Studio 运行在 JVM 中,但包含了 Android 的类,这让 OkHttp 感到困惑!

  • 修复:对于 SSE 调用,包含头部 Accept: text/event-stream。如果请求已包含 Accept 头部,则不添加此头部。

  • 修复:如果服务器在我们发送 ping 时发送关闭,不会因 NullPointerException 而崩溃。OkHttp 曾存在一个竞态条件 bug。

版本 4.6.0

2020-04-28

  • 修复:对 GET 和 POST 以外的方法遵循 HTTP 307 和 308 重定向。我们不愿意改变 OkHttp 处理常见 HTTP 状态码的行为,但这个修复早就该做了!新行为现在与RFC 7231(比 OkHttp 本身还新)保持一致。如果您想要此更新但保留旧行为,请使用此拦截器

  • 修复:解压 WebSocket 消息时不会崩溃。我们曾有一个 bug,错误地假设输入的是已压缩字节,输出就总是已压缩字节,而实际并非总是如此!

  • 修复:在 Windows 上可靠地更新和失效磁盘缓存。最初设计的内部 DiskLruCache 假设文件系统类似于 inode,可以删除正在读写的文件。在 Windows 上,文件系统禁止这样做,因此在删除和重命名文件时必须更加小心。

  • 修复:在 Java 8u252 上不会崩溃,该版本引入了一个以前仅在 Java 9 及更高版本中存在的 API。请参阅Jetty 的概述了解 API 更改及其后果。

  • 新增:MultipartReader 是用于 MIME multipart (RFC 2045) 消息的流式解码器。它补充了我们的流式编码器 MultipartBody

    val response: Response = call.execute()
    val multipartReader = MultipartReader(response.body!!)
    
    multipartReader.use {
      while (true) {
        val part = multipartReader.nextPart() ?: break
        process(part.headers, part.body)
      }
    }
    
  • 新增:MediaType.parameter()multipart/mixed; boundary="abc" 这样的媒体类型中获取像 boundary 这样的参数。

  • 新增:Authenticator.JAVA_NET_AUTHENTICATOR 将身份验证请求转发到 java.net.Authenticator。这使得 okhttp-urlconnection 模块中的 JavaNetAuthenticator 过时。

  • 新增:CertificatePinner 现在提供用于检查配置的 pinning 的 API。

  • 升级:Okio 2.6.0

    implementation("com.squareup.okio:okio:2.6.0")
    
  • 升级:publicsuffix.org 数据。这为 HttpUrl.topPrivateDomain() 提供支持。OkHttp 也通过它知道哪些域可以相互共享 cookie。

  • 升级:Bouncy Castle 1.65。okhttp-tls 模块需要此依赖。

  • 升级:Kotlin 1.3.71

版本 4.5.0

2020-04-06

此版本修复了一个严重错误,其中 OkHttp 错误地检测并从不健康的连接中恢复。 已失效或已取消的连接被错误地尝试使用,本不该如此,这导致了罕见的无限重试情况。请升级到此版本!

  • 修复:不在 DnsOverHttps 中返回陈旧的 DNS 条目。我们之前无限期地缓存 DNS 结果,而不是按照响应的 cache-control 头部指定的持续时间。
  • 修复:以规范形式验证证书 IP 地址。当服务器提供包含 IP 地址的 TLS 证书时,即使两个地址编码不同(例如 192.168.1.10::0:0:FFFF:C0A8:101),我们也必须将该地址与 URL 的 IP 地址进行匹配。请注意,OkHttp 曾错误地拒绝了有效证书,导致连接失败;但从未接受过无效证书。
  • 新增:OkHttpClient.Builder.minWebSocketMessageToCompress() 配置了压缩出站 WebSocket 消息的阈值。将其配置为 0L 表示总是压缩出站消息,配置为 Long.MAX_VALUE 表示从不压缩出站消息。默认值为 1024L,表示压缩大小为 1 KiB 及更大的消息。(入站消息是否压缩取决于 WebSocket 服务器的配置。)
  • 新增:延迟构造 InflaterDeflater 实例直到需要时再进行。如果协商了 WebSocket 压缩但未实际使用,这可以节省内存。

版本 4.5.0-RC1

2020-03-17

此候选版本开启了 WebSocket 压缩。

规范包含了一个复杂的机制,供客户端和服务器协商压缩特性。我们致力于在默认配置下提供卓越的性能,因此从这个候选版本开始,我们将压缩作为所有用户的默认设置。

在推广此版本时,请考虑您的服务器及其运维人员。压缩可以节省带宽,但会消耗 CPU 和内存!如果遇到问题,您可能需要在服务器上调整或禁用 permessage-deflate 压缩设置。

请注意,发送小于 1 KiB 的消息时,OkHttp 不会使用压缩。

  • 修复:当 URL 主机名在 Android 上包含下划线时不会崩溃。
  • 修复:更改 HTTP/2 以使用守护线程作为其 socket 读取器。如果您曾见过命令行应用在完成所有工作后挂起,可能是由于像这样的非守护线程。
  • 新增:当到目标服务的所有路由都失败时,包含被抑制的异常。

版本 4.4.1

2020-03-08

  • 修复:如果证书匹配但 DNS 不匹配,重定向时不要重用连接。为了更好的本地性和性能,OkHttp 尝试在重定向和后续请求中重用同一池化连接。当 IP 地址和证书匹配时,即使主机名不匹配,它也会独立共享连接。在 4.4.0 版本中,我们引入了一个回归问题,即当证书匹配但 DNS 地址不匹配时,我们共享了连接。这只会发生在从一个主机名重定向到另一个主机名,并且两个主机都有共同证书的情况下。

  • 修复:当客户端配置了“信任所有”信任管理器时,重定向不会失败。通常,这会导致某些重定向在调试和开发配置中失败。

版本 4.4.0

2020-02-17

  • 新增:支持 canceled() 作为 EventListener 可观察到的事件。这对于在指标中区分已取消的调用应该很有用。

  • 新增:发布 OkHttp 的物料清单 (BOM)。通过 Gradle 或 Maven 依赖此 BOM,以使所有 OkHttp 构件保持同一版本,即使它们是通过传递依赖声明的。在声明其他 OkHttp 依赖时,甚至可以省略版本。

    dependencies {
       api(platform("com.squareup.okhttp3:okhttp-bom:4.4.0"))
       api("com.squareup.okhttp3:okhttp")              // No version!
       api("com.squareup.okhttp3:logging-interceptor") // No version!
    }
    
  • 新增:升级到 Okio 2.4.3。

    implementation("com.squareup.okio:okio:2.4.3")
    
  • 修复:限制 HTTP/2 REFUSED_STREAMCANCEL 失败的重试次数。

  • 修复:当在多个主机名之间错误地共享连接时自动重试。当主机共享 IP 地址和证书时(例如 squareup.com 和 www.squareup.com),OkHttp 会共享连接。如果服务器拒绝此类共享,它将返回 HTTP 421,并且 OkHttp 将在未共享的连接上自动重试。
  • 修复:如果 TLS 隧道响应体被截断,不会崩溃。
  • 修复:不再跟踪无用的路由。我们曾有一个 bug,可以无限期地跟踪某些坏路由;现在我们只跟踪那些可能需要的路由。
  • 修复:延迟代理选择直到需要代理。这在使用池化连接的调用中,节省了对 ProxySelector 的调用。

版本 4.3.1

2020-01-07

  • 修复:当 WebSocket 在连接之前关闭时,不会因 NullPointerException 而崩溃。这是 OkHttp 4.3.0 中引入的一个回归问题。
  • 修复:在 Android 10 上使用自定义信任管理器时,不会因 IllegalArgumentException 而崩溃。Android 使用反射查找一个神奇的 checkServerTrusted() 方法,而我们没有实现它。
  • 修复:在 Android 5 上进行 HTTPS 连接时,明确指定远程服务器名称。在 4.3.0 版本中,我们引入了一个回归问题,导致 Android 5 上的服务器名称指示 (SNI) 失效。

版本 4.3.0

2019-12-31

  • 修复:超时后降级 HTTP/2 连接。当 HTTP/2 流超时时,可能只影响该流或整个连接。通过此修复,OkHttp 现在会在流超时后发送 HTTP/2 ping 以确定连接是否应继续符合池化条件。

  • 修复:在收到字节之前,不调用 EventListener.responseHeadersStart()responseBodyStart()。之前这些事件错误地发送得太早,即 OkHttp 准备读取响应头部或响应体时,这误导了跟踪工具。请注意,responseFailed() 事件过去总是紧随这些事件之一;现在它可以在没有这些事件的情况下发送。

  • 新增:升级到 Kotlin 1.3.61。

  • 新增:在 CertificatePinner 中使用两个星号匹配任意数量的子域。例如,**.squareup.com 匹配 us-west.www.squareup.comwww.squareup.comsquareup.com

  • 新增:在 OkHttp 的 HTTP/2 连接、连接池、WebSocket 和缓存之间更积极地共享线程。OkHttp 有一个新的内部任务运行器抽象,用于管理任务调度。在您的调试器中,您将看到新的线程名称和更多地使用守护线程。

  • 修复:遇到意外异常时,不丢弃回调。当拦截器抛出未经检查的异常时,回调现在会被通知调用已取消。该异常仍然发送给未捕获异常处理器以进行报告和恢复。

  • 修复:取消弃用 MockResponse.setHeaders() 和其他 setter 方法。这些方法在 OkHttp 4.0 中被弃用,但破坏了 Java 调用者的链式调用。

  • 修复:在 HTTP/2 HEAD 请求中,如果 Content-Length 头部存在但与响应体的长度不一致,不会崩溃。

  • 修复:将具有无法解析主机名的 HttpUrl 实例转换为 URI 时,不会崩溃。新行为会在转换前,从主机名中去除诸如 "{ 等无效字符。

  • 修复:撤销 OkHttp 4.0 中引入的性能回归,该回归是由 Kotlin 的 assert() 和 Java 的 assert() 行为差异引起的。(Kotlin 总是评估参数;Java 只在启用断言时评估。)

  • 修复:在 HttpLoggingInterceptor 中遵守 RequestBody.isOneShot()

版本 4.2.2

2019-10-06

  • 修复:在关闭已取消的 HTTP/2 流时,不发送 END_STREAM 标志。这可能导致服务器错误地将该流解释为正常完成。这在请求体需要取消自身调用时最有用。

版本 4.2.1

2019-10-02

  • 修复:在 4.1.0 版本中,我们引入了一个性能回归问题,导致在某些情况下连接无法被池化。我们对连接池有良好的测试覆盖率,但我们遗漏了这个问题,因为它只发生在配置了代理且在多个 OkHttpClient 实例之间共享连接池的情况下。

    这个特别微妙的 bug 是由于当配置了显式代理时,我们为每个 OkHttpClient 实例分配了其自己的 NullProxySelector 引起的。但当代理选择器不同时,我们不会共享连接。哎!

版本 4.2.0

2019-09-10

  • 新增:解码证书和私钥以创建 HeldCertificate 的 API。此 API 接受一个包含证书和 PKCS #8 编码的私钥的字符串。

    val heldCertificate = HeldCertificate.decode("""
        |-----BEGIN CERTIFICATE-----
        |MIIBYTCCAQegAwIBAgIBKjAKBggqhkjOPQQDAjApMRQwEgYDVQQLEwtlbmdpbmVl
        |cmluZzERMA8GA1UEAxMIY2FzaC5hcHAwHhcNNzAwMTAxMDAwMDA1WhcNNzAwMTAx
        |MDAwMDEwWjApMRQwEgYDVQQLEwtlbmdpbmVlcmluZzERMA8GA1UEAxMIY2FzaC5h
        |cHAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASda8ChkQXxGELnrV/oBnIAx3dD
        |ocUOJfdz4pOJTP6dVQB9U3UBiW5uSX/MoOD0LL5zG3bVyL3Y6pDwKuYvfLNhoyAw
        |HjAcBgNVHREBAf8EEjAQhwQBAQEBgghjYXNoLmFwcDAKBggqhkjOPQQDAgNIADBF
        |AiAyHHg1N6YDDQiY920+cnI5XSZwEGhAtb9PYWO8bLmkcQIhAI2CfEZf3V/obmdT
        |yyaoEufLKVXhrTQhRfodTeigi4RX
        |-----END CERTIFICATE-----
        |-----BEGIN PRIVATE KEY-----
        |MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCA7ODT0xhGSNn4ESj6J
        |lu/GJQZoU9lDrCPeUcQ28tzOWw==
        |-----END PRIVATE KEY-----
        """.trimMargin())
    val handshakeCertificates = HandshakeCertificates.Builder()
        .heldCertificate(heldCertificate)
        .build()
    val server = MockWebServer()
    server.useHttps(handshakeCertificates.sslSocketFactory(), false)
    

    使用 HeldCertificate.certificatePem()privateKeyPkcs8Pem() 获取这些字符串。

  • 修复:握手现在按规范顺序返回对端证书:每个证书由其后续证书签名,最后一个证书由信任根签名。

  • 修复:当接收数据与流关闭发生竞态时,不会丢失 HTTP/2 流量控制字节。如果这种情况发生足够多次,连接最终会停滞。

  • 修复:原子地确认并应用入站 HTTP/2 设置。之前我们有一个竞态问题,即在确认新的流量控制容量之前就可以使用它,导致严格的 HTTP/2 服务器使调用失败。

版本 4.1.1

2019-09-05

  • 修复:验证缓存响应时,不丢弃重复的头部。在我们的 Kotlin 升级中,我们引入了一个回归问题,即我们迭代的是唯一头部名称的数量,而不是唯一头部的数量。如果您使用 OkHttp 的响应缓存,这可能会影响您。

版本 4.1.0

2019-08-12

  • OkHttp 新的 okhttp-brotli 模块实现了 Brotli 压缩。 安装该拦截器以启用Brotli 压缩,其压缩率比 gzip 小 5-20%。

    val client = OkHttpClient.Builder()
        .addInterceptor(BrotliInterceptor)
        .build()
    

    此构件依赖于 Google 的 Brotli 解码器(95 KiB)。

  • 新增:EventListener.proxySelectStart(), proxySelectEnd() 事件提供了对代理选择过程的可见性。

  • 新增:Response.byteString() 将整个响应作为字节字符串读入内存。
  • 新增:OkHttpClient.x509TrustManager 访问器。
  • 新增:允许新的 WebSocket 响应码:1012 (服务重启),1013 (稍后重试),以及 1014 (来自上游的无效响应)。
  • 新增:使用 Kotlin 1.3.41, BouncyCastle 1.62, 和 Conscrypt 2.2.1 构建。
  • 修复:当合并的连接立即变得不健康时,能优雅地恢复。
  • 修复:查找默认代理选择器时,延迟抛出 SecurityException
  • 修复:在 MockWebServer 中,IPv6 主机名不使用方括号格式化。
  • 修复:不允许缓存迭代器移除正在写入的条目。

版本 4.0.1

2019-07-10

  • 修复:在公共 API 中容忍对 null 不友好的列表。使用 List.of(...) 创建的列表不喜欢您对其调用 contains(null)
  • 修复:在 okhttp3.internal.HttpHeaders.hasBody() 中保留二进制兼容性。有些不择手段的编码者会调用此方法,我们不希望他们的用户因此受苦。

版本 4.0.0

2019-06-26

此版本将 OkHttp 升级到 Kotlin。 我们尽力使从 OkHttp 3.x 升级快速且安全。我们编写了升级指南以帮助迁移,并撰写了博文进行解释。

  • 修复:Java 和 Kotlin 目标字节码为 Java 8。

版本 4.0.0-RC3

2019-06-24

  • 修复:在 okhttp3.internal.HttpMethod 中保留二进制兼容性。不良的第三方 SDK 会导入此方法,我们希望方便其用户进行升级。

版本 4.0.0-RC2

2019-06-21

  • 新增:要求 Kotlin 1.3.40。
  • 新增:将 Kotlin API 从 File.toRequestBody() 更改为 File.asRequestBody(),并将 BufferedSource.toResponseBody() 更改为 BufferedSource.asResponseBody()。如果返回的值是创建它的视图,则使用 *as*。
  • 修复:允许响应码为零,以与 OkHttp 3.x 兼容。
  • 修复:将 MockWebServer.takeRequest() 的返回类型更改为可空。
  • 修复:使 Call.clone() 对 Kotlin 调用者公开。

版本 4.0.0-RC1

2019-06-03

  • OkHttp 4 的第一个稳定预览版。

版本 3.x

变更日志