Skip to content

Support HTTP/1.1 protocol upgrades #5874

Description

@swankjesse

We should implement user-requested protocol upgrades as specified by RFC 7230 section 6.7.

Use Cases

Eligibility

An HTTP/1 call is upgraded if all of the following are true:

  • The caller’s request includes an Upgrade header
  • The caller’s request includes a Connection header with the value upgrade
  • The server’s response includes an Upgrade header
  • The server’s response includes a Connection header with the value upgrade
  • The response code is 101.

On Upgrade

A successful upgrade changes the behavior of the HTTP response:

  • The ResponseBody is null.
  • The response has a non-null Streams object that carries the input and output stream. Note that the source and sink timeouts should work properly!
interface Streams {
  val source: BufferedSource
  val sink: BufferedSink
  fun cancel()
}
class Response {
  ...
  /** Non-null if this response is a successful upgrade ... */
  @get:JvmName("streams") val streams: Streams?
}

A successful upgrade has these side-effects:

  • The call timeout is immediately completed. (RealCall.timeoutEarlyExit())
  • The connection is forbidden from carrying new exchanges. (RealConnection.noNewExchanges())
  • The socket’s read timeout is disabled. (Socket.setSoTimeout())
  • If the call is asynchronous (Call.enqueue()), the call counts against Dispatcher limits until onResponse() returns.

I’ve used the class name Streams instead of UpgradedConnection or something feature-specific because I think we might be able to reuse this type for CONNECT calls.

Web Sockets

Can we migrate our internal web sockets code to use this? Ideally yes, though that shouldn’t block this from being released.

Event Listeners

Ideally we have well defined behavior for EventListeners on an upgraded connection. We need to decide whether to count bytes of the upgraded connection for the benefit of listeners.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions