2017-03-21 2 views
1

Ich habe ein Problem mit Daten-Streaming Während des Spülens regelmäßigen Stück Datenserver sendet es mit seiner Länge, die tatsächlich den Datenstrom beschädigt.HttpServletResponse Writer sendet Nachricht Länge auf Flush

(Embedded Anlegesteg & eingebettet tomcat erzeugt die gleichen Ergebnisse.)

github

ich netty als Client bin mit und es meldet sich die Nummer als erste Bytes der eingehenden Chunk (regular mit \ getrennt Linien n \ r). Auch Anlegesteg des Loggers

DEBUG org.eclipse.jetty.io.WriteFlusher - write: [email protected] ... [[email protected] ... {<<<\r\n26\r\n>>>...},[email protected]{<<<event: put\ndata:{...rty':'value'}\n\n>>>...}] 

Wo
"\ r \ n26 \ r \ n" - eine HEX Darstellung der Länge Nachricht ist
„event: put \ ndata: {... rty ':' Wert '} \ n \ n "- Nachricht tatsächlich gesendet

Wie kann ich die Längenübertragung abschalten?

Der Code:

public class TestCorruptedWrites { 

    private static Server server = null; 
    private final static int port = 8089; 
    private final static String endpoint = "/test"; 
    static String message = "event: put\ndata:{'property':'value'}\n\n"; 

    private static void sleep(int millis){ 
     try { 
      Thread.sleep(millis); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

    @BeforeClass 
    public static void initMockServer() throws Exception { 
     System.out.println(message.length()); 
     final ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS); 
     contextHandler.addServlet(new ServletHolder(new HttpServlet() { 
      @Override 
      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
       resp.setCharacterEncoding(StandardCharsets.UTF_8.name()); 
       resp.flushBuffer(); 

       Writer writer = resp.getWriter(); 
       while (true) { 
        writer.write(message); 
        writer.flush(); 
        sleep(300); 
       } 
      } 
     }), endpoint); 
     contextHandler.setContextPath("/"); 

     server = new Server(new QueuedThreadPool(50, 10)); 
     ServerConnector connector = new ServerConnector(server, new HttpConnectionFactory()); 
     connector.setPort(port); 
     server.addConnector(connector); 
     server.setHandler(contextHandler); 
     server.start(); 
    } 

    @Test 
    public void testClient() throws InterruptedException, IOException { 
     InternalLoggerFactory.setDefaultFactory(new Slf4JLoggerFactory()); 

     final Bootstrap bootstrap = new Bootstrap(); 
     final URI uri = URI.create("http://localhost:" + port + endpoint); 

     bootstrap 
       .group(new NioEventLoopGroup()) 
       .channel(NioSocketChannel.class) 
       .remoteAddress(new InetSocketAddress(uri.getHost(), uri.getPort())) 
       .handler(new ChannelInitializer<SocketChannel>() { 
        @Override 
        public void initChannel(SocketChannel channel) throws Exception { 
         ChannelPipeline pipeline = channel.pipeline(); 
         pipeline.addLast("logger", new LoggingHandler(LogLevel.DEBUG)); 
         pipeline.addLast("line", new DelimiterBasedFrameDecoder(Integer.MAX_VALUE, Delimiters.lineDelimiter())); 
         pipeline.addLast("string", new StringDecoder()); 
         pipeline.addLast("encoder", new HttpRequestEncoder()); 
         pipeline.addLast("log", new SimpleChannelInboundHandler<String>(){ 
          @Override 
          protected void messageReceived(ChannelHandlerContext ctx, String msg) throws Exception { 
           System.out.println(" ---> " + msg); 
          } 
          @Override 
          public void channelActive(ChannelHandlerContext context) { 
           System.out.println("active!"); 
           HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, uri.toString()); 
           request.headers().add(HttpHeaders.Names.ACCEPT, "text/event-stream"); 
           request.headers().add(HttpHeaders.Names.HOST, uri.getHost()); 
           request.headers().add(HttpHeaders.Names.ORIGIN, "http://" + uri.getHost()); 
           context.channel().writeAndFlush(request); 
          } 
         }); 
        } 
       }) 
       .connect(); 
     Thread.sleep(500_000); 
    } 
} 

Abhängigkeiten:

<?xml version="1.0" encoding="UTF-8"?> 
<project xmlns="http://maven.apache.org/POM/4.0.0" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 

    <groupId>com.test</groupId> 
    <artifactId>test</artifactId> 
    <version>1.0-SNAPSHOT</version> 

    <dependencies> 

    <dependency> 
     <groupId>org.slf4j</groupId> 
     <artifactId>slf4j-api</artifactId> 
     <version>1.7.2</version> 
    </dependency> 
    <dependency> 
     <groupId>ch.qos.logback</groupId> 
     <artifactId>logback-classic</artifactId> 
     <version>1.0.9</version> 
    </dependency> 

    <dependency> 
     <groupId>io.netty</groupId> 
     <artifactId>netty-all</artifactId> 
     <version>5.0.0.Alpha1</version> 
    </dependency> 
    <dependency> 
     <groupId>junit</groupId> 
     <artifactId>junit</artifactId> 
     <version>4.12</version> 
    </dependency> 
    <dependency> 
     <groupId>org.eclipse.jetty</groupId> 
     <artifactId>jetty-servlet</artifactId> 
     <version>9.4.2.v20170220</version> 
    </dependency> 
    </dependencies> 

    <build> 
    <plugins> 
     <plugin> 
     <artifactId>maven-compiler-plugin</artifactId> 
     <configuration> 
      <source>1.8</source> 
      <target>1.8</target> 
     </configuration> 
     </plugin> 
    </plugins> 
    </build> 

</project> 

Antwort

1

Das Standard-HTTP ist/1.1 Chunking Transfer-Codierung Sie sehen.

Chunking tritt auf, wenn Sie eine Antwort ohne Content-Length Header haben, und die Verbindung dauerhaft (nach der HTTP/1.1-Spezifikation) bleiben soll.

Wenn Sie einen HTTP/1.1-Client und den Content-Length Header auf der Serverseite nicht einstellen können, sollten Sie die Einstellung der Connection: close Anfrage und/oder Antwort-Header, wie die ständige Verbindung Modus beenden, die die segmentierte Übertragungscodierung auslöst.

Hinweis: (! Auch Proxies) es wäre klug, Chunked Transfer-Codierung zu unterstützen, wie Sie, dass aus einer beliebigen Anzahl von Orten sehen

Verwandte Themen