View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.hc.core5.testing.classic;
29  
30  import java.io.BufferedReader;
31  import java.io.IOException;
32  import java.io.InputStream;
33  import java.io.InputStreamReader;
34  import java.io.OutputStream;
35  import java.nio.charset.Charset;
36  import java.nio.charset.StandardCharsets;
37  import java.util.ArrayList;
38  import java.util.List;
39  import java.util.Random;
40  
41  import org.apache.hc.core5.http.ClassicHttpRequest;
42  import org.apache.hc.core5.http.ClassicHttpResponse;
43  import org.apache.hc.core5.http.ContentType;
44  import org.apache.hc.core5.http.Header;
45  import org.apache.hc.core5.http.HttpEntity;
46  import org.apache.hc.core5.http.HttpException;
47  import org.apache.hc.core5.http.HttpHeaders;
48  import org.apache.hc.core5.http.HttpHost;
49  import org.apache.hc.core5.http.HttpStatus;
50  import org.apache.hc.core5.http.HttpVersion;
51  import org.apache.hc.core5.http.Method;
52  import org.apache.hc.core5.http.URIScheme;
53  import org.apache.hc.core5.http.config.Http1Config;
54  import org.apache.hc.core5.http.io.entity.AbstractHttpEntity;
55  import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
56  import org.apache.hc.core5.http.io.entity.EntityUtils;
57  import org.apache.hc.core5.http.io.entity.StringEntity;
58  import org.apache.hc.core5.http.io.support.BasicHttpServerExpectationDecorator;
59  import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
60  import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
61  import org.apache.hc.core5.http.protocol.DefaultHttpProcessor;
62  import org.apache.hc.core5.http.protocol.HttpContext;
63  import org.apache.hc.core5.http.protocol.HttpCoreContext;
64  import org.apache.hc.core5.http.protocol.RequestConnControl;
65  import org.apache.hc.core5.http.protocol.RequestContent;
66  import org.apache.hc.core5.http.protocol.RequestExpectContinue;
67  import org.apache.hc.core5.http.protocol.RequestTargetHost;
68  import org.apache.hc.core5.http.protocol.RequestUserAgent;
69  import org.apache.hc.core5.testing.classic.extension.ClassicTestResources;
70  import org.apache.hc.core5.util.Timeout;
71  import org.junit.jupiter.api.Assertions;
72  import org.junit.jupiter.api.Test;
73  import org.junit.jupiter.api.extension.RegisterExtension;
74  
75  public abstract class ClassicIntegrationTest {
76  
77      private static final Timeout TIMEOUT = Timeout.ofMinutes(1);
78  
79      private final URIScheme scheme;
80      @RegisterExtension
81      private final ClassicTestResources testResources;
82  
83      public ClassicIntegrationTest(final URIScheme scheme) {
84          this.scheme = scheme;
85          this.testResources = new ClassicTestResources(scheme, TIMEOUT);
86      }
87  
88      /**
89       * This test case executes a series of simple GET requests
90       */
91      @Test
92      public void testSimpleBasicHttpRequests() throws Exception {
93          final ClassicTestServer server = testResources.server();
94          final ClassicTestClient client = testResources.client();
95  
96          final int reqNo = 20;
97  
98          final Random rnd = new Random();
99  
100         // Prepare some random data
101         final List<byte[]> testData = new ArrayList<>(reqNo);
102         for (int i = 0; i < reqNo; i++) {
103             final int size = rnd.nextInt(5000);
104             final byte[] data = new byte[size];
105             rnd.nextBytes(data);
106             testData.add(data);
107         }
108 
109 
110         // Initialize the server-side request handler
111         server.registerHandler("*", (request, response, context) -> {
112 
113             String s = request.getPath();
114             if (s.startsWith("/?")) {
115                 s = s.substring(2);
116             }
117             final int index = Integer.parseInt(s);
118             final byte[] data = testData.get(index);
119             final ByteArrayEntity entity = new ByteArrayEntity(data, null);
120             response.setEntity(entity);
121         });
122 
123         server.start();
124         client.start();
125 
126         final HttpCoreContext context = HttpCoreContext.create();
127         final HttpHost host = new HttpHost(scheme.id, "localhost", server.getPort());
128 
129         for (int r = 0; r < reqNo; r++) {
130             final BasicClassicHttpRequest get = new BasicClassicHttpRequest(Method.GET, "/?" + r);
131             try (final ClassicHttpResponse response = client.execute(host, get, context)) {
132                 final byte[] received = EntityUtils.toByteArray(response.getEntity());
133                 final byte[] expected = testData.get(r);
134 
135                 Assertions.assertEquals(expected.length, received.length);
136                 for (int i = 0; i < expected.length; i++) {
137                     Assertions.assertEquals(expected[i], received[i]);
138                 }
139             }
140         }
141     }
142 
143     /**
144      * This test case executes a series of simple POST requests with content length
145      * delimited content.
146      */
147     @Test
148     public void testSimpleHttpPostsWithContentLength() throws Exception {
149         final ClassicTestServer server = testResources.server();
150         final ClassicTestClient client = testResources.client();
151 
152         final int reqNo = 20;
153 
154         final Random rnd = new Random();
155 
156         // Prepare some random data
157         final List<byte[]> testData = new ArrayList<>(reqNo);
158         for (int i = 0; i < reqNo; i++) {
159             final int size = rnd.nextInt(5000);
160             final byte[] data = new byte[size];
161             rnd.nextBytes(data);
162             testData.add(data);
163         }
164 
165         // Initialize the server-side request handler
166         server.registerHandler("*", (request, response, context) -> {
167 
168             final HttpEntity entity = request.getEntity();
169             if (entity != null) {
170                 final byte[] data = EntityUtils.toByteArray(entity);
171                 response.setEntity(new ByteArrayEntity(data, null));
172             }
173         });
174 
175         server.start();
176         client.start();
177 
178         final HttpCoreContext context = HttpCoreContext.create();
179         final HttpHost host = new HttpHost(scheme.id, "localhost", server.getPort());
180 
181         for (int r = 0; r < reqNo; r++) {
182             final BasicClassicHttpRequest post = new BasicClassicHttpRequest(Method.POST, "/");
183             final byte[] data = testData.get(r);
184             post.setEntity(new ByteArrayEntity(data, null));
185 
186             try (final ClassicHttpResponse response = client.execute(host, post, context)) {
187                 final byte[] received = EntityUtils.toByteArray(response.getEntity());
188                 final byte[] expected = testData.get(r);
189 
190                 Assertions.assertEquals(expected.length, received.length);
191                 for (int i = 0; i < expected.length; i++) {
192                     Assertions.assertEquals(expected[i], received[i]);
193                 }
194             }
195         }
196     }
197 
198     /**
199      * This test case executes a series of simple POST requests with chunk
200      * coded content content.
201      */
202     @Test
203     public void testSimpleHttpPostsChunked() throws Exception {
204         final ClassicTestServer server = testResources.server();
205         final ClassicTestClient client = testResources.client();
206 
207         final int reqNo = 20;
208 
209         final Random rnd = new Random();
210 
211         // Prepare some random data
212         final List<byte[]> testData = new ArrayList<>(reqNo);
213         for (int i = 0; i < reqNo; i++) {
214             final int size = rnd.nextInt(20000);
215             final byte[] data = new byte[size];
216             rnd.nextBytes(data);
217             testData.add(data);
218         }
219 
220         // Initialize the server-side request handler
221         server.registerHandler("*", (request, response, context) -> {
222 
223             final HttpEntity entity = request.getEntity();
224             if (entity != null) {
225                 final byte[] data = EntityUtils.toByteArray(entity);
226                 response.setEntity(new ByteArrayEntity(data, null, true));
227             }
228         });
229 
230         server.start();
231         client.start();
232 
233         final HttpCoreContext context = HttpCoreContext.create();
234         final HttpHost host = new HttpHost(scheme.id, "localhost", server.getPort());
235 
236         for (int r = 0; r < reqNo; r++) {
237             final BasicClassicHttpRequest post = new BasicClassicHttpRequest(Method.POST, "/");
238             final byte[] data = testData.get(r);
239             post.setEntity(new ByteArrayEntity(data, null, true));
240 
241             try (final ClassicHttpResponse response = client.execute(host, post, context)) {
242                 final byte[] received = EntityUtils.toByteArray(response.getEntity());
243                 final byte[] expected = testData.get(r);
244 
245                 Assertions.assertEquals(expected.length, received.length);
246                 for (int i = 0; i < expected.length; i++) {
247                     Assertions.assertEquals(expected[i], received[i]);
248                 }
249             }
250         }
251     }
252 
253     /**
254      * This test case executes a series of simple HTTP/1.0 POST requests.
255      */
256     @Test
257     public void testSimpleHttpPostsHTTP10() throws Exception {
258         final ClassicTestServer server = testResources.server();
259         final ClassicTestClient client = testResources.client();
260 
261         final int reqNo = 20;
262 
263         final Random rnd = new Random();
264 
265         // Prepare some random data
266         final List<byte[]> testData = new ArrayList<>(reqNo);
267         for (int i = 0; i < reqNo; i++) {
268             final int size = rnd.nextInt(5000);
269             final byte[] data = new byte[size];
270             rnd.nextBytes(data);
271             testData.add(data);
272         }
273 
274         // Initialize the server-side request handler
275         server.registerHandler("*", (request, response, context) -> {
276 
277             final HttpEntity entity = request.getEntity();
278             if (entity != null) {
279                 final byte[] data = EntityUtils.toByteArray(entity);
280                 response.setEntity(new ByteArrayEntity(data, null));
281             }
282             if (HttpVersion.HTTP_1_0.equals(request.getVersion())) {
283                 response.addHeader("Version", "1.0");
284             }
285         });
286 
287         server.start();
288         client.start();
289 
290         final HttpCoreContext context = HttpCoreContext.create();
291         final HttpHost host = new HttpHost(scheme.id, "localhost", server.getPort());
292 
293         for (int r = 0; r < reqNo; r++) {
294             // Set protocol level to HTTP/1.0
295             final BasicClassicHttpRequest post = new BasicClassicHttpRequest(Method.POST, "/");
296             post.setVersion(HttpVersion.HTTP_1_0);
297             final byte[] data = testData.get(r);
298             post.setEntity(new ByteArrayEntity(data, null));
299 
300             try (final ClassicHttpResponse response = client.execute(host, post, context)) {
301                 Assertions.assertEquals(HttpVersion.HTTP_1_1, response.getVersion());
302                 final Header h1 = response.getFirstHeader("Version");
303                 Assertions.assertNotNull(h1);
304                 Assertions.assertEquals("1.0", h1.getValue());
305                 final byte[] received = EntityUtils.toByteArray(response.getEntity());
306                 final byte[] expected = testData.get(r);
307 
308                 Assertions.assertEquals(expected.length, received.length);
309                 for (int i = 0; i < expected.length; i++) {
310                     Assertions.assertEquals(expected[i], received[i]);
311                 }
312             }
313         }
314     }
315 
316     /**
317      * This test case executes a series of simple POST requests using
318      * the 'expect: continue' handshake.
319      */
320     @Test
321     public void testHttpPostsWithExpectContinue() throws Exception {
322         final ClassicTestServer server = testResources.server();
323         final ClassicTestClient client = testResources.client();
324 
325         final int reqNo = 20;
326 
327         final Random rnd = new Random();
328 
329         // Prepare some random data
330         final List<byte[]> testData = new ArrayList<>(reqNo);
331         for (int i = 0; i < reqNo; i++) {
332             final int size = rnd.nextInt(5000);
333             final byte[] data = new byte[size];
334             rnd.nextBytes(data);
335             testData.add(data);
336         }
337 
338         // Initialize the server-side request handler
339         server.registerHandler("*", (request, response, context) -> {
340 
341             final HttpEntity entity = request.getEntity();
342             if (entity != null) {
343                 final byte[] data = EntityUtils.toByteArray(entity);
344                 response.setEntity(new ByteArrayEntity(data, null, true));
345             }
346         });
347 
348         server.start();
349         client.start();
350 
351         final HttpCoreContext context = HttpCoreContext.create();
352         final HttpHost host = new HttpHost(scheme.id, "localhost", server.getPort());
353 
354         for (int r = 0; r < reqNo; r++) {
355             final BasicClassicHttpRequest post = new BasicClassicHttpRequest(Method.POST, "/");
356             final byte[] data = testData.get(r);
357             post.setEntity(new ByteArrayEntity(data, null, true));
358 
359             try (final ClassicHttpResponse response = client.execute(host, post, context)) {
360                 final byte[] received = EntityUtils.toByteArray(response.getEntity());
361                 final byte[] expected = testData.get(r);
362 
363                 Assertions.assertEquals(expected.length, received.length);
364                 for (int i = 0; i < expected.length; i++) {
365                     Assertions.assertEquals(expected[i], received[i]);
366                 }
367             }
368         }
369     }
370 
371     /**
372      * This test case executes a series of simple POST requests that do not
373      * meet the target server expectations.
374      */
375     @Test
376     public void testHttpPostsWithExpectationVerification() throws Exception {
377         final ClassicTestServer server = testResources.server();
378         final ClassicTestClient client = testResources.client();
379 
380         final int reqNo = 20;
381 
382         // Initialize the server-side request handler
383         server.registerHandler("*", (request, response, context) -> response.setEntity(new StringEntity("No content")));
384 
385         server.start(null, null, handler -> new BasicHttpServerExpectationDecorator(handler) {
386 
387             @Override
388             protected ClassicHttpResponse verify(final ClassicHttpRequest request, final HttpContext context) {
389                 final Header someheader = request.getFirstHeader("Secret");
390                 if (someheader != null) {
391                     final int secretNumber;
392                     try {
393                         secretNumber = Integer.parseInt(someheader.getValue());
394                     } catch (final NumberFormatException ex) {
395                         final ClassicHttpResponse response = new BasicClassicHttpResponse(HttpStatus.SC_BAD_REQUEST);
396                         response.setEntity(new StringEntity(ex.toString()));
397                         return response;
398                     }
399                     if (secretNumber >= 2) {
400                         final ClassicHttpResponse response = new BasicClassicHttpResponse(HttpStatus.SC_EXPECTATION_FAILED);
401                         response.setEntity(new StringEntity("Wrong secret number", ContentType.TEXT_PLAIN));
402                         return response;
403                     }
404                 }
405                 return null;
406             }
407 
408         });
409         client.start();
410 
411         final HttpCoreContext context = HttpCoreContext.create();
412         final HttpHost host = new HttpHost(scheme.id, "localhost", server.getPort());
413 
414         for (int r = 0; r < reqNo; r++) {
415             final BasicClassicHttpRequest post = new BasicClassicHttpRequest(Method.POST, "/");
416             post.addHeader("Secret", Integer.toString(r));
417 
418             final byte[] b = new byte[2048];
419             for (int i = 0; i < b.length; i++) {
420                 b[i] = (byte) ('a' + r);
421             }
422             post.setEntity(new ByteArrayEntity(b, ContentType.TEXT_PLAIN));
423 
424             try (final ClassicHttpResponse response = client.execute(host, post, context)) {
425                 final HttpEntity responseEntity = response.getEntity();
426                 Assertions.assertNotNull(responseEntity);
427                 EntityUtils.consume(responseEntity);
428 
429                 if (r >= 2) {
430                     Assertions.assertEquals(HttpStatus.SC_EXPECTATION_FAILED, response.getCode());
431                 } else {
432                     Assertions.assertEquals(HttpStatus.SC_OK, response.getCode());
433                 }
434             }
435         }
436     }
437 
438     static class RepeatingEntity extends AbstractHttpEntity {
439 
440         private final byte[] raw;
441         private final int n;
442 
443         public RepeatingEntity(final String content, final Charset charset, final int n, final boolean chunked) {
444             super(ContentType.TEXT_PLAIN.withCharset(charset), null, chunked);
445             final Charset cs = charset != null ? charset : StandardCharsets.US_ASCII;
446             this.raw = content.getBytes(cs);
447             this.n = n;
448         }
449 
450         @Override
451         public InputStream getContent() throws IOException, IllegalStateException {
452             throw new IllegalStateException("This method is not implemented");
453         }
454 
455         @Override
456         public long getContentLength() {
457             return (this.raw.length + 2) * this.n;
458         }
459 
460         @Override
461         public boolean isRepeatable() {
462             return true;
463         }
464 
465         @Override
466         public boolean isStreaming() {
467             return false;
468         }
469 
470         @Override
471         public void writeTo(final OutputStream outStream) throws IOException {
472             for (int i = 0; i < this.n; i++) {
473                 outStream.write(this.raw);
474                 outStream.write('\r');
475                 outStream.write('\n');
476             }
477             outStream.flush();
478         }
479 
480         @Override
481         public void close() throws IOException {
482         }
483 
484     }
485 
486     @Test
487     public void testHttpContent() throws Exception {
488         final ClassicTestServer server = testResources.server();
489         final ClassicTestClient client = testResources.client();
490 
491         final String[] patterns = {
492 
493             "0123456789ABCDEF",
494             "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
495             "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
496             "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
497             "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
498             "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
499             "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
500             "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
501             "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
502             "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
503             "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
504             "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
505             "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
506             "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
507             "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
508             "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that"
509         };
510 
511         // Initialize the server-side request handler
512         server.registerHandler("*", (request, response, context) -> {
513 
514             int n = 1;
515             String s = request.getPath();
516             if (s.startsWith("/?n=")) {
517                 s = s.substring(4);
518                 try {
519                     n = Integer.parseInt(s);
520                     if (n <= 0) {
521                         throw new HttpException("Invalid request: " +
522                                 "number of repetitions cannot be negative or zero");
523                     }
524                 } catch (final NumberFormatException ex) {
525                     throw new HttpException("Invalid request: " +
526                             "number of repetitions is invalid");
527                 }
528             }
529 
530             final HttpEntity entity = request.getEntity();
531             if (entity != null) {
532                 final String line = EntityUtils.toString(entity);
533                 final ContentType contentType = ContentType.parse(entity.getContentType());
534                 final Charset charset = ContentType.getCharset(contentType, StandardCharsets.ISO_8859_1);
535                 response.setEntity(new RepeatingEntity(line, charset, n, n % 2 == 0));
536             }
537         });
538 
539         server.start();
540         client.start();
541 
542         final HttpCoreContext context = HttpCoreContext.create();
543         final HttpHost host = new HttpHost(scheme.id, "localhost", server.getPort());
544 
545         for (final String pattern : patterns) {
546             for (int n = 1000; n < 1020; n++) {
547                 final BasicClassicHttpRequest post = new BasicClassicHttpRequest(
548                         Method.POST.name(), "/?n=" + n);
549                 post.setEntity(new StringEntity(pattern, ContentType.TEXT_PLAIN, n % 2 == 0));
550 
551                 try (final ClassicHttpResponse response = client.execute(host, post, context)) {
552                     final HttpEntity entity = response.getEntity();
553                     Assertions.assertNotNull(entity);
554                     final InputStream inStream = entity.getContent();
555                     final ContentType contentType = ContentType.parse(entity.getContentType());
556                     final Charset charset = ContentType.getCharset(contentType, StandardCharsets.ISO_8859_1);
557                     Assertions.assertNotNull(inStream);
558                     final BufferedReader reader = new BufferedReader(new InputStreamReader(inStream, charset));
559 
560                     String line;
561                     int count = 0;
562                     while ((line = reader.readLine()) != null) {
563                         Assertions.assertEquals(pattern, line);
564                         count++;
565                     }
566                     Assertions.assertEquals(n, count);
567                 }
568             }
569         }
570     }
571 
572     @Test
573     public void testHttpPostNoEntity() throws Exception {
574         final ClassicTestServer server = testResources.server();
575         final ClassicTestClient client = testResources.client();
576 
577         server.registerHandler("*", (request, response, context) -> {
578 
579             final HttpEntity entity = request.getEntity();
580             if (entity != null) {
581                 final byte[] data = EntityUtils.toByteArray(entity);
582                 response.setEntity(new ByteArrayEntity(data, null));
583             }
584         });
585 
586         server.start();
587         client.start();
588 
589         final HttpCoreContext context = HttpCoreContext.create();
590         final HttpHost host = new HttpHost(scheme.id, "localhost", server.getPort());
591 
592         final BasicClassicHttpRequest post = new BasicClassicHttpRequest(Method.POST, "/");
593         post.setEntity(null);
594 
595         try (final ClassicHttpResponse response = client.execute(host, post, context)) {
596             Assertions.assertEquals(HttpStatus.SC_OK, response.getCode());
597             final byte[] received = EntityUtils.toByteArray(response.getEntity());
598             Assertions.assertEquals(0, received.length);
599         }
600     }
601 
602     @Test
603     public void testHttpPostNoContentLength() throws Exception {
604         final ClassicTestServer server = testResources.server();
605         final ClassicTestClient client = testResources.client();
606 
607         server.registerHandler("*", (request, response, context) -> {
608 
609             final HttpEntity entity = request.getEntity();
610             if (entity != null) {
611                 final byte[] data = EntityUtils.toByteArray(entity);
612                 response.setEntity(new ByteArrayEntity(data, null));
613             }
614         });
615 
616         server.start();
617         client.start(new DefaultHttpProcessor(
618                 RequestTargetHost.INSTANCE,
619                 RequestConnControl.INSTANCE,
620                 RequestUserAgent.INSTANCE,
621                 RequestExpectContinue.INSTANCE));
622 
623         final HttpCoreContext context = HttpCoreContext.create();
624         final HttpHost host = new HttpHost(scheme.id, "localhost", server.getPort());
625 
626         final BasicClassicHttpRequest post = new BasicClassicHttpRequest(Method.POST, "/");
627         post.setEntity(null);
628 
629         try (final ClassicHttpResponse response = client.execute(host, post, context)) {
630             Assertions.assertEquals(HttpStatus.SC_OK, response.getCode());
631             final byte[] received = EntityUtils.toByteArray(response.getEntity());
632             Assertions.assertEquals(0, received.length);
633         }
634     }
635 
636     @Test
637     public void testHttpPostIdentity() throws Exception {
638         final ClassicTestServer server = testResources.server();
639         final ClassicTestClient client = testResources.client();
640 
641         server.registerHandler("*", (request, response, context) -> {
642 
643             final HttpEntity entity = request.getEntity();
644             if (entity != null) {
645                 final byte[] data = EntityUtils.toByteArray(entity);
646                 response.setEntity(new ByteArrayEntity(data, null));
647             }
648         });
649 
650         server.start();
651         client.start(new DefaultHttpProcessor(
652                 (request, entity, context) -> request.addHeader(HttpHeaders.TRANSFER_ENCODING, "identity"),
653                 RequestTargetHost.INSTANCE,
654                 RequestConnControl.INSTANCE,
655                 RequestUserAgent.INSTANCE,
656                 RequestExpectContinue.INSTANCE));
657 
658         final HttpCoreContext context = HttpCoreContext.create();
659         final HttpHost host = new HttpHost(scheme.id, "localhost", server.getPort());
660 
661         final BasicClassicHttpRequest post = new BasicClassicHttpRequest(Method.POST, "/");
662         post.setEntity(null);
663 
664         try (final ClassicHttpResponse response = client.execute(host, post, context)) {
665             Assertions.assertEquals(HttpStatus.SC_NOT_IMPLEMENTED, response.getCode());
666         }
667     }
668 
669     @Test
670     public void testNoContentResponse() throws Exception {
671         final ClassicTestServer server = testResources.server();
672         final ClassicTestClient client = testResources.client();
673 
674         final int reqNo = 20;
675 
676         // Initialize the server-side request handler
677         server.registerHandler("*", (request, response, context) -> response.setCode(HttpStatus.SC_NO_CONTENT));
678 
679         server.start();
680         client.start();
681 
682         final HttpCoreContext context = HttpCoreContext.create();
683         final HttpHost host = new HttpHost(scheme.id, "localhost", server.getPort());
684 
685         for (int r = 0; r < reqNo; r++) {
686             final BasicClassicHttpRequest get = new BasicClassicHttpRequest(Method.GET, "/?" + r);
687             try (final ClassicHttpResponse response = client.execute(host, get, context)) {
688                 Assertions.assertNull(response.getEntity());
689             }
690         }
691     }
692 
693     @Test
694     public void testAbsentHostHeader() throws Exception {
695         final ClassicTestServer server = testResources.server();
696         final ClassicTestClient client = testResources.client();
697 
698         // Initialize the server-side request handler
699         server.registerHandler("*", (request, response, context) -> response.setEntity(new StringEntity("All is well", StandardCharsets.US_ASCII)));
700 
701         server.start();
702         client.start(new DefaultHttpProcessor(RequestContent.INSTANCE, new RequestConnControl()));
703 
704         final HttpCoreContext context = HttpCoreContext.create();
705         final HttpHost host = new HttpHost(scheme.id, "localhost", server.getPort());
706 
707         final BasicClassicHttpRequest get1 = new BasicClassicHttpRequest(Method.GET, "/");
708         get1.setVersion(HttpVersion.HTTP_1_0);
709         try (final ClassicHttpResponse response1 = client.execute(host, get1, context)) {
710             Assertions.assertEquals(200, response1.getCode());
711             EntityUtils.consume(response1.getEntity());
712         }
713 
714         final BasicClassicHttpRequest get2 = new BasicClassicHttpRequest(Method.GET, "/");
715         try (final ClassicHttpResponse response2 = client.execute(host, get2, context)) {
716             Assertions.assertEquals(400, response2.getCode());
717             EntityUtils.consume(response2.getEntity());
718         }
719     }
720 
721     @Test
722     public void testHeaderTooLarge() throws Exception {
723         final ClassicTestServer server = testResources.server();
724         final ClassicTestClient client = testResources.client();
725 
726         server.registerHandler("*", (request, response, context) ->
727                 response.setEntity(new StringEntity("All is well", StandardCharsets.US_ASCII)));
728 
729         server.start(
730                 Http1Config.custom()
731                         .setMaxLineLength(100)
732                         .build(),
733                 null,
734                 null);
735         client.start();
736 
737         final HttpCoreContext context = HttpCoreContext.create();
738         final HttpHost host = new HttpHost(scheme.id, "localhost", server.getPort());
739 
740         final BasicClassicHttpRequest get1 = new BasicClassicHttpRequest(Method.GET, "/");
741         get1.setHeader("big-f-header", "1234567890123456789012345678901234567890123456789012345678901234567890" +
742                 "1234567890123456789012345678901234567890");
743         try (final ClassicHttpResponse response1 = client.execute(host, get1, context)) {
744             Assertions.assertEquals(431, response1.getCode());
745             EntityUtils.consume(response1.getEntity());
746         }
747     }
748 
749     @Test
750     public void testHeaderTooLargePost() throws Exception {
751         final ClassicTestServer server = testResources.server();
752         final ClassicTestClient client = testResources.client();
753 
754         server.registerHandler("*", (request, response, context) ->
755                 response.setEntity(new StringEntity("All is well", StandardCharsets.US_ASCII)));
756 
757         server.start(
758                 Http1Config.custom()
759                         .setMaxLineLength(100)
760                         .build(),
761                 null,
762                 null);
763         client.start(
764                 new DefaultHttpProcessor(RequestContent.INSTANCE, RequestTargetHost.INSTANCE, RequestConnControl.INSTANCE));
765 
766         final HttpCoreContext context = HttpCoreContext.create();
767         final HttpHost host = new HttpHost(scheme.id, "localhost", server.getPort());
768 
769         final ClassicHttpRequest post1 = new BasicClassicHttpRequest(Method.POST, "/");
770         post1.setHeader("big-f-header", "1234567890123456789012345678901234567890123456789012345678901234567890" +
771                 "1234567890123456789012345678901234567890");
772         final byte[] b = new byte[2048];
773         for (int i = 0; i < b.length; i++) {
774             b[i] = (byte) ('a' + i % 10);
775         }
776         post1.setEntity(new ByteArrayEntity(b, ContentType.TEXT_PLAIN));
777 
778         try (final ClassicHttpResponse response1 = client.execute(host, post1, context)) {
779             Assertions.assertEquals(431, response1.getCode());
780             EntityUtils.consume(response1.getEntity());
781         }
782     }
783 
784 }