@@ -29,7 +29,7 @@ public static HttpResponseMessage CreateResponseMessage(
29
29
// Create a single buffer to use for all subsequent WinHttpQueryHeaders string interop calls.
30
30
// This buffer is the length needed for WINHTTP_QUERY_RAW_HEADERS_CRLF, which includes the status line
31
31
// and all headers separated by CRLF, so it should be large enough for any individual status line or header queries.
32
- int bufferLength = GetResponseHeaderCharBufferLength ( requestHandle , Interop . WinHttp . WINHTTP_QUERY_RAW_HEADERS_CRLF ) ;
32
+ int bufferLength = GetResponseHeaderCharBufferLength ( requestHandle , Interop . WinHttp . WINHTTP_QUERY_RAW_HEADERS_CRLF , isTrailingHeaders : false ) ;
33
33
char [ ] buffer = ArrayPool < char > . Shared . Rent ( bufferLength ) ;
34
34
try
35
35
{
@@ -58,7 +58,7 @@ public static HttpResponseMessage CreateResponseMessage(
58
58
string . Empty ;
59
59
60
60
// Create response stream and wrap it in a StreamContent object.
61
- var responseStream = new WinHttpResponseStream ( requestHandle , state ) ;
61
+ var responseStream = new WinHttpResponseStream ( requestHandle , state , response ) ;
62
62
state . RequestHandle = null ; // ownership successfully transfered to WinHttpResponseStram.
63
63
Stream decompressedStream = responseStream ;
64
64
@@ -93,7 +93,7 @@ public static HttpResponseMessage CreateResponseMessage(
93
93
response . RequestMessage = request ;
94
94
95
95
// Parse raw response headers and place them into response message.
96
- ParseResponseHeaders ( requestHandle , response , buffer , stripEncodingHeaders ) ;
96
+ ParseResponseHeaders ( requestHandle , Interop . WinHttp . WINHTTP_QUERY_RAW_HEADERS_CRLF , response , buffer , stripEncodingHeaders , isTrailers : false ) ;
97
97
98
98
if ( response . RequestMessage . Method != HttpMethod . Head )
99
99
{
@@ -223,7 +223,7 @@ private static unsafe int GetResponseHeader(SafeWinHttpHandle requestHandle, uin
223
223
/// <summary>
224
224
/// Returns the size of the char array buffer.
225
225
/// </summary>
226
- private static unsafe int GetResponseHeaderCharBufferLength ( SafeWinHttpHandle requestHandle , uint infoLevel )
226
+ public static unsafe int GetResponseHeaderCharBufferLength ( SafeWinHttpHandle requestHandle , uint infoLevel , bool isTrailingHeaders )
227
227
{
228
228
char * buffer = null ;
229
229
int bufferLength = 0 ;
@@ -233,11 +233,21 @@ private static unsafe int GetResponseHeaderCharBufferLength(SafeWinHttpHandle re
233
233
{
234
234
int lastError = Marshal . GetLastWin32Error ( ) ;
235
235
236
- Debug . Assert ( lastError != Interop . WinHttp . ERROR_WINHTTP_HEADER_NOT_FOUND ) ;
236
+ if ( ! isTrailingHeaders )
237
+ {
238
+ Debug . Assert ( lastError != Interop . WinHttp . ERROR_WINHTTP_HEADER_NOT_FOUND ) ;
237
239
238
- if ( lastError != Interop . WinHttp . ERROR_INSUFFICIENT_BUFFER )
240
+ if ( lastError != Interop . WinHttp . ERROR_INSUFFICIENT_BUFFER )
241
+ {
242
+ throw WinHttpException . CreateExceptionUsingError ( lastError , nameof ( Interop . WinHttp . WinHttpQueryHeaders ) ) ;
243
+ }
244
+ }
245
+ else
239
246
{
240
- throw WinHttpException . CreateExceptionUsingError ( lastError , nameof ( Interop . WinHttp . WinHttpQueryHeaders ) ) ;
247
+ if ( ! ( lastError == Interop . WinHttp . ERROR_INSUFFICIENT_BUFFER || lastError == Interop . WinHttp . ERROR_WINHTTP_HEADER_NOT_FOUND ) )
248
+ {
249
+ throw WinHttpException . CreateExceptionUsingError ( lastError , nameof ( Interop . WinHttp . WinHttpQueryHeaders ) ) ;
250
+ }
241
251
}
242
252
}
243
253
@@ -286,47 +296,69 @@ private static string GetReasonPhrase(HttpStatusCode statusCode, char[] buffer,
286
296
new string ( buffer , 0 , bufferLength ) ;
287
297
}
288
298
289
- private static void ParseResponseHeaders (
299
+ private class HttpResponseTrailers : HttpHeaders
300
+ {
301
+ }
302
+
303
+ public static void ParseResponseHeaders (
290
304
SafeWinHttpHandle requestHandle ,
305
+ uint infoLevel ,
291
306
HttpResponseMessage response ,
292
307
char [ ] buffer ,
293
- bool stripEncodingHeaders )
308
+ bool stripEncodingHeaders ,
309
+ bool isTrailers )
294
310
{
295
311
HttpResponseHeaders responseHeaders = response . Headers ;
296
312
HttpContentHeaders contentHeaders = response . Content . Headers ;
313
+ #if NETSTANDARD2_1
314
+ HttpResponseHeaders responseTrailers = response . TrailingHeaders ;
315
+ #else
316
+ HttpResponseTrailers responseTrailers = new HttpResponseTrailers ( ) ;
317
+ response . RequestMessage . Properties [ "__ResponseTrailers" ] = responseTrailers ;
318
+ #endif
297
319
298
320
int bufferLength = GetResponseHeader (
299
321
requestHandle ,
300
- Interop . WinHttp . WINHTTP_QUERY_RAW_HEADERS_CRLF ,
322
+ infoLevel ,
301
323
buffer ) ;
302
324
303
325
var reader = new WinHttpResponseHeaderReader ( buffer , 0 , bufferLength ) ;
304
326
305
- // Skip the first line which contains status code, etc. information that we already parsed.
306
- reader . ReadLine ( ) ;
327
+ if ( ! isTrailers )
328
+ {
329
+ // Skip the first line which contains status code, etc. information that we already parsed.
330
+ reader . ReadLine ( ) ;
331
+ }
307
332
308
333
// Parse the array of headers and split them between Content headers and Response headers.
309
334
string headerName ;
310
335
string headerValue ;
311
336
312
337
while ( reader . ReadHeader ( out headerName , out headerValue ) )
313
338
{
314
- if ( ! responseHeaders . TryAddWithoutValidation ( headerName , headerValue ) )
339
+ if ( ! isTrailers )
315
340
{
316
- if ( stripEncodingHeaders )
341
+ if ( ! responseHeaders . TryAddWithoutValidation ( headerName , headerValue ) )
317
342
{
318
- // Remove Content-Length and Content-Encoding headers if we are
319
- // decompressing the response stream in the handler (due to
320
- // WINHTTP not supporting it in a particular downlevel platform).
321
- // This matches the behavior of WINHTTP when it does decompression itself.
322
- if ( string . Equals ( HttpKnownHeaderNames . ContentLength , headerName , StringComparison . OrdinalIgnoreCase ) ||
323
- string . Equals ( HttpKnownHeaderNames . ContentEncoding , headerName , StringComparison . OrdinalIgnoreCase ) )
343
+ if ( stripEncodingHeaders )
324
344
{
325
- continue ;
345
+ // Remove Content-Length and Content-Encoding headers if we are
346
+ // decompressing the response stream in the handler (due to
347
+ // WINHTTP not supporting it in a particular downlevel platform).
348
+ // This matches the behavior of WINHTTP when it does decompression itself.
349
+ if ( string . Equals ( HttpKnownHeaderNames . ContentLength , headerName , StringComparison . OrdinalIgnoreCase ) ||
350
+ string . Equals ( HttpKnownHeaderNames . ContentEncoding , headerName , StringComparison . OrdinalIgnoreCase ) )
351
+ {
352
+ continue ;
353
+ }
326
354
}
327
- }
328
355
329
- contentHeaders . TryAddWithoutValidation ( headerName , headerValue ) ;
356
+ contentHeaders . TryAddWithoutValidation ( headerName , headerValue ) ;
357
+ }
358
+ }
359
+ else
360
+ {
361
+ responseTrailers . TryAddWithoutValidation ( headerName , headerValue ) ;
330
362
}
331
363
}
332
364
}
0 commit comments