Skip to content

Commit ef743ec

Browse files
authored
Add a setter for header_table_size (hyperium#638)
1 parent 56651e6 commit ef743ec

File tree

7 files changed

+87
-2
lines changed

7 files changed

+87
-2
lines changed

src/client.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,39 @@ impl Builder {
10721072
self
10731073
}
10741074

1075+
/// Sets the header table size.
1076+
///
1077+
/// This setting informs the peer of the maximum size of the header compression
1078+
/// table used to encode header blocks, in octets. The encoder may select any value
1079+
/// equal to or less than the header table size specified by the sender.
1080+
///
1081+
/// The default value is 4,096.
1082+
///
1083+
/// # Examples
1084+
///
1085+
/// ```
1086+
/// # use tokio::io::{AsyncRead, AsyncWrite};
1087+
/// # use h2::client::*;
1088+
/// # use bytes::Bytes;
1089+
/// #
1090+
/// # async fn doc<T: AsyncRead + AsyncWrite + Unpin>(my_io: T)
1091+
/// # -> Result<((SendRequest<Bytes>, Connection<T, Bytes>)), h2::Error>
1092+
/// # {
1093+
/// // `client_fut` is a future representing the completion of the HTTP/2
1094+
/// // handshake.
1095+
/// let client_fut = Builder::new()
1096+
/// .header_table_size(1_000_000)
1097+
/// .handshake(my_io);
1098+
/// # client_fut.await
1099+
/// # }
1100+
/// #
1101+
/// # pub fn main() {}
1102+
/// ```
1103+
pub fn header_table_size(&mut self, size: u32) -> &mut Self {
1104+
self.settings.set_header_table_size(Some(size));
1105+
self
1106+
}
1107+
10751108
/// Sets the first stream ID to something other than 1.
10761109
#[cfg(feature = "unstable")]
10771110
pub fn initial_stream_id(&mut self, stream_id: u32) -> &mut Self {

src/codec/framed_read.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,12 @@ impl<T> FramedRead<T> {
8888
pub fn set_max_header_list_size(&mut self, val: usize) {
8989
self.max_header_list_size = val;
9090
}
91+
92+
/// Update the header table size setting.
93+
#[inline]
94+
pub fn set_header_table_size(&mut self, val: usize) {
95+
self.hpack.queue_size_update(val);
96+
}
9197
}
9298

9399
/// Decodes a frame.

src/codec/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ impl<T, B> Codec<T, B> {
9595
self.framed_write().set_header_table_size(val)
9696
}
9797

98+
/// Set the decoder header table size size.
99+
pub fn set_recv_header_table_size(&mut self, val: usize) {
100+
self.inner.set_header_table_size(val)
101+
}
102+
98103
/// Set the max header list size that can be received.
99104
pub fn set_max_recv_header_list_size(&mut self, val: usize) {
100105
self.inner.set_max_header_list_size(val);

src/frame/settings.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,9 @@ impl Settings {
121121
self.header_table_size
122122
}
123123

124-
/*
125124
pub fn set_header_table_size(&mut self, size: Option<u32>) {
126125
self.header_table_size = size;
127126
}
128-
*/
129127

130128
pub fn load(head: Head, payload: &[u8]) -> Result<Settings, Error> {
131129
use self::Setting::*;

src/proto/settings.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ impl Settings {
6060
codec.set_max_recv_header_list_size(max as usize);
6161
}
6262

63+
if let Some(val) = local.header_table_size() {
64+
codec.set_recv_header_table_size(val as usize);
65+
}
66+
6367
streams.apply_local_settings(local)?;
6468
self.local = Local::Synced;
6569
Ok(())

tests/h2-support/src/frames.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,11 @@ impl Mock<frame::Settings> {
391391
self.0.set_enable_connect_protocol(Some(val));
392392
self
393393
}
394+
395+
pub fn header_table_size(mut self, val: u32) -> Self {
396+
self.0.set_header_table_size(Some(val));
397+
self
398+
}
394399
}
395400

396401
impl From<Mock<frame::Settings>> for frame::Settings {

tests/h2-tests/tests/client_request.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1627,6 +1627,40 @@ async fn rogue_server_reused_headers() {
16271627
join(srv, h2).await;
16281628
}
16291629

1630+
#[tokio::test]
1631+
async fn client_builder_header_table_size() {
1632+
h2_support::trace_init!();
1633+
let (io, mut srv) = mock::new();
1634+
let mut settings = frame::Settings::default();
1635+
1636+
settings.set_header_table_size(Some(10000));
1637+
1638+
let srv = async move {
1639+
let recv_settings = srv.assert_client_handshake().await;
1640+
assert_frame_eq(recv_settings, settings);
1641+
1642+
srv.recv_frame(
1643+
frames::headers(1)
1644+
.request("GET", "https://example.com/")
1645+
.eos(),
1646+
)
1647+
.await;
1648+
srv.send_frame(frames::headers(1).response(200).eos()).await;
1649+
};
1650+
1651+
let mut builder = client::Builder::new();
1652+
builder.header_table_size(10000);
1653+
1654+
let h2 = async move {
1655+
let (mut client, mut h2) = builder.handshake::<_, Bytes>(io).await.unwrap();
1656+
let request = Request::get("https://example.com/").body(()).unwrap();
1657+
let (response, _) = client.send_request(request, true).unwrap();
1658+
h2.drive(response).await.unwrap();
1659+
};
1660+
1661+
join(srv, h2).await;
1662+
}
1663+
16301664
const SETTINGS: &[u8] = &[0, 0, 0, 4, 0, 0, 0, 0, 0];
16311665
const SETTINGS_ACK: &[u8] = &[0, 0, 0, 4, 1, 0, 0, 0, 0];
16321666

0 commit comments

Comments
 (0)