Compare commits

...

10 Commits

Author SHA1 Message Date
4JX
b088466fea Switch pseudo header order to mimic chrome
Some checks failed
CI / Check Style (push) Has been cancelled
CI / Test (beta) (push) Has been cancelled
CI / Test (nightly) (push) Has been cancelled
CI / Test (stable) (push) Has been cancelled
CI / Check MSRV (1.56) (push) Has been cancelled
2022-08-17 19:06:56 +02:00
4JX
7c45fd1657 Merge branch 'hyperium:master' into master 2022-08-17 15:40:32 +00:00
4JX
ee6d3fd5e1 Add a setter for header_table_size 2022-08-17 17:13:12 +02:00
Lucio Franco
88b0789254 v0.3.14 2022-08-16 15:29:08 -07:00
4JX
d05d0a7a93 Uncomment set_header_table_size 2022-08-16 16:34:15 +02:00
Erèbe - Romain Gerard
b0f54d80f2 Use RST_STREAM(NO_ERROR) in case server early respond (#633) (#634)
Http2 Server are allowed to early respond without fully
  consuming client input stream, but must respond with an
  error code of NO_ERROR when sending RST_STREAM.
  Nginx treat any other error code as fatal if not done so

  Commit change error code from CANCEL to NO_ERROR, when the
  server is early responding to the client

  https://github.com/hyperium/h2/issues/633
  https://trac.nginx.org/nginx/ticket/2376
2022-08-15 14:08:56 -07:00
Miguel Guarniz
756384f4cd Replace internal PollExt trait with Poll inherent methods (#625)
Signed-off-by: Miguel Guarniz <mi9uel9@gmail.com>
2022-07-18 16:23:52 -07:00
Sean McArthur
fd4040d90d Bump MSRV to 1.56 (#626) 2022-07-18 16:07:28 -07:00
Ryan Russell
e4cf88c1a1 Fix Typo received (#620)
Signed-off-by: Ryan Russell <git@ryanrussell.org>
2022-06-01 17:21:06 -05:00
Bruce Guenter
f6aa3be671 Add Error::is_reset function (#618) 2022-05-18 16:23:40 -07:00
13 changed files with 51 additions and 67 deletions

View File

@@ -90,7 +90,7 @@ jobs:
strategy: strategy:
matrix: matrix:
rust: rust:
- 1.49 # never go past Hyper's own MSRV - 1.56 # never go past Hyper's own MSRV
os: os:
- ubuntu-latest - ubuntu-latest

3
.gitignore vendored
View File

@@ -1,10 +1,11 @@
target target
Cargo.lock Cargo.lock
h2spec h2spec
.history
# These are backup files generated by rustfmt # These are backup files generated by rustfmt
**/*.rs.bk **/*.rs.bk
# Files generated by honggfuzz # Files generated by honggfuzz
hfuzz_target hfuzz_target
hfuzz_workspace hfuzz_workspace

View File

@@ -1,3 +1,9 @@
# 0.3.14 (August 16, 2022)
* Add `Error::is_reset` function.
* Bump MSRV to Rust 1.56.
* Return `RST_STREAM(NO_ERROR)` when the server early responds.
# 0.3.13 (March 31, 2022) # 0.3.13 (March 31, 2022)
* Update private internal `tokio-util` dependency. * Update private internal `tokio-util` dependency.

View File

@@ -5,7 +5,7 @@ name = "h2"
# - html_root_url. # - html_root_url.
# - Update CHANGELOG.md. # - Update CHANGELOG.md.
# - Create git tag # - Create git tag
version = "0.3.13" version = "0.3.14"
license = "MIT" license = "MIT"
authors = [ authors = [
"Carl Lerche <me@carllerche.com>", "Carl Lerche <me@carllerche.com>",

View File

@@ -526,7 +526,7 @@ where
/// ///
/// This setting is configured by the server peer by sending the /// This setting is configured by the server peer by sending the
/// [`SETTINGS_ENABLE_CONNECT_PROTOCOL` parameter][2] in a `SETTINGS` frame. /// [`SETTINGS_ENABLE_CONNECT_PROTOCOL` parameter][2] in a `SETTINGS` frame.
/// This method returns the currently acknowledged value recieved from the /// This method returns the currently acknowledged value received from the
/// remote. /// remote.
/// ///
/// [1]: https://datatracker.ietf.org/doc/html/rfc8441#section-4 /// [1]: https://datatracker.ietf.org/doc/html/rfc8441#section-4
@@ -1022,6 +1022,12 @@ impl Builder {
self self
} }
/// Sets the header table size
pub fn header_table_size(&mut self, size: u32) -> &mut Self {
self.settings.set_header_table_size(Some(size));
self
}
/// Sets the first stream ID to something other than 1. /// Sets the first stream ID to something other than 1.
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]
pub fn initial_stream_id(&mut self, stream_id: u32) -> &mut Self { pub fn initial_stream_id(&mut self, stream_id: u32) -> &mut Self {
@@ -1280,7 +1286,7 @@ where
/// ///
/// This limit is configured by the server peer by sending the /// This limit is configured by the server peer by sending the
/// [`SETTINGS_MAX_CONCURRENT_STREAMS` parameter][1] in a `SETTINGS` frame. /// [`SETTINGS_MAX_CONCURRENT_STREAMS` parameter][1] in a `SETTINGS` frame.
/// This method returns the currently acknowledged value recieved from the /// This method returns the currently acknowledged value received from the
/// remote. /// remote.
/// ///
/// [1]: https://tools.ietf.org/html/rfc7540#section-5.1.2 /// [1]: https://tools.ietf.org/html/rfc7540#section-5.1.2

View File

@@ -59,10 +59,7 @@ impl Error {
/// Returns true if the error is an io::Error /// Returns true if the error is an io::Error
pub fn is_io(&self) -> bool { pub fn is_io(&self) -> bool {
match self.kind { matches!(self.kind, Kind::Io(..))
Kind::Io(_) => true,
_ => false,
}
} }
/// Returns the error if the error is an io::Error /// Returns the error if the error is an io::Error
@@ -92,6 +89,11 @@ impl Error {
matches!(self.kind, Kind::GoAway(..)) matches!(self.kind, Kind::GoAway(..))
} }
/// Returns true if the error is from a `RST_STREAM`.
pub fn is_reset(&self) -> bool {
matches!(self.kind, Kind::Reset(..))
}
/// Returns true if the error was received in a frame from the remote. /// Returns true if the error was received in a frame from the remote.
/// ///
/// Such as from a received `RST_STREAM` or `GOAWAY` frame. /// Such as from a received `RST_STREAM` or `GOAWAY` frame.

View File

@@ -686,13 +686,13 @@ impl Iterator for Iter {
return Some(Method(method)); return Some(Method(method));
} }
if let Some(scheme) = pseudo.scheme.take() {
return Some(Scheme(scheme));
}
if let Some(authority) = pseudo.authority.take() { if let Some(authority) = pseudo.authority.take() {
return Some(Authority(authority)); return Some(Authority(authority));
} }
if let Some(scheme) = pseudo.scheme.take() {
return Some(Scheme(scheme));
}
if let Some(path) = pseudo.path.take() { if let Some(path) = pseudo.path.take() {
return Some(Path(path)); return Some(Path(path));

View File

@@ -120,12 +120,10 @@ impl Settings {
pub fn header_table_size(&self) -> Option<u32> { pub fn header_table_size(&self) -> Option<u32> {
self.header_table_size self.header_table_size
} }
/*
pub fn set_header_table_size(&mut self, size: Option<u32>) { pub fn set_header_table_size(&mut self, size: Option<u32>) {
self.header_table_size = size; self.header_table_size = size;
} }
*/
pub fn load(head: Head, payload: &[u8]) -> Result<Settings, Error> { pub fn load(head: Head, payload: &[u8]) -> Result<Settings, Error> {
use self::Setting::*; use self::Setting::*;

View File

@@ -78,7 +78,7 @@
//! [`server::handshake`]: server/fn.handshake.html //! [`server::handshake`]: server/fn.handshake.html
//! [`client::handshake`]: client/fn.handshake.html //! [`client::handshake`]: client/fn.handshake.html
#![doc(html_root_url = "https://docs.rs/h2/0.3.13")] #![doc(html_root_url = "https://docs.rs/h2/0.3.14")]
#![deny(missing_debug_implementations, missing_docs)] #![deny(missing_debug_implementations, missing_docs)]
#![cfg_attr(test, deny(warnings))] #![cfg_attr(test, deny(warnings))]
@@ -133,44 +133,3 @@ pub use crate::share::{FlowControl, Ping, PingPong, Pong, RecvStream, SendStream
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]
pub use codec::{Codec, SendError, UserError}; pub use codec::{Codec, SendError, UserError};
use std::task::Poll;
// TODO: Get rid of this trait once https://github.com/rust-lang/rust/pull/63512
// is stabilized.
trait PollExt<T, E> {
/// Changes the success value of this `Poll` with the closure provided.
fn map_ok_<U, F>(self, f: F) -> Poll<Option<Result<U, E>>>
where
F: FnOnce(T) -> U;
/// Changes the error value of this `Poll` with the closure provided.
fn map_err_<U, F>(self, f: F) -> Poll<Option<Result<T, U>>>
where
F: FnOnce(E) -> U;
}
impl<T, E> PollExt<T, E> for Poll<Option<Result<T, E>>> {
fn map_ok_<U, F>(self, f: F) -> Poll<Option<Result<U, E>>>
where
F: FnOnce(T) -> U,
{
match self {
Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(f(t)))),
Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e))),
Poll::Ready(None) => Poll::Ready(None),
Poll::Pending => Poll::Pending,
}
}
fn map_err_<U, F>(self, f: F) -> Poll<Option<Result<T, U>>>
where
F: FnOnce(E) -> U,
{
match self {
Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(t))),
Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(f(e)))),
Poll::Ready(None) => Poll::Ready(None),
Poll::Pending => Poll::Pending,
}
}
}

View File

@@ -12,7 +12,6 @@ use http::{HeaderMap, Request, Response};
use std::task::{Context, Poll, Waker}; use std::task::{Context, Poll, Waker};
use tokio::io::AsyncWrite; use tokio::io::AsyncWrite;
use crate::PollExt;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::{fmt, io}; use std::{fmt, io};
@@ -1282,7 +1281,7 @@ impl OpaqueStreamRef {
me.actions me.actions
.recv .recv
.poll_pushed(cx, &mut stream) .poll_pushed(cx, &mut stream)
.map_ok_(|(h, key)| { .map_ok(|(h, key)| {
me.refs += 1; me.refs += 1;
let opaque_ref = let opaque_ref =
OpaqueStreamRef::new(self.inner.clone(), &mut me.store.resolve(key)); OpaqueStreamRef::new(self.inner.clone(), &mut me.store.resolve(key));
@@ -1462,9 +1461,21 @@ fn drop_stream_ref(inner: &Mutex<Inner>, key: store::Key) {
fn maybe_cancel(stream: &mut store::Ptr, actions: &mut Actions, counts: &mut Counts) { fn maybe_cancel(stream: &mut store::Ptr, actions: &mut Actions, counts: &mut Counts) {
if stream.is_canceled_interest() { if stream.is_canceled_interest() {
// Server is allowed to early respond without fully consuming the client input stream
// But per the RFC, must send a RST_STREAM(NO_ERROR) in such cases. https://www.rfc-editor.org/rfc/rfc7540#section-8.1
// Some other http2 implementation may interpret other error code as fatal if not respected (i.e: nginx https://trac.nginx.org/nginx/ticket/2376)
let reason = if counts.peer().is_server()
&& stream.state.is_send_closed()
&& stream.state.is_recv_streaming()
{
Reason::NO_ERROR
} else {
Reason::CANCEL
};
actions actions
.send .send
.schedule_implicit_reset(stream, Reason::CANCEL, counts, &mut actions.task); .schedule_implicit_reset(stream, reason, counts, &mut actions.task);
actions.recv.enqueue_reset_expiration(stream, counts); actions.recv.enqueue_reset_expiration(stream, counts);
} }
} }

View File

@@ -554,7 +554,7 @@ where
/// ///
/// This limit is configured by the client peer by sending the /// This limit is configured by the client peer by sending the
/// [`SETTINGS_MAX_CONCURRENT_STREAMS` parameter][1] in a `SETTINGS` frame. /// [`SETTINGS_MAX_CONCURRENT_STREAMS` parameter][1] in a `SETTINGS` frame.
/// This method returns the currently acknowledged value recieved from the /// This method returns the currently acknowledged value received from the
/// remote. /// remote.
/// ///
/// [1]: https://tools.ietf.org/html/rfc7540#section-5.1.2 /// [1]: https://tools.ietf.org/html/rfc7540#section-5.1.2

View File

@@ -5,7 +5,6 @@ use crate::proto::{self, WindowSize};
use bytes::{Buf, Bytes}; use bytes::{Buf, Bytes};
use http::HeaderMap; use http::HeaderMap;
use crate::PollExt;
use std::fmt; use std::fmt;
#[cfg(feature = "stream")] #[cfg(feature = "stream")]
use std::pin::Pin; use std::pin::Pin;
@@ -307,8 +306,8 @@ impl<B: Buf> SendStream<B> {
pub fn poll_capacity(&mut self, cx: &mut Context) -> Poll<Option<Result<usize, crate::Error>>> { pub fn poll_capacity(&mut self, cx: &mut Context) -> Poll<Option<Result<usize, crate::Error>>> {
self.inner self.inner
.poll_capacity(cx) .poll_capacity(cx)
.map_ok_(|w| w as usize) .map_ok(|w| w as usize)
.map_err_(Into::into) .map_err(Into::into)
} }
/// Sends a single data frame to the remote peer. /// Sends a single data frame to the remote peer.
@@ -403,7 +402,7 @@ impl RecvStream {
/// Poll for the next data frame. /// Poll for the next data frame.
pub fn poll_data(&mut self, cx: &mut Context<'_>) -> Poll<Option<Result<Bytes, crate::Error>>> { pub fn poll_data(&mut self, cx: &mut Context<'_>) -> Poll<Option<Result<Bytes, crate::Error>>> {
self.inner.inner.poll_data(cx).map_err_(Into::into) self.inner.inner.poll_data(cx).map_err(Into::into)
} }
#[doc(hidden)] #[doc(hidden)]

View File

@@ -566,7 +566,9 @@ async fn sends_reset_cancel_when_req_body_is_dropped() {
client client
.recv_frame(frames::headers(1).response(200).eos()) .recv_frame(frames::headers(1).response(200).eos())
.await; .await;
client.recv_frame(frames::reset(1).cancel()).await; client
.recv_frame(frames::reset(1).reason(Reason::NO_ERROR))
.await;
}; };
let srv = async move { let srv = async move {