tatsuhiro-t / spdylay

The experimental SPDY protocol version 2, 3 and 3.1 implementation in C
http://tatsuhiro-t.github.io/spdylay/
MIT License
603 stars 102 forks source link

shrpx sends "End of chunked encoding" twice #76

Closed kalmi closed 10 years ago

kalmi commented 11 years ago

Hi,

I have a setup like this: client --(HTTP)-- shrpx --(SPDY)-- shrpx --(HTTP)-- server

The server responds using chunked encoding. I can observe the communcation (using Wireshark) between the server and shrpx, and i see no odd things.

However when I observe the communiction between the client and shrpx, i can see that the "End of chunked encoding" sequence (0\r\n\r\n) is sent twice.

I believe the it is not legal.

Most clients don't care, but nodejs does, and it triggers an error event.

How to reproduce

-1. Start a wireshark capture on the loopback device -2. Start these:

shrpx -b 127.0.0.1,8000 -f 127.0.0.1,3333 --frontend-spdy-no-tls -L INFO --no-via
shrpx --client-proxy -b 127.0.0.1,3333 -f 127.0.0.1,3332 --backend-spdy-no-tls -L INFO --no-via
node server.js

-3. run client.js

node client.js

-4. Observe that client.js errors out after the response is completed -5. Look at wireshark capture and observe that client.js received "0\r\n\r\n0\r\n\r\n". end_of_chunked_twice

client.js

var http = require("http");

var options = {
  host: "127.0.0.1",
  port: 3332,
  path: "http://www.test.com",
  headers: {
    Host: "www.test.com"
  }
};
http.get(options, function(res) {
  console.log(res);
  res.pipe(process.stdout);
});

server.js

(Taken from here: https://gist.github.com/kadishmal/3871017 )

var http = require('http');

http.createServer(function (request, response) {
    response.setHeader('Content-Type', 'text/html; charset=UTF-8');
    response.setHeader('Transfer-Encoding', 'chunked');

    var html =
        '<!DOCTYPE html>' +
        '<html lang="en">' +
            '<head>' +
                '<meta charset="utf-8">' +
                '<title>Chunked transfer encoding test</title>' +
            '</head>' +
            '<body>';

    response.write(html);

    html = '<h1>Chunked transfer encoding test</h1>'

    response.write(html);

    // Now imitate a long request which lasts 5 seconds.
    setTimeout(function(){
        html = '<h5>This is a chunked response after 5 seconds. The server should not close the stream before all chunks are sent to a client.</h5>'

        response.write(html);

        // since this is the last chunk, close the stream.
        html =
            '</body>' +
                '</html';

        response.end(html);

    }, 5000);

    // this is another chunk of data sent to a client after 2 seconds before the
    // 5-second chunk is sent.
    setTimeout(function(){
        html = '<h5>This is a chunked response after 2 seconds. Should be displayed before 5-second chunk arrives.</h5>'

        response.write(html);

    }, 2000);

}).listen(8000, null);
tatsuhiro-t commented 11 years ago

Thank you for reporting bug. Fix committed in 3403ebc

kalmi commented 10 years ago

Thanks, this solved it.