@@ -11,11 +11,18 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
1111{
1212 internal sealed class Http2HeadersEnumerator : IEnumerator < KeyValuePair < string , string > >
1313 {
14- private bool _isTrailers ;
14+ private enum HeadersType : byte
15+ {
16+ Headers ,
17+ Trailers ,
18+ Untyped
19+ }
20+ private HeadersType _headersType ;
1521 private HttpResponseHeaders . Enumerator _headersEnumerator ;
1622 private HttpResponseTrailers . Enumerator _trailersEnumerator ;
1723 private IEnumerator < KeyValuePair < string , StringValues > > _genericEnumerator ;
1824 private StringValues . Enumerator _stringValuesEnumerator ;
25+ private bool _hasMultipleValues ;
1926 private KnownHeaderType _knownHeaderType ;
2027
2128 public int HPackStaticTableId => GetResponseHeaderStaticTableId ( _knownHeaderType ) ;
@@ -29,136 +36,89 @@ public Http2HeadersEnumerator()
2936 public void Initialize ( HttpResponseHeaders headers )
3037 {
3138 _headersEnumerator = headers . GetEnumerator ( ) ;
32- _trailersEnumerator = default ;
33- _genericEnumerator = null ;
34- _isTrailers = false ;
35-
36- _stringValuesEnumerator = default ;
37- Current = default ;
38- _knownHeaderType = default ;
39+ _headersType = HeadersType . Headers ;
40+ _hasMultipleValues = false ;
3941 }
4042
4143 public void Initialize ( HttpResponseTrailers headers )
4244 {
43- _headersEnumerator = default ;
4445 _trailersEnumerator = headers . GetEnumerator ( ) ;
45- _genericEnumerator = null ;
46- _isTrailers = true ;
47-
48- _stringValuesEnumerator = default ;
49- Current = default ;
50- _knownHeaderType = default ;
46+ _headersType = HeadersType . Trailers ;
47+ _hasMultipleValues = false ;
5148 }
5249
5350 public void Initialize ( IDictionary < string , StringValues > headers )
5451 {
55- _headersEnumerator = default ;
56- _trailersEnumerator = default ;
5752 _genericEnumerator = headers . GetEnumerator ( ) ;
58- _isTrailers = false ;
59-
60- _stringValuesEnumerator = default ;
61- Current = default ;
62- _knownHeaderType = default ;
53+ _headersType = HeadersType . Untyped ;
54+ _hasMultipleValues = false ;
6355 }
6456
6557 public bool MoveNext ( )
6658 {
67- if ( MoveNextOnStringEnumerator ( ) )
59+ if ( _hasMultipleValues && MoveNextOnStringEnumerator ( Current . Key ) )
6860 {
6961 return true ;
7062 }
7163
72- if ( ! TryGetNextStringEnumerator ( out _stringValuesEnumerator ) )
64+ if ( _headersType == HeadersType . Headers )
7365 {
74- return false ;
66+ return _headersEnumerator . MoveNext ( )
67+ ? SetCurrent ( _headersEnumerator . Current . Key , _headersEnumerator . Current . Value , _headersEnumerator . CurrentKnownType )
68+ : false ;
7569 }
76-
77- return MoveNextOnStringEnumerator ( ) ;
78- }
79-
80- private string GetCurrentKey ( )
81- {
82- if ( _genericEnumerator != null )
83- {
84- return _genericEnumerator . Current . Key ;
85- }
86- else if ( _isTrailers )
70+ else if ( _headersType == HeadersType . Trailers )
8771 {
88- return _trailersEnumerator . Current . Key ;
72+ return _trailersEnumerator . MoveNext ( )
73+ ? SetCurrent ( _trailersEnumerator . Current . Key , _trailersEnumerator . Current . Value , _trailersEnumerator . CurrentKnownType )
74+ : false ;
8975 }
9076 else
9177 {
92- return _headersEnumerator . Current . Key ;
78+ return _genericEnumerator . MoveNext ( )
79+ ? SetCurrent ( _genericEnumerator . Current . Key , _genericEnumerator . Current . Value , default )
80+ : false ;
9381 }
9482 }
9583
96- private bool MoveNextOnStringEnumerator ( )
84+ private bool MoveNextOnStringEnumerator ( string key )
9785 {
9886 var result = _stringValuesEnumerator . MoveNext ( ) ;
99- Current = result ? new KeyValuePair < string , string > ( GetCurrentKey ( ) , _stringValuesEnumerator . Current ) : default ;
87+ Current = result ? new KeyValuePair < string , string > ( key , _stringValuesEnumerator . Current ) : default ;
10088 return result ;
10189 }
10290
103- private bool TryGetNextStringEnumerator ( out StringValues . Enumerator enumerator )
91+ private bool SetCurrent ( string name , StringValues value , KnownHeaderType knownHeaderType )
10492 {
105- if ( _genericEnumerator != null )
106- {
107- if ( ! _genericEnumerator . MoveNext ( ) )
108- {
109- enumerator = default ;
110- return false ;
111- }
112- else
113- {
114- enumerator = _genericEnumerator . Current . Value . GetEnumerator ( ) ;
115- _knownHeaderType = default ;
116- return true ;
117- }
118- }
119- else if ( _isTrailers )
93+ if ( value . Count == 1 )
12094 {
121- if ( ! _trailersEnumerator . MoveNext ( ) )
122- {
123- enumerator = default ;
124- return false ;
125- }
126- else
127- {
128- enumerator = _trailersEnumerator . Current . Value . GetEnumerator ( ) ;
129- _knownHeaderType = _trailersEnumerator . CurrentKnownType ;
130- return true ;
131- }
95+ Current = new KeyValuePair < string , string > ( name , value . ToString ( ) ) ;
96+ _knownHeaderType = knownHeaderType ;
97+ _hasMultipleValues = false ;
98+ return true ;
13299 }
133100 else
134101 {
135- if ( ! _headersEnumerator . MoveNext ( ) )
136- {
137- enumerator = default ;
138- return false ;
139- }
140- else
141- {
142- enumerator = _headersEnumerator . Current . Value . GetEnumerator ( ) ;
143- _knownHeaderType = _headersEnumerator . CurrentKnownType ;
144- return true ;
145- }
102+ _stringValuesEnumerator = value . GetEnumerator ( ) ;
103+ _hasMultipleValues = true ;
104+
105+ return MoveNextOnStringEnumerator ( name ) ;
146106 }
147107 }
148108
149109 public void Reset ( )
150110 {
151- if ( _genericEnumerator != null )
111+ if ( _headersType == HeadersType . Headers )
152112 {
153- _genericEnumerator . Reset ( ) ;
113+ _headersEnumerator . Reset ( ) ;
154114 }
155- else if ( _isTrailers )
115+ else if ( _headersType == HeadersType . Trailers )
156116 {
157117 _trailersEnumerator . Reset ( ) ;
158118 }
159119 else
160120 {
161- _headersEnumerator . Reset ( ) ;
121+ _genericEnumerator . Reset ( ) ;
162122 }
163123 _stringValuesEnumerator = default ;
164124 _knownHeaderType = default ;
0 commit comments