Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
b2d666f
Use update ntex-io api
fafhrd91 Sep 21, 2026
1fd4c83
Introduce new error
fafhrd91 Sep 24, 2026
861eb88
New reason
fafhrd91 Sep 24, 2026
e48efe9
Rename config params
fafhrd91 Sep 25, 2026
8e4d7ae
Fix SimpleClient::active_streams() returning 0
fafhrd91 Sep 25, 2026
44821a4
Add SimpleClient::on_capacity(), a callback called when a client capa…
fafhrd91 Sep 25, 2026
df438b5
Add SimpleClient::reserve()
fafhrd91 Sep 25, 2026
70c9a40
Graceful disconnect waits for outstanding stream reservations
fafhrd91 Sep 25, 2026
a48e196
Client SendStream is not cancelled when RecvStream is dropped
fafhrd91 Sep 26, 2026
627707a
Apply the capacity timeout to send_capacity() and poll_send_capacity()
fafhrd91 Sep 26, 2026
da114fc
Wake a pending RecvStream::recv() when SendStream resets the stream
fafhrd91 Sep 26, 2026
56785fb
clippy
fafhrd91 Sep 26, 2026
5716a45
test
fafhrd91 Sep 26, 2026
be085ea
Update to ntex-codec 2.0
fafhrd91 Sep 26, 2026
7a5ac27
Use new name
fafhrd91 Sep 26, 2026
7cc0287
Count DATA frame padding toward flow control
fafhrd91 Sep 27, 2026
3ea093c
Codec::set_send_frame_size() panics unless the size is between 16,384…
fafhrd91 Sep 27, 2026
7fbed44
Release the thread-local header encoding buffer after encoding a head…
fafhrd91 Sep 27, 2026
d786ccb
Reject DATA frames that exceed the receive window
fafhrd91 Sep 27, 2026
e81db69
Do not copy GO_AWAY debug data on decode
fafhrd91 Sep 27, 2026
6a5ab37
Replace the generic length delimited codec with a dedicated HTTP/2 fr…
fafhrd91 Sep 27, 2026
a751ef7
cleanups
fafhrd91 Sep 27, 2026
4bae0cc
Enforce the header list size limit on decoded headers
fafhrd91 Sep 27, 2026
0bafaa5
Reset only the stream, instead of closing the connection, on malforme…
fafhrd91 Sep 27, 2026
aa9c25f
Reset only the stream on requests with missing or unexpected pseudo h…
fafhrd91 Sep 27, 2026
f89a373
Update api docs
fafhrd91 Sep 27, 2026
4cca949
Wake streams waiting for send capacity when SETTINGS_INITIAL_WINDOW_S…
fafhrd91 Sep 27, 2026
181e064
Client assumes a limit of 100 concurrent streams until the peer's SET…
fafhrd91 Sep 27, 2026
9d0c51d
Streams over the concurrency limit are always refused with REFUSED_ST…
fafhrd91 Sep 27, 2026
b12bda5
The first frame from the peer must be SETTINGS
fafhrd91 Sep 27, 2026
ca8a4ec
Send the SETTINGS ACK after the peer's settings are applied
fafhrd91 Sep 27, 2026
042a123
SETTINGS_INITIAL_WINDOW_SIZE that overflows a stream send window is a…
fafhrd91 Sep 27, 2026
a0ad8e2
Publish stream reset message for locally closed streams
fafhrd91 Sep 27, 2026
d2cb675
Remove unused ConnectionError::MissingPseudo and ConnectionError::Une…
fafhrd91 Sep 27, 2026
d912107
Use RFC 9113 error codes for frame decoding errors
fafhrd91 Sep 27, 2026
3444942
Cap the HPACK encoder table at 4096 bytes
fafhrd91 Sep 27, 2026
a51a46d
Improve spec complience
fafhrd91 Sep 27, 2026
fdeb7e3
HPACK decoder compacts dynamic table entries with trimdown()
fafhrd91 Sep 27, 2026
e51ed82
HPACK encoder compacts dynamic table entries, entries do not pin appl…
fafhrd91 Sep 27, 2026
2e338b5
Accept CONNECT requests without :scheme and :path, reject them if pre…
fafhrd91 Sep 27, 2026
d617d95
Control service failure fails open streams
fafhrd91 Sep 27, 2026
459ee1b
Stop the capacity timer when a stream closes or fails
fafhrd91 Sep 27, 2026
ceee03e
Ignore RST_STREAM for unknown or forgotten streams instead of a conne…
fafhrd91 Sep 27, 2026
b238aca
Connection receive window is released when received data is consumed
fafhrd91 Sep 27, 2026
5e00b3e
Capacity timeout resets the stream with CANCEL
fafhrd91 Sep 27, 2026
6ae6e7d
Requests waiting for a stream slot fail on disconnect
fafhrd91 Sep 27, 2026
2fd26af
Released stream slots wake a waiting request per free slot
fafhrd91 Sep 27, 2026
3ab3a6d
Client does not fail a complete response on RST_STREAM(NO_ERROR)
fafhrd91 Sep 27, 2026
65575d6
Stream WINDOW_UPDATE is not sent for streams with a closed receive side
fafhrd91 Sep 27, 2026
7f29f8f
Document that a remote stream reset outside of a publish call does no…
fafhrd91 Sep 27, 2026
c0c88ef
A publish call of a remote stream is cancelled only if the stream is …
fafhrd91 Sep 27, 2026
3c1a96e
Late frames for closed streams are not connection errors
fafhrd91 Sep 27, 2026
6d7ec5f
Client ignores late HEADERS for its closed streams
fafhrd91 Sep 27, 2026
4b98cf5
Client delivers interim 1xx responses and waits for the final response
fafhrd91 Sep 28, 2026
8e96f69
wip
fafhrd91 Sep 28, 2026
749660b
Client validates a response to a HEAD request as a response without c…
fafhrd91 Sep 28, 2026
f4d99d4
Server resets a request with the :protocol pseudo header with PROTOCO…
fafhrd91 Sep 28, 2026
25b9db3
update api docs
fafhrd91 Sep 28, 2026
87932de
Remove unreachable Stream re-export, unused types
fafhrd91 Sep 28, 2026
626f1f3
Remove unused code
fafhrd91 Sep 28, 2026
9cc3652
Sending empty payload without eof does not wait for send capacity and…
fafhrd91 Sep 28, 2026
2021bbb
Waiting for send capacity fails with OperationError::Closed once the …
fafhrd91 Sep 28, 2026
d4602a0
fix debug
fafhrd91 Sep 28, 2026
b254336
Stream window updates do not restart the capacity timeout while the c…
fafhrd91 Sep 28, 2026
6753558
Sending payload waits for the io write back-pressure release
fafhrd91 Sep 28, 2026
f340367
A received GOAWAY honors last_stream_id
fafhrd91 Sep 28, 2026
b488467
DATA frame exceeding the stream receive window does not trigger a str…
fafhrd91 Sep 28, 2026
18dea35
Capacity timer task cancellation, e.g. on runtime shutdown
fafhrd91 Sep 29, 2026
0aafdec
Stream reset cancels all in-flight publish calls of the stream
fafhrd91 Sep 29, 2026
eaa8de6
Add Control::Expect for requests with 'Expect: 100-continue'
fafhrd91 Sep 29, 2026
15863be
Document that only one task at a time may send payload or wait for se…
fafhrd91 Sep 29, 2026
93db1e5
Add StreamRef::is_reset(), StreamRef::on_reset() and the same methods…
fafhrd91 Sep 29, 2026
6be10aa
Complience fixes
fafhrd91 Sep 29, 2026
2ed82e1
Server graceful shutdown sends GOAWAY(NO_ERROR)
fafhrd91 Sep 29, 2026
183b4fc
Accept 'te: trailers' case-insensitively
fafhrd91 Sep 29, 2026
81a4802
DATA frames with the PADDED flag are encoded with a pad length field
fafhrd91 Sep 29, 2026
0c2950e
The rapid-reset ratio is measured over recent streams
fafhrd91 Sep 29, 2026
6044c5f
Exceeding the rapid-reset limit closes the connection with ENHANCE_YO…
fafhrd91 Sep 29, 2026
de380b6
Trailers with pseudo-headers are a stream error
fafhrd91 Sep 29, 2026
f2ab8d1
Resetting a stream twice refreshes its pending reset entry
fafhrd91 Sep 29, 2026
2deafe8
Keep-alive accepts only the PING ACK carrying the payload of the last…
fafhrd91 Sep 29, 2026
f6a9ad8
Client RecvStream is woken when the stream is reset locally
fafhrd91 Sep 29, 2026
c8ca94f
Client RecvStream is woken when the stream is reset locally
fafhrd91 Sep 29, 2026
bdb1e87
Merge branch 'refine-api' of github.com:ntex-rs/ntex-h2 into refine-api
fafhrd91 Sep 29, 2026
7660f2a
Reset active stream counters when a connection error or disconnect fails
fafhrd91 Sep 30, 2026
3951d48
wip
fafhrd91 Sep 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ jobs:
if: matrix.rust == 'nightly' || matrix.rust == 'beta'
with:
command: build
args: --features=ntex-net/neon

- name: Run lib tests and doc tests
uses: actions-rs/cargo@v1
Expand All @@ -74,7 +73,7 @@ jobs:
args: --features=ntex-net/tokio

- name: Generate code coverage
run: cargo llvm-cov --no-report --features=ntex-net/neon
run: cargo llvm-cov --no-report
if: matrix.rust == 'stable'

#- name: Run integration tests
Expand Down Expand Up @@ -127,4 +126,3 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: check
args: --features=ntex-net/neon
260 changes: 260 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,265 @@
# Changes

## [4.1.0] - Unreleased

* Reset active stream counters when a connection error or disconnect fails all streams,
`active_streams()` kept counting the failed streams

* Do not answer a received RST_STREAM with RST_STREAM (RFC 9113 §5.4.2)

* GOAWAY frames report the last stream opened by the peer, `last_stream_id` was always 0

* Client treats HEADERS on a server-initiated stream as a connection error, push is not enabled

* Check `content-length` when a message ends with the headers or with trailers,
a `304` response can describe the omitted body

* `Client` pool wakes waiting requests when a stream is released, including
cancelled streams, waiters were woken only on the end of a response

* Server graceful shutdown sends GOAWAY(NO_ERROR) with the last processed stream (RFC 9113 §6.8)

* Accept `te: trailers` case-insensitively, drop unknown HEADERS flags instead of keeping them

* DATA frames with the `PADDED` flag are encoded with a pad length field, the frame was malformed

* The rapid-reset ratio is measured over recent streams, a long-lived connection allowed
an unbounded burst of resets

* Exceeding the rapid-reset limit closes the connection with ENHANCE_YOUR_CALM instead of FLOW_CONTROL_ERROR

* Trailers with pseudo-headers are a stream error (RFC 9113 §8.1), the pseudo-headers were dropped

* Resetting a stream twice refreshes its pending reset entry, a duplicate entry forgot the stream early

* Keep-alive accepts only the PING ACK carrying the payload of the last keep-alive ping,
any PING ACK was treated as a pong

* Client `RecvStream` is woken when the stream is reset locally, including capacity timeout and resets through `StreamRef`

* GOAWAY with a non-zero stream identifier is a connection error (RFC 9113 §6.8)

* Ignore invalid PRIORITY frames for idle and closed streams, an idle stream must not be reset

* Add `StreamRef::is_reset()`, `StreamRef::on_reset()` and the same methods on `SendStream`,
`on_reset()` returns an io waiter that completes when the stream is reset or the connection closes

* Document that only one task at a time may send payload or wait for send capacity on a stream,
debug builds panic on concurrent capacity waiters

* Add `StreamRef::send_informational()`, sends `1xx` interim responses before the final response

* Add `Control::Expect` for requests with `Expect: 100-continue`, created by the application layer,
`ControlAck::into_expect()` returns the request back with the result

* `StreamEof::Data` carries the receive-window `Capacity` of the final DATA frame, the connection
window was released before the application consumed the data, `StreamEof` is not `Clone`

* Remove `StreamRef::poll_send_reset()` and `SendStream::poll_send_reset()`

* `SimpleClient::on_disconnect()` returns `ntex_io::Waiter<'static>`, `OnDisconnect` is removed from ntex-io

* Stream reset cancels all in-flight publish calls of the stream (HEADERS, DATA, trailers),
only the HEADERS publish call was cancelled on reset

* Add `ServiceConfig::set_max_inflight_messages()`, limits in-flight service calls
of a connection, default is 16,384

* Capacity timer task cancellation, e.g. on runtime shutdown, releases registered stream references

* DATA frame exceeding the stream receive window does not trigger a stream WINDOW_UPDATE
before the stream reset

* A received GOAWAY honors `last_stream_id` (RFC 9113 §6.8): only locally initiated streams
above it are failed, remaining streams complete, new streams are refused with
`ConnectionError::GoAway`, the connection closes once the remaining streams are done

* Sending payload waits for the io write back-pressure release, a peer with large flow-control
windows that does not read could make the sender buffer unbounded data

* Stream window updates do not restart the capacity timeout while the connection
window is exhausted

* Waiting for send capacity fails with `OperationError::Closed` once the send side
is closed, instead of waiting forever or reporting capacity

* Sending empty payload without eof does not wait for send capacity and does not
send an empty `DATA` frame

* Remove unused `PseudoHeaders::request()`, `set_status()`, `set_scheme()`, `set_protocol()`
and `set_authority()`, pseudo header fields are public

* Remove unreachable `Stream` re-export, unused `client::Observer` and `unstable` feature,
`ClientBuilder::with_default()` and `SimpleClient::connection()`

* Fix build with the `trace` feature, API docs updates

* Close the connection with `SETTINGS_TIMEOUT` if the peer does not acknowledge local settings
in time, new `ServiceConfig::set_settings_timeout()` (default 5 seconds) and
`ConnectionError::SettingsTimeout`

* Server resets a request with the `:protocol` pseudo header with `PROTOCOL_ERROR`, extended
CONNECT is not enabled

* Client validates a response to a `HEAD` request as a response without content, its
`content-length` header was checked against the response `DATA`

* Client delivers interim `1xx` responses and waits for the final response, a following `HEADERS`
was rejected as trailers without end of stream, an interim response with `END_STREAM` or `101`
status is malformed (new `StreamError::InvalidInformational`)

* Client ignores late `HEADERS` for its closed streams without updating the last peer stream id,
`HEADERS` for an idle client stream is a connection error

* Late frames for closed streams are not connection errors, `WINDOW_UPDATE` is ignored, `DATA`
is reset with `STREAM_CLOSED`, trailers for a reset stream are ignored, frames for idle
streams are still connection errors

* A publish call of a remote stream is cancelled only if the stream is reset during the call,
request data after a complete response and the final message of a reset stream are published

* Document that a remote stream reset outside of a publish call does not get the final message

* Stream `WINDOW_UPDATE` is not sent for streams with a closed receive side, consumed data
still releases the connection window

* Client does not fail a complete response on `RST_STREAM(NO_ERROR)`, the reset only stops
the request body and is not counted as a reset

* Released stream slots wake a waiting request per free slot, a dropped woken request passes
the wake up to the next waiting request

* Requests waiting for a stream slot fail on disconnect, keep-alive and read timeouts and
graceful disconnect instead of waiting forever

* Capacity timeout resets the stream with `CANCEL` and does not count toward the stream resets
limit. Default capacity timeout is 5 seconds

* Connection receive window is released when received data is consumed, the window bounds
unconsumed data of all streams. Default connection window size is 4 MiB

* Ignore RST_STREAM for unknown or forgotten streams instead of a connection error

* Stop the capacity timer when a stream closes or fails, the timer does not keep closed streams
alive

* Dropping a pending `send_capacity()` future stops the capacity timer, the stream is not reset
with `FLOW_CONTROL_ERROR` without a waiter

* Control service failure fails open streams and publishes `Disconnect` for them, pending
handlers do not block the connection shutdown

* PRIORITY frame with an invalid length is a stream error `FRAME_SIZE_ERROR`

* Accept `CONNECT` requests without `:scheme` and `:path`, reject them if present. Client omits
`:scheme` and `:path` for `CONNECT` requests

* HPACK encoder compacts dynamic table entries, entries do not pin application buffers

* HPACK decoder compacts dynamic table entries with `trimdown()`, entries do not pin read buffers

* Client treats `SETTINGS_ENABLE_PUSH=1` from the server as a connection error `PROTOCOL_ERROR`,
add `ConnectionError::UnexpectedEnablePush`

* Requests, responses and trailers over the peer's `SETTINGS_MAX_HEADER_LIST_SIZE` fail with
`OperationError::HeaderListTooLarge`. `send_trailers()` returns `Result`

* Cap the HPACK encoder table at 4096 bytes, the peer's larger `SETTINGS_HEADER_TABLE_SIZE`
is not used

* Use RFC 9113 error codes for frame decoding errors (`FRAME_SIZE_ERROR`, `FLOW_CONTROL_ERROR`,
`COMPRESSION_ERROR`), GOAWAY debug data contains the decoding error. Add `FrameError::reason()`
and `FrameError::InvalidInitialWindowSize`, fix swapped SETTINGS payload length errors

* A response without `:status` or with request pseudo-headers is a stream error with
`PROTOCOL_ERROR`. Remove unused `ConnectionError::MissingPseudo` and
`ConnectionError::UnexpectedPseudo`

* Publish stream reset message for locally closed streams

* `SETTINGS_INITIAL_WINDOW_SIZE` that overflows a stream send window is a connection
`FLOW_CONTROL_ERROR`, instead of a stream reset

* Send the SETTINGS ACK after the peer's settings are applied

* The first frame from the peer must be SETTINGS, otherwise the connection is closed
with `PROTOCOL_ERROR`. Add `ConnectionError::MissingSettings`

* Streams over the concurrency limit are always refused with `REFUSED_STREAM` and count
toward the rapid reset limit, instead of closing the connection on the second overflow.
Remove `ConnectionError::ConcurrencyOverflow`

* During shutdown all new streams are refused, DATA for refused streams is ignored

* Client assumes a limit of 100 concurrent streams until the peer's SETTINGS arrive,
instead of no limit

* Wake streams waiting for send capacity when `SETTINGS_INITIAL_WINDOW_SIZE` grows the
stream windows, senders stalled until the capacity timeout

* Add `ClientBuilder::connect_timeout()` and `ClientBuilder::disconnect_timeout()`

* Remove unused `control::Terminated`

* Document all public items and fix inaccurate API docs

* Reset only the stream on requests with missing or unexpected pseudo headers, instead of
closing the connection, add `StreamError::MissingPseudo` and `StreamError::UnexpectedPseudo`

* Remove unused `FrameContinuationError::Malformed`

* Reset only the stream, instead of closing the connection, on malformed, too large or
self-dependent header blocks and self-dependent PRIORITY frames, add `Frame::Invalid`,
`frame::InvalidFrame` and `StreamError::InvalidFrame`

* Ignore DATA frames received on streams that were reset locally, instead of replying
with `STREAM_CLOSED` resets

* Enforce the header list size limit on decoded headers, `Headers::load_hpack()` accepts `max_list_size`

* Count every header field toward `max_headers`, not only distinct names

* Fix quadratic copying when joining CONTINUATION frames

* Replace the generic length delimited codec with a dedicated HTTP/2 frame decoder

* Do not copy GO_AWAY debug data on decode, `GoAway::load()` accepts `Bytes`

* Reject DATA frames that exceed the receive window, with a `FLOW_CONTROL_ERROR` stream
reset or connection error, add `StreamError::RecvWindowExceeded` and
`ConnectionError::RecvWindowExceeded`

* `Codec::set_send_frame_size()` panics unless the size is between 16,384 and 16,777,215,
a zero size made the encoder loop forever

* Count DATA frame padding toward flow control, add `frame::Data::flow_controlled_len()`

* Update to ntex-codec 2.0

* Export `client::ClientDisconnect`, the future returned by `SimpleClient::disconnect()`

* Wake a pending `RecvStream::recv()` when `SendStream` resets the stream, is dropped
unfinished, or fails to send

* Apply the capacity timeout to `send_capacity()` and `poll_send_capacity()`, not only to
payload sending, a stale capacity timer of a closed stream is ignored

* Client `SendStream` is not cancelled when `RecvStream` is dropped, the request body
can be sent after the response is received

* Graceful disconnect waits for outstanding stream reservations, a reserved stream
can be opened during graceful disconnect

* Add `SimpleClient::reserve()` and `StreamReservation`, a stream counted as active until
the reservation is dropped or its request's stream is closed

* Add `SimpleClient::on_capacity()`, a callback called when a client stream is released,
the peer changes its concurrent stream limit, or the connection is closed

* Fix `SimpleClient::active_streams()` returning `0` until the peer sends `MAX_CONCURRENT_STREAMS`

* Rename `ClientBuilder::maxconn()` to `ClientBuilder::connection_limit()`, to match the ntex http client pool configuration

## [4.0.1] - 2026-09-18

* Update api docs
Expand Down
38 changes: 24 additions & 14 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ntex-h2"
version = "4.0.1"
version = "4.1.0"
license = "MIT OR Apache-2.0"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
description = "An HTTP/2 client and server"
Expand All @@ -16,26 +16,23 @@
[features]
default = []

# unstable features
unstable = []

# log extra info
trace = []

[package.metadata.docs.rs]
features = []

[dependencies]
ntex-bytes = "1.9.0"
ntex-codec = "1.2"
ntex-dispatcher = "4.0.0"
ntex-bytes = "1.10.0"
ntex-codec = "2.0"
ntex-dispatcher = "4.1.0"
ntex-error = "2.6"
ntex-http = "1.2"
ntex-io = "4.0.0"
ntex-net = "4.0.0"
ntex-service = "5.0.0"
ntex-util = "4.0.0"
ntex-server = "4.0.0"
ntex-io = "4.1.0"
ntex-net = "4.1.0"
ntex-service = "5.0.1"
ntex-util = "4.2.0"
ntex-server = "4.2.0"

Check warning on line 35 in Cargo.toml

View workflow job for this annotation

GitHub Actions / Test (beta)

unused dependency `ntex-server`

Check warning on line 35 in Cargo.toml

View workflow job for this annotation

GitHub Actions / Test (beta)

unused dependency `ntex-server`

Check warning on line 35 in Cargo.toml

View workflow job for this annotation

GitHub Actions / Test (nightly)

unused dependency `ntex-server`

Check warning on line 35 in Cargo.toml

View workflow job for this annotation

GitHub Actions / Test (nightly)

unused dependency `ntex-server`

bitflags = "2"
foldhash = "0.2"
Expand All @@ -55,12 +52,25 @@
serde = "1"
serde_json = "1"

ntex = { version = "4.0.0-beta.13", features = ["openssl"] }
ntex-tls = { version = "4.0.0", features = ["openssl"] }
ntex = { version = "4.0.0-beta.14", features = ["openssl"] }
ntex-tls = { version = "4.1.0", features = ["openssl"] }
openssl = "0.10"

# Examples
env_logger = "0.11"

[patch.crates-io]
ntex-h2 = { path = "." }

ntex = { git = "https://github.com/ntex-rs/ntex.git" }
ntex-error = { git = "https://github.com/ntex-rs/ntex.git" }
ntex-io = { git = "https://github.com/ntex-rs/ntex.git" }
ntex-net = { git = "https://github.com/ntex-rs/ntex.git" }
ntex-util = { git = "https://github.com/ntex-rs/ntex.git" }
ntex-bytes = { git = "https://github.com/ntex-rs/ntex.git" }
ntex-codec = { git = "https://github.com/ntex-rs/ntex.git" }
ntex-server = { git = "https://github.com/ntex-rs/ntex.git" }
ntex-dispatcher = { git = "https://github.com/ntex-rs/ntex.git" }
ntex-rt = { git = "https://github.com/ntex-rs/ntex.git" }
ntex-tls = { git = "https://github.com/ntex-rs/ntex.git" }
ntex-router = { git = "https://github.com/ntex-rs/ntex.git" }
2 changes: 1 addition & 1 deletion examples/tls-server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ async fn main() -> std::io::Result<()> {
header::CONTENT_TYPE,
header::HeaderValue::try_from("blah").unwrap(),
);
stream.send_trailers(hdrs);
stream.send_trailers(hdrs)?;
}
MessageKind::Data(data, _cap) => {
println!("Got data: {:?}", data.len());
Expand Down
Loading
Loading