arturobernalg commented on PR #733:
URL: 
https://github.com/apache/httpcomponents-core/pull/733#issuecomment-6559726012

   Reproducer, run against master 450ef92a4. It sends a POST carrying both 
Content-Length and Transfer-Encoding, followed by a pipelined GET, to the 
classic and to the async server.
   
   ```java
   import java.io.InputStream;
   import java.net.InetSocketAddress;
   import java.net.Socket;
   import java.net.SocketTimeoutException;
   import java.nio.charset.StandardCharsets;
   import java.util.concurrent.atomic.AtomicInteger;
   
   import org.apache.hc.core5.http.EntityDetails;
   import org.apache.hc.core5.http.HttpRequest;
   import org.apache.hc.core5.http.Message;
   import org.apache.hc.core5.http.URIScheme;
   import org.apache.hc.core5.http.impl.bootstrap.AsyncServerBootstrap;
   import org.apache.hc.core5.http.impl.bootstrap.HttpAsyncServer;
   import org.apache.hc.core5.http.impl.bootstrap.HttpServer;
   import org.apache.hc.core5.http.impl.bootstrap.ServerBootstrap;
   import org.apache.hc.core5.http.io.entity.StringEntity;
   import org.apache.hc.core5.http.nio.AsyncRequestConsumer;
   import org.apache.hc.core5.http.nio.AsyncServerRequestHandler;
   import org.apache.hc.core5.http.nio.entity.StringAsyncEntityConsumer;
   import org.apache.hc.core5.http.nio.support.BasicRequestConsumer;
   import org.apache.hc.core5.http.nio.support.BasicResponseProducer;
   import org.apache.hc.core5.http.nio.support.BasicServerExchangeHandler;
   import org.apache.hc.core5.http.protocol.HttpContext;
   import org.apache.hc.core5.io.CloseMode;
   
   public class PipelinedTeCl {
   
       static final String RAW = "POST /a HTTP/1.1\r\nHost: 
localhost\r\nContent-Length: 6\r\n"
               + "Transfer-Encoding: chunked\r\n\r\n5\r\nAAAAA\r\n0\r\n\r\n"
               + "GET /b HTTP/1.1\r\nHost: localhost\r\n\r\n";
   
       static int responses(final int port) throws Exception {
           try (Socket s = new Socket("localhost", port)) {
               s.setSoTimeout(2000);
               
s.getOutputStream().write(RAW.getBytes(StandardCharsets.ISO_8859_1));
               final StringBuilder sb = new StringBuilder();
               final InputStream in = s.getInputStream();
               final byte[] b = new byte[1024];
               try {
                   int n;
                   while ((n = in.read(b)) != -1) {
                       sb.append(new String(b, 0, n, 
StandardCharsets.ISO_8859_1));
                   }
               } catch (final SocketTimeoutException ignore) {
               }
               return sb.toString().split("HTTP/1.1 200 OK", -1).length - 1;
           }
       }
   
       public static void main(final String[] args) throws Exception {
           final AtomicInteger calls = new AtomicInteger();
   
           final HttpServer classic = ServerBootstrap.bootstrap()
                   .setCanonicalHostName("localhost")
                   .register("*", (request, response, context) -> {
                       calls.incrementAndGet();
                       response.setEntity(new StringEntity("ok"));
                   })
                   .create();
           classic.start();
           System.out.println("classic server: responses=" + 
responses(classic.getLocalPort())
                   + " handler calls=" + calls.get());
           classic.close(CloseMode.IMMEDIATE);
   
           calls.set(0);
           final HttpAsyncServer async = AsyncServerBootstrap.bootstrap()
                   .setCanonicalHostName("localhost")
                   .register("*", () -> new BasicServerExchangeHandler<>(
                           new AsyncServerRequestHandler<Message<HttpRequest, 
String>>() {
   
                               @Override
                               public AsyncRequestConsumer<Message<HttpRequest, 
String>> prepare(
                                       final HttpRequest request, final 
EntityDetails entityDetails,
                                       final HttpContext context) {
                                   return new BasicRequestConsumer<>(new 
StringAsyncEntityConsumer());
                               }
   
                               @Override
                               public void handle(
                                       final Message<HttpRequest, String> 
message, final ResponseTrigger trigger,
                                       final HttpContext context) throws 
java.io.IOException,
                                       org.apache.hc.core5.http.HttpException {
                                   calls.incrementAndGet();
                                   trigger.submitResponse(new 
BasicResponseProducer(200, "ok"), context);
                               }
                           }))
                   .create();
           async.start();
           final int port = ((InetSocketAddress) async.listen(new 
InetSocketAddress(0), URIScheme.HTTP)
                   .get().getAddress()).getPort();
           System.out.println("async server:   responses=" + responses(port) + 
" handler calls=" + calls.get());
           async.close(CloseMode.IMMEDIATE);
       }
   }
   ```
   
   Output:
   
   ```
   classic server: responses=1 handler calls=1
   async server:   responses=2 handler calls=2
   ```
   
   Both servers frame the request by Transfer-Encoding, so answering the 
pipelined GET is correct under that framing. The difference is that the classic 
server closes the connection after the first response, as the reuse strategy 
says, while the async server has already read the next request by then and 
answers it too. It only matters behind a front end that frames by 
Content-Length. I do not claim more than that.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to