@@ -241,6 +241,64 @@ void testConvertFromFieldsConnectPresentPath() {
241241 "Header ':path' must not be set for CONNECT request" );
242242 }
243243
244+ @ Test
245+ void testConvertFromFieldsExtendedConnect () throws Exception {
246+ final List <Header > headers = Arrays .asList (
247+ new BasicHeader (":method" , "CONNECT" ),
248+ new BasicHeader (":protocol" , "websocket" ),
249+ new BasicHeader (":scheme" , "https" ),
250+ new BasicHeader (":authority" , "www.example.com" ),
251+ new BasicHeader (":path" , "/chat" ));
252+
253+ final DefaultH2RequestConverter converter = new DefaultH2RequestConverter ();
254+ final HttpRequest request = converter .convert (headers );
255+
256+ Assertions .assertEquals ("CONNECT" , request .getMethod ());
257+ Assertions .assertEquals ("https" , request .getScheme ());
258+ Assertions .assertEquals ("/chat" , request .getPath ());
259+ Assertions .assertEquals ("websocket" , request .getFirstHeader (":protocol" ).getValue ());
260+ }
261+
262+ @ Test
263+ void testConvertFromFieldsExtendedConnectMissingScheme () {
264+ final List <Header > headers = Arrays .asList (
265+ new BasicHeader (":method" , "CONNECT" ),
266+ new BasicHeader (":protocol" , "websocket" ),
267+ new BasicHeader (":authority" , "www.example.com" ),
268+ new BasicHeader (":path" , "/chat" ));
269+
270+ final DefaultH2RequestConverter converter = new DefaultH2RequestConverter ();
271+ Assertions .assertThrows (HttpException .class , () -> converter .convert (headers ),
272+ "Header ':scheme' is mandatory for extended CONNECT" );
273+ }
274+
275+ @ Test
276+ void testConvertFromFieldsExtendedConnectMissingPath () {
277+ final List <Header > headers = Arrays .asList (
278+ new BasicHeader (":method" , "CONNECT" ),
279+ new BasicHeader (":protocol" , "websocket" ),
280+ new BasicHeader (":scheme" , "https" ),
281+ new BasicHeader (":authority" , "www.example.com" ));
282+
283+ final DefaultH2RequestConverter converter = new DefaultH2RequestConverter ();
284+ Assertions .assertThrows (HttpException .class , () -> converter .convert (headers ),
285+ "Header ':path' is mandatory for extended CONNECT" );
286+ }
287+
288+ @ Test
289+ void testConvertFromFieldsProtocolWithNonConnect () {
290+ final List <Header > headers = Arrays .asList (
291+ new BasicHeader (":method" , "GET" ),
292+ new BasicHeader (":protocol" , "websocket" ),
293+ new BasicHeader (":scheme" , "https" ),
294+ new BasicHeader (":authority" , "www.example.com" ),
295+ new BasicHeader (":path" , "/" ));
296+
297+ final DefaultH2RequestConverter converter = new DefaultH2RequestConverter ();
298+ Assertions .assertThrows (HttpException .class , () -> converter .convert (headers ),
299+ "Header ':protocol' must not be set for GET request" );
300+ }
301+
244302 @ Test
245303 void testConvertFromMessageBasic () throws Exception {
246304
@@ -332,6 +390,53 @@ void testConvertFromMessageConnectWithPath() {
332390 "CONNECT request path must be null" );
333391 }
334392
393+ @ Test
394+ void testConvertFromMessageExtendedConnect () throws Exception {
395+ final HttpRequest request = new BasicHttpRequest ("CONNECT" , new HttpHost ("host" ), "/chat" );
396+ request .setScheme ("https" );
397+ request .setAuthority (new URIAuthority ("host" ));
398+ request .addHeader (":protocol" , "websocket" );
399+
400+ final DefaultH2RequestConverter converter = new DefaultH2RequestConverter ();
401+ final List <Header > headers = converter .convert (request );
402+
403+ Assertions .assertTrue (headers .stream ().anyMatch (h -> ":protocol" .equals (h .getName ())));
404+ }
405+
406+ @ Test
407+ void testConvertFromMessageExtendedConnectMissingScheme () {
408+ final HttpRequest request = new BasicHttpRequest ("CONNECT" , new HttpHost ("host" ), "/chat" );
409+ request .setAuthority (new URIAuthority ("host" ));
410+ request .setScheme (null );
411+ request .addHeader (":protocol" , "websocket" );
412+
413+ final DefaultH2RequestConverter converter = new DefaultH2RequestConverter ();
414+ Assertions .assertThrows (HttpException .class , () -> converter .convert (request ),
415+ "CONNECT request scheme is not set" );
416+ }
417+
418+ @ Test
419+ void testConvertFromMessageExtendedConnectMissingPath () {
420+ final HttpRequest request = new BasicHttpRequest ("CONNECT" , new HttpHost ("host" ), null );
421+ request .setAuthority (new URIAuthority ("host" ));
422+ request .setScheme ("https" );
423+ request .addHeader (":protocol" , "websocket" );
424+
425+ final DefaultH2RequestConverter converter = new DefaultH2RequestConverter ();
426+ Assertions .assertThrows (HttpException .class , () -> converter .convert (request ),
427+ "CONNECT request path is not set" );
428+ }
429+
430+ @ Test
431+ void testConvertFromMessageProtocolWithNonConnect () {
432+ final HttpRequest request = new BasicHttpRequest ("GET" , new HttpHost ("host" ), "/" );
433+ request .addHeader (":protocol" , "websocket" );
434+
435+ final DefaultH2RequestConverter converter = new DefaultH2RequestConverter ();
436+ Assertions .assertThrows (HttpException .class , () -> converter .convert (request ),
437+ "Header name ':protocol' is invalid" );
438+ }
439+
335440 @ Test
336441 void testConvertFromFieldsTETrailerHeader () throws Exception {
337442
0 commit comments