spdy-http2 / node-spdy

SPDY server on Node.js
2.81k stars 196 forks source link

Connection not closing in simple test case #158

Closed guybedford closed 8 years ago

guybedford commented 10 years ago

I was just playing around with a simple test case today and came across this issue. My apologies in advance if I'm doing something stupid, but I thought it would be worth posting as I've tried a few things.

My server looks like:

var spdy = require('spdy');
var fs = require('fs');

spdy.createServer({
  key: fs.readFileSync(__dirname + '/keys/spdy-key.pem'),
  cert: fs.readFileSync(__dirname + '/keys/spdy-cert.pem'),
  ca: fs.readFileSync(__dirname + '/keys/spdy-csr.pem'),
}, function(req, res) {
  var headers = {
    'content-type': 'application/javascript',
    'cache-control': 'max-age=3600'
  };

  res.push('/test-file', headers, function(err, stream) {
    stream.on('error', function(e) {
      console.log(e);
      read.unpipe(stream);
    });
    var read = fs.createReadStream('large-file');
    read.pipe(stream);

    res.writeHead(200, { 'content-type': 'text/html' });
    res.end('hello world');
  });

}).listen(4443);

large-file here is a 50MB file on my local machine.

When first viewed, everything works as expected. But when viewing the page for the second time, the browser sends a RESET. Then the server sends the headers, but it never sends the final response.

It seems like the RESET on the push stream is closing the underlying main stream?

Moving the res.end outside of the push stream callback does not seem to help either.

Here is the SPDY session:

t=7987 [st=0]  SPDY_SESSION_PING
               --> is_ack = false
               --> type = "sent"
               --> unique_id = 1
t=7987 [st=0]  SPDY_SESSION_SYN_STREAM
               --> fin = true
               --> :host: localhost:4443
                   :method: GET
                   :path: /
                   :scheme: https
                   :version: HTTP/1.1
                   accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
                   accept-encoding: gzip,deflate,sdch
                   accept-language: en-US,en;q=0.8
                   cache-control: no-cache
                   cookie: [29 bytes were stripped]
                   pragma: no-cache
                   user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.86 Safari/537.36
               --> spdy_priority = 0
               --> stream_id = 5
               --> unidirectional = false
t=7991 [st=4]  SPDY_SESSION_PING
               --> is_ack = false
               --> type = "received"
               --> unique_id = 1
t=7992 [st=5]  SPDY_SESSION_PUSHED_SYN_STREAM
               --> associated_stream = 5
               --> fin = false
               --> :host: localhost:4443
                   :method: GET
                   :path: /test@^1.2.3
                   :scheme: https
                   :status: 200
                   :version: HTTP/1.1
                   cache-control: max-age=3600
                   content-type: application/javascript
               --> spdy_priority = 7
               --> stream_id = 6
               --> unidirectional = true
t=7992 [st=5]  SPDY_SESSION_SEND_RST_STREAM
               --> description = "Received duplicate pushed stream with url: https://localhost:4443/test-file"
               --> status = 1
               --> stream_id = 6
t=7992 [st=5]  SPDY_SESSION_SYN_REPLY
               --> fin = false
               --> :status: 200 OK
                   :version: HTTP/1.1
                   content-type: text/html
                   date: Fri, 09 May 2014 03:46:24 GMT
               --> stream_id = 5
indutny commented 10 years ago

Sorry, I don't seem to be able to reproduce it locally. I wonder if it is possible to write a test case that will require only node-spdy client and node-spdy server. Which node-spdy version are you using, btw?

guybedford commented 10 years ago

It seems to specifically happen only when the push stream is already cached in the browser.

The response doesn't appear and the loading icon on the page just keeps spinning and the connection isn't closed. Could it be a bug in Chrome?

I'm running SPDY 1.25.6 on NodeJS 0.10.28.

I updated to SPDY 1.26.0 and it still happens.

guybedford commented 10 years ago

I've published the test case here - https://github.com/guybedford/spdy-issue-158, if it helps.

indutny commented 10 years ago

Oh, I think I know what the problem is with... It is the spdy/3.1 protocol :) Basically, the browser doesn't seem to decrease window when receiving frames on canceled PUSH stream. I'll look into chromium implementation to see if there anything that could be done in node-spdy.

indutny commented 10 years ago

https://groups.google.com/forum/#!topic/spdy-dev/hz9jp2rZbdQ for details

indutny commented 10 years ago

Ah, seems to be a bug on my side after all.

guybedford commented 10 years ago

Glad to hear you've tracked it down! Thanks so much for looking into it.