@@ -1566,7 +1566,7 @@ defmodule Mint.HTTP2 do
1566
1566
responses = [ { :data , stream . ref , data } | responses ]
1567
1567
1568
1568
if flag_set? ( flags , :data , :end_stream ) do
1569
- conn = close_stream! ( conn , stream . id , :no_error )
1569
+ conn = close_stream! ( conn , stream . id , :remote_end_stream )
1570
1570
{ conn , [ { :done , stream . ref } | responses ] }
1571
1571
else
1572
1572
{ conn , responses }
@@ -1675,7 +1675,7 @@ defmodule Mint.HTTP2 do
1675
1675
{ conn , responses }
1676
1676
1677
1677
end_stream? ->
1678
- conn = close_stream! ( conn , stream . id , :no_error )
1678
+ conn = close_stream! ( conn , stream . id , :remote_end_stream )
1679
1679
{ conn , [ { :done , ref } | new_responses ] }
1680
1680
1681
1681
true ->
@@ -1685,7 +1685,7 @@ defmodule Mint.HTTP2 do
1685
1685
end
1686
1686
1687
1687
end_stream? ->
1688
- conn = close_stream! ( conn , stream . id , :no_error )
1688
+ conn = close_stream! ( conn , stream . id , :remote_end_stream )
1689
1689
{ conn , [ { :done , ref } | new_responses ] }
1690
1690
1691
1691
true ->
@@ -1695,7 +1695,7 @@ defmodule Mint.HTTP2 do
1695
1695
# Trailer headers. We don't care about the :status header here.
1696
1696
headers when received_first_headers? ->
1697
1697
if end_stream? do
1698
- conn = close_stream! ( conn , stream . id , :no_error )
1698
+ conn = close_stream! ( conn , stream . id , :remote_end_stream )
1699
1699
headers = headers |> Headers . remove_unallowed_trailer ( ) |> join_cookie_headers ( )
1700
1700
{ conn , [ { :done , ref } , { :headers , ref , headers } | responses ] }
1701
1701
else
@@ -2094,18 +2094,27 @@ defmodule Mint.HTTP2 do
2094
2094
throw ( { :mint , % { conn | state: :closed } , wrap_error ( { error_code , debug_data } ) } )
2095
2095
end
2096
2096
2097
- defp close_stream! ( conn , stream_id , error_code ) do
2097
+ # Reason is either an error code or `remote_end_stream`
2098
+ defp close_stream! ( conn , stream_id , reason ) do
2098
2099
stream = Map . fetch! ( conn . streams , stream_id )
2099
2100
2100
- # First of all we send a RST_STREAM with the given error code so that we
2101
- # move the stream to the :closed state (that is, we remove it).
2102
- rst_stream_frame = rst_stream ( stream_id: stream_id , error_code: error_code )
2103
-
2104
2101
conn =
2105
- if open? ( conn ) do
2106
- send! ( conn , Frame . encode ( rst_stream_frame ) )
2107
- else
2108
- conn
2102
+ cond do
2103
+ # If the stream is ended on both sides, it is already deemed closed and
2104
+ # there's no need to send a RST_STREAM frame
2105
+ reason == :remote_end_stream and stream . state == :half_closed_local ->
2106
+ conn
2107
+
2108
+ # We send a RST_STREAM with the given error code so that we move the
2109
+ # stream to the :closed state (that is, we remove it).
2110
+ open? ( conn ) ->
2111
+ error_code = if reason == :remote_end_stream , do: :no_error , else: reason
2112
+ rst_stream_frame = rst_stream ( stream_id: stream_id , error_code: error_code )
2113
+ send! ( conn , Frame . encode ( rst_stream_frame ) )
2114
+
2115
+ # If the connection is already closed, no-op
2116
+ true ->
2117
+ conn
2109
2118
end
2110
2119
2111
2120
delete_stream ( conn , stream )
0 commit comments