Skip to content

Mint adapter cannot upload more than 65535 bytes on HTTP/2 #394

@jayjun

Description

@jayjun
  • tesla 1.3.3
  • mint 1.1.0

To reproduce,

client = Tesla.client([], Tesla.Adapter.Mint)
Tesla.post(client, "https://httpbin.org/post", String.duplicate("0", 65536))

returns :exceeds_window_size error.

%Mint.HTTPError{
  module: Mint.HTTP2,
  reason: {:exceeds_window_size, :connection, 65535}
}
Full error
{:error,
 %Mint.HTTP2{
   buffer: <<0, 0, 4, 8, 0, 0, 0, 0, 0, 127, 255, 0, 0>>,
   client_settings: %{
     enable_push: true,
     max_concurrent_streams: 100,
     max_frame_size: 16384
   },
   client_settings_queue: {[[]], []},
   decode_table: %Mint.HTTP2.HPACK.Table{
     entries: [],
     length: 0,
     max_table_size: 4096,
     size: 0
   },
   encode_table: %Mint.HTTP2.HPACK.Table{
     entries: [],
     length: 0,
     max_table_size: 4096,
     size: 0
   },
   headers_being_processed: nil,
   hostname: "httpbin.org",
   mode: :active,
   next_stream_id: 5,
   open_client_stream_count: 1,
   open_server_stream_count: 0,
   ping_queue: {[], []},
   port: 443,
   private: %{},
   ref_to_stream_id: %{#Reference<0.4203460067.3989045250.44202> => 3},
   scheme: "https",
   server_settings: %{
     enable_push: true,
     initial_window_size: 65536,
     max_concurrent_streams: 128,
     max_frame_size: 16777215,
     max_header_list_size: :infinity
   },
   socket: {:sslsocket, {:gen_tcp, #Port<0.2811>, :tls_connection, :undefined},
    [#PID<0.1699.0>, #PID<0.1698.0>]},
   state: :open,
   streams: %{
     3 => %{
       id: 3,
       received_first_headers?: false,
       ref: #Reference<0.4203460067.3989045250.44202>,
       state: :open,
       window_size: 65536
     }
   },
   transport: Mint.Core.Transport.SSL,
   window_size: 65535
 },
 %Mint.HTTPError{
   module: Mint.HTTP2,
   reason: {:exceeds_window_size, :connection, 65535}
 }}

That is because window_size: 65535 is set initially, according to standard, but is not updated when the server sends WINDOW_UPDATE frames.

Each time Tesla sends data using Mint.HTTP.stream_request_body, the window size is decremented by data’s size. When the window size gets low, the server sends WINDOW_UPDATE frames to increment the connection’s window size. Calling Mint.HTTP.stream to read responses will automatically do this.

https://github.com/teamon/tesla/blob/754d4a6ffe41ff508fc7fa460508a40e965b2960/lib/tesla/adapter/mint.ex#L178-L187

However, the adapter repeatedly calls Mint.HTTP.stream_request_body without calling Mint.HTTP.stream so the window size hits zero and Mint errors.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions