@@ -11,11 +11,18 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
11
11
{
12
12
internal sealed class Http2HeadersEnumerator : IEnumerator < KeyValuePair < string , string > >
13
13
{
14
- private bool _isTrailers ;
14
+ private enum HeadersType : byte
15
+ {
16
+ Headers ,
17
+ Trailers ,
18
+ Untyped
19
+ }
20
+ private HeadersType _headersType ;
15
21
private HttpResponseHeaders . Enumerator _headersEnumerator ;
16
22
private HttpResponseTrailers . Enumerator _trailersEnumerator ;
17
23
private IEnumerator < KeyValuePair < string , StringValues > > _genericEnumerator ;
18
24
private StringValues . Enumerator _stringValuesEnumerator ;
25
+ private bool _hasMultipleValues ;
19
26
private KnownHeaderType _knownHeaderType ;
20
27
21
28
public int HPackStaticTableId => GetResponseHeaderStaticTableId ( _knownHeaderType ) ;
@@ -29,136 +36,89 @@ public Http2HeadersEnumerator()
29
36
public void Initialize ( HttpResponseHeaders headers )
30
37
{
31
38
_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 ;
39
41
}
40
42
41
43
public void Initialize ( HttpResponseTrailers headers )
42
44
{
43
- _headersEnumerator = default ;
44
45
_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 ;
51
48
}
52
49
53
50
public void Initialize ( IDictionary < string , StringValues > headers )
54
51
{
55
- _headersEnumerator = default ;
56
- _trailersEnumerator = default ;
57
52
_genericEnumerator = headers . GetEnumerator ( ) ;
58
- _isTrailers = false ;
59
-
60
- _stringValuesEnumerator = default ;
61
- Current = default ;
62
- _knownHeaderType = default ;
53
+ _headersType = HeadersType . Untyped ;
54
+ _hasMultipleValues = false ;
63
55
}
64
56
65
57
public bool MoveNext ( )
66
58
{
67
- if ( MoveNextOnStringEnumerator ( ) )
59
+ if ( _hasMultipleValues && MoveNextOnStringEnumerator ( Current . Key ) )
68
60
{
69
61
return true ;
70
62
}
71
63
72
- if ( ! TryGetNextStringEnumerator ( out _stringValuesEnumerator ) )
64
+ if ( _headersType == HeadersType . Headers )
73
65
{
74
- return false ;
66
+ return _headersEnumerator . MoveNext ( )
67
+ ? SetCurrent ( _headersEnumerator . Current . Key , _headersEnumerator . Current . Value , _headersEnumerator . CurrentKnownType )
68
+ : false ;
75
69
}
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 )
87
71
{
88
- return _trailersEnumerator . Current . Key ;
72
+ return _trailersEnumerator . MoveNext ( )
73
+ ? SetCurrent ( _trailersEnumerator . Current . Key , _trailersEnumerator . Current . Value , _trailersEnumerator . CurrentKnownType )
74
+ : false ;
89
75
}
90
76
else
91
77
{
92
- return _headersEnumerator . Current . Key ;
78
+ return _genericEnumerator . MoveNext ( )
79
+ ? SetCurrent ( _genericEnumerator . Current . Key , _genericEnumerator . Current . Value , default )
80
+ : false ;
93
81
}
94
82
}
95
83
96
- private bool MoveNextOnStringEnumerator ( )
84
+ private bool MoveNextOnStringEnumerator ( string key )
97
85
{
98
86
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 ;
100
88
return result ;
101
89
}
102
90
103
- private bool TryGetNextStringEnumerator ( out StringValues . Enumerator enumerator )
91
+ private bool SetCurrent ( string name , StringValues value , KnownHeaderType knownHeaderType )
104
92
{
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 )
120
94
{
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 ;
132
99
}
133
100
else
134
101
{
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 ) ;
146
106
}
147
107
}
148
108
149
109
public void Reset ( )
150
110
{
151
- if ( _genericEnumerator != null )
111
+ if ( _headersType == HeadersType . Headers )
152
112
{
153
- _genericEnumerator . Reset ( ) ;
113
+ _headersEnumerator . Reset ( ) ;
154
114
}
155
- else if ( _isTrailers )
115
+ else if ( _headersType == HeadersType . Trailers )
156
116
{
157
117
_trailersEnumerator . Reset ( ) ;
158
118
}
159
119
else
160
120
{
161
- _headersEnumerator . Reset ( ) ;
121
+ _genericEnumerator . Reset ( ) ;
162
122
}
163
123
_stringValuesEnumerator = default ;
164
124
_knownHeaderType = default ;
0 commit comments