|
15 | 15 | using Microsoft.AspNetCore.Connections;
|
16 | 16 | using Microsoft.AspNetCore.Connections.Features;
|
17 | 17 | using Microsoft.AspNetCore.Http;
|
| 18 | +using Microsoft.AspNetCore.Http.Features; |
18 | 19 | using Microsoft.AspNetCore.Server.Kestrel.Core.Features;
|
19 | 20 | using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
|
20 | 21 | using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2;
|
@@ -209,6 +210,84 @@ await ExpectAsync(Http2FrameType.HEADERS,
|
209 | 210 | await StopConnectionAsync(expectedLastStreamId: 3, ignoreNonGoAwayFrames: false);
|
210 | 211 | }
|
211 | 212 |
|
| 213 | + [Fact] |
| 214 | + public async Task ResponseTrailers_MultipleStreams_Reset() |
| 215 | + { |
| 216 | + IEnumerable<KeyValuePair<string, string>> requestHeaders = new[] |
| 217 | + { |
| 218 | + new KeyValuePair<string, string>(HeaderNames.Method, "GET"), |
| 219 | + new KeyValuePair<string, string>(HeaderNames.Path, "/hello"), |
| 220 | + new KeyValuePair<string, string>(HeaderNames.Scheme, "http"), |
| 221 | + new KeyValuePair<string, string>(HeaderNames.Authority, "localhost:80"), |
| 222 | + new KeyValuePair<string, string>(HeaderNames.ContentType, "application/json") |
| 223 | + }; |
| 224 | + |
| 225 | + var requestCount = 0; |
| 226 | + await InitializeConnectionAsync(context => |
| 227 | + { |
| 228 | + requestCount++; |
| 229 | + |
| 230 | + var trailers = context.Features.Get<IHttpResponseTrailersFeature>().Trailers; |
| 231 | + trailers["trailer-" + requestCount] = "true"; |
| 232 | + return Task.CompletedTask; |
| 233 | + }); |
| 234 | + |
| 235 | + await StartStreamAsync(1, requestHeaders, endStream: true); |
| 236 | + |
| 237 | + await ExpectAsync(Http2FrameType.HEADERS, |
| 238 | + withLength: 36, |
| 239 | + withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS), |
| 240 | + withStreamId: 1); |
| 241 | + |
| 242 | + var trailersFrame = await ExpectAsync(Http2FrameType.HEADERS, |
| 243 | + withLength: 16, |
| 244 | + withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM), |
| 245 | + withStreamId: 1); |
| 246 | + |
| 247 | + _hpackDecoder.Decode(trailersFrame.PayloadSequence, endHeaders: true, handler: this); |
| 248 | + |
| 249 | + Assert.Single(_decodedHeaders); |
| 250 | + Assert.Equal("true", _decodedHeaders["trailer-1"]); |
| 251 | + |
| 252 | + _decodedHeaders.Clear(); |
| 253 | + |
| 254 | + // Ping will trigger the stream to be returned to the pool so we can assert it |
| 255 | + await SendPingAsync(Http2PingFrameFlags.NONE); |
| 256 | + await ExpectAsync(Http2FrameType.PING, |
| 257 | + withLength: 8, |
| 258 | + withFlags: (byte)Http2PingFrameFlags.ACK, |
| 259 | + withStreamId: 0); |
| 260 | + await SendPingAsync(Http2PingFrameFlags.NONE); |
| 261 | + await ExpectAsync(Http2FrameType.PING, |
| 262 | + withLength: 8, |
| 263 | + withFlags: (byte)Http2PingFrameFlags.ACK, |
| 264 | + withStreamId: 0); |
| 265 | + |
| 266 | + // Stream has been returned to the pool |
| 267 | + Assert.Equal(1, _connection.StreamPool.Count); |
| 268 | + |
| 269 | + await StartStreamAsync(3, requestHeaders, endStream: true); |
| 270 | + |
| 271 | + await ExpectAsync(Http2FrameType.HEADERS, |
| 272 | + withLength: 6, |
| 273 | + withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS), |
| 274 | + withStreamId: 3); |
| 275 | + |
| 276 | + trailersFrame = await ExpectAsync(Http2FrameType.HEADERS, |
| 277 | + withLength: 16, |
| 278 | + withFlags: (byte)(Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM), |
| 279 | + withStreamId: 3); |
| 280 | + |
| 281 | + _hpackDecoder.Decode(trailersFrame.PayloadSequence, endHeaders: true, handler: this); |
| 282 | + |
| 283 | + Assert.Single(_decodedHeaders); |
| 284 | + Assert.Equal("true", _decodedHeaders["trailer-2"]); |
| 285 | + |
| 286 | + _decodedHeaders.Clear(); |
| 287 | + |
| 288 | + await StopConnectionAsync(expectedLastStreamId: 3, ignoreNonGoAwayFrames: false); |
| 289 | + } |
| 290 | + |
212 | 291 | [Fact]
|
213 | 292 | public async Task StreamPool_SingleStream_ReturnedToPool()
|
214 | 293 | {
|
|
0 commit comments