@@ -37,12 +37,23 @@ use error::{Kind, Parse};
37
37
#[ derive( Clone , Debug ) ]
38
38
pub struct Http {
39
39
exec : Exec ,
40
- http2 : bool ,
40
+ mode : ConnectionMode ,
41
41
keep_alive : bool ,
42
42
max_buf_size : Option < usize > ,
43
43
pipeline_flush : bool ,
44
44
}
45
45
46
+ /// The internal mode of HTTP protocol which indicates the behavior when an parse error occurs.
47
+ #[ derive( Clone , Debug , PartialEq ) ]
48
+ enum ConnectionMode {
49
+ /// Always use HTTP/1 and do not upgrade when an parse error occurs.
50
+ H1Only ,
51
+ /// Always use HTTP/2.
52
+ H2Only ,
53
+ /// Use HTTP/1 and try to upgrade to h2 when an parse error occurs.
54
+ Fallback ,
55
+ }
56
+
46
57
/// A stream mapping incoming IOs to new services.
47
58
///
48
59
/// Yields `Connecting`s that are futures that should be put on a reactor.
94
105
S :: ResBody ,
95
106
> ,
96
107
> > ,
108
+ fallback : bool ,
97
109
}
98
110
99
111
/// Deconstructed parts of a `Connection`.
@@ -126,18 +138,34 @@ impl Http {
126
138
pub fn new ( ) -> Http {
127
139
Http {
128
140
exec : Exec :: Default ,
129
- http2 : false ,
141
+ mode : ConnectionMode :: Fallback ,
130
142
keep_alive : true ,
131
143
max_buf_size : None ,
132
144
pipeline_flush : false ,
133
145
}
134
146
}
135
147
148
+ /// Sets whether HTTP1 is required.
149
+ ///
150
+ /// Default is false
151
+ pub fn http1_only ( & mut self , val : bool ) -> & mut Self {
152
+ if val {
153
+ self . mode = ConnectionMode :: H1Only ;
154
+ } else {
155
+ self . mode = ConnectionMode :: Fallback ;
156
+ }
157
+ self
158
+ }
159
+
136
160
/// Sets whether HTTP2 is required.
137
161
///
138
162
/// Default is false
139
163
pub fn http2_only ( & mut self , val : bool ) -> & mut Self {
140
- self . http2 = val;
164
+ if val {
165
+ self . mode = ConnectionMode :: H2Only ;
166
+ } else {
167
+ self . mode = ConnectionMode :: Fallback ;
168
+ }
141
169
self
142
170
}
143
171
@@ -230,25 +258,29 @@ impl Http {
230
258
Bd : Payload ,
231
259
I : AsyncRead + AsyncWrite ,
232
260
{
233
- let either = if !self . http2 {
234
- let mut conn = proto:: Conn :: new ( io) ;
235
- if !self . keep_alive {
236
- conn. disable_keep_alive ( ) ;
261
+ let either = match self . mode {
262
+ ConnectionMode :: H1Only | ConnectionMode :: Fallback => {
263
+ let mut conn = proto:: Conn :: new ( io) ;
264
+ if !self . keep_alive {
265
+ conn. disable_keep_alive ( ) ;
266
+ }
267
+ conn. set_flush_pipeline ( self . pipeline_flush ) ;
268
+ if let Some ( max) = self . max_buf_size {
269
+ conn. set_max_buf_size ( max) ;
270
+ }
271
+ let sd = proto:: h1:: dispatch:: Server :: new ( service) ;
272
+ Either :: A ( proto:: h1:: Dispatcher :: new ( sd, conn) )
237
273
}
238
- conn. set_flush_pipeline ( self . pipeline_flush ) ;
239
- if let Some ( max) = self . max_buf_size {
240
- conn. set_max_buf_size ( max) ;
274
+ ConnectionMode :: H2Only => {
275
+ let rewind_io = Rewind :: new ( io) ;
276
+ let h2 = proto:: h2:: Server :: new ( rewind_io, service, self . exec . clone ( ) ) ;
277
+ Either :: B ( h2)
241
278
}
242
- let sd = proto:: h1:: dispatch:: Server :: new ( service) ;
243
- Either :: A ( proto:: h1:: Dispatcher :: new ( sd, conn) )
244
- } else {
245
- let rewind_io = Rewind :: new ( io) ;
246
- let h2 = proto:: h2:: Server :: new ( rewind_io, service, self . exec . clone ( ) ) ;
247
- Either :: B ( h2)
248
279
} ;
249
280
250
281
Connection {
251
282
conn : Some ( either) ,
283
+ fallback : self . mode == ConnectionMode :: Fallback ,
252
284
}
253
285
}
254
286
@@ -385,7 +417,7 @@ where
385
417
Err ( e) => {
386
418
debug ! ( "error polling connection protocol without shutdown: {}" , e) ;
387
419
match * e. kind ( ) {
388
- Kind :: Parse ( Parse :: VersionH2 ) => {
420
+ Kind :: Parse ( Parse :: VersionH2 ) if self . fallback => {
389
421
self . upgrade_h2 ( ) ;
390
422
continue ;
391
423
}
@@ -435,7 +467,7 @@ where
435
467
Err ( e) => {
436
468
debug ! ( "error polling connection protocol: {}" , e) ;
437
469
match * e. kind ( ) {
438
- Kind :: Parse ( Parse :: VersionH2 ) => {
470
+ Kind :: Parse ( Parse :: VersionH2 ) if self . fallback => {
439
471
self . upgrade_h2 ( ) ;
440
472
continue ;
441
473
}
0 commit comments