spdy-http2 / node-spdy

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

Assertion error when using server push #285

Open ebrpol opened 8 years ago

ebrpol commented 8 years ago

Following the server-push example, I am using a slightly adapted version:

const bundleJsUrl = '/static/js/bundle.js'
const stream = res.push(bundleJsUrl, {
    //status: 200, // optional
    //method: 'GET', // optional
    request: {
        accept: '*/*'
    },
    response: {
        'content-type': 'application/javascript'
    }
});
stream.on('error', function(e) {
    log.error("Error while server pushing: " + bundleJsUrl)
});
const readStream = fs.createReadStream("." + bundleJsUrl);
readStream.pipe(stream);

When refreshing the browser a couple of times in a row, I get the following assertion error:

/home/erik/dev/webmodeler/node_modules/spdy-transport/lib/spdy-transport/priority.js:72
  assert(index !== -1);
  ^
AssertionError: false == true
    at PriorityNode.removeChild (/home/erik/dev/webmodeler/node_modules/spdy-transport/lib/spdy-transport/priority.js:72:3)
    at PriorityNode.remove (/home/erik/dev/webmodeler/node_modules/spdy-transport/lib/spdy-transport/priority.js:61:15)
    at PriorityTree.add (/home/erik/dev/webmodeler/node_modules/spdy-transport/lib/spdy-transport/priority.js:157:23)
    at PriorityTree.addDefault (/home/erik/dev/webmodeler/node_modules/spdy-transport/lib/spdy-transport/priority.js:174:15)
    at PriorityTree.add (/home/erik/dev/webmodeler/node_modules/spdy-transport/lib/spdy-transport/priority.js:130:17)
    at Stream._initPriority (/home/erik/dev/webmodeler/node_modules/spdy-transport/lib/spdy-transport/stream.js:101:25)
    at new Stream (/home/erik/dev/webmodeler/node_modules/spdy-transport/lib/spdy-transport/stream.js:75:8)
    at Connection._createStream (/home/erik/dev/webmodeler/node_modules/spdy-transport/lib/spdy-transport/connection.js:394:16)
    at Connection._handleHeaders (/home/erik/dev/webmodeler/node_modules/spdy-transport/lib/spdy-transport/connection.js:441:21)
    at Connection._handleFrame (/home/erik/dev/webmodeler/node_modules/spdy-transport/lib/spdy-transport/connection.js:324:10)

Note that the server-pushed file is relatively large (4MB). Might this be related to the closed issue #244 ? I'm using Express as well btw.

heavyskyl commented 7 years ago

Have same issue. Have latest libraries versions.

spdy:priority add node=195 parent=0 weight=256 exclusive=1 +36ms spdy:priority hit maximum remove id=1 +0ms spdy:priority add node=197 parent=195 weight=147 exclusive=1 +2ms spdy:priority hit maximum remove id=2 +0ms

{ AssertionError: false == true at PriorityNode.removeChild (/usr/src/app/node_modules/spdy-transport/lib/spdy-transport/priority.js:72:3) at PriorityNode.remove (/usr/src/app/node_modules/spdy-transport/lib/spdy-transport/priority.js:61:15) at PriorityTree.add (/usr/src/app/node_modules/spdy-transport/lib/spdy-transport/priority.js:157:23) at Stream._initPriority (/usr/src/app/node_modules/spdy-transport/lib/spdy-transport/stream.js:101:25) at new Stream (/usr/src/app/node_modules/spdy-transport/lib/spdy-transport/stream.js:75:8) at Connection._createStream (/usr/src/app/node_modules/spdy-transport/lib/spdy-transport/connection.js:391:16) at Connection._handleHeaders (/usr/src/app/node_modules/spdy-transport/lib/spdy-transport/connection.js:438:21) at Connection._handleFrame (/usr/src/app/node_modules/spdy-transport/lib/spdy-transport/connection.js:321:10) at Parser. (/usr/src/app/node_modules/spdy-transport/lib/spdy-transport/connection.js:158:10) at emitOne (events.js:96:13) at Parser.emit (events.js:191:7) at readableAddChunk (/usr/src/app/node_modules/readable-stream/lib/_stream_readable.js:217:18) at Parser.Readable.push (/usr/src/app/node_modules/readable-stream/lib/_stream_readable.js:176:10) at Parser.Transform.push (/usr/src/app/node_modules/readable-stream/lib/_stream_transform.js:123:32) at next (/usr/src/app/node_modules/spdy-transport/lib/spdy-transport/protocol/base/parser.js:52:12) at /usr/src/app/node_modules/spdy-transport/lib/spdy-transport/protocol/http2/parser.js:71:5 name: 'AssertionError', actual: false, expected: true, operator: '==', message: 'false == true', generatedMessage: true }

Happens when I press f5 several times quickly ( I use push ).

Crecket commented 7 years ago

I seem to have the same issue, the initial request + pushed files are fine but any requests after that seem to trigger the same assertion error. This only occurs if I hit refresh multiple times or when my service worker does a lot of requests simultaneously.

assert.js:81
throw new assert.AssertionError({
    ^
    AssertionError: false == true
at PriorityNode.removeChild (\project\node_modules\spdy-transport\lib\spdy-transport\priority.js:72:3)
at PriorityNode.remove (\project\node_modules\spdy-transport\lib\spdy-transport\priority.js:61:15)
at PriorityTree.add (\project\node_modules\spdy-transport\lib\spdy-transport\priority.js:157:23)
at Stream._initPriority (\project\node_modules\spdy-transport\lib\spdy-transport\stream.js:101:25)
at new Stream (\project\node_modules\spdy-transport\lib\spdy-transport\stream.js:75:8)
at Connection._createStream (\project\node_modules\spdy-transport\lib\spdy-transport\connection.js:391:16)
at Connection._handleHeaders (\project\node_modules\spdy-transport\lib\spdy-transport\connection.js:438:21)
at Connection._handleFrame (\project\node_modules\spdy-transport\lib\spdy-transport\connection.js:321:10)
at Parser.<anonymous> (\project\node_modules\spdy-transport\lib\spdy-transport\connection.js:158:10)
at emitOne (events.js:96:13)
at Parser.emit (events.js:191:7)

I'm using the on error callback but the AssertionError still triggers a fatal error on the server. I've disabled push for now

daviddias commented 7 years ago

Hi all, thanks for reporting this one. It would be super helpful if you could provide a test that fails for this case, do you think you can come up with one? Thanks!

WVmf commented 7 years ago

I'm also having the same issue as described here and in #285.

I.e. when using push I get an AssertionError after reloading the page a few times, or when the page has a sufficient amount of resources it also happens on the first page load. But the issue doesn't seem to be caused by the push itself. Because the error happens after the pushed resource and some normal resources have already been delivered to the client. For example when only the first page load includes a pushed resource, the error still happens when subsequently loading different pages without any pushed resources. So the push only seems to trigger some condition that later on (after some additional requests) results in the error.

Output of "DEBUG=spdy:priority" up until assertion error:

Click to expand

Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=0 parent=-1 weight=1 exclusive=0
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=0 parent=-1 weight=1 exclusive=0
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=1 parent=0 weight=256 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=3 parent=0 weight=256 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority creating default node
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=2 parent=0 weight=16 exclusive=0
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=5 parent=3 weight=256 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=7 parent=5 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=9 parent=7 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=11 parent=9 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=13 parent=11 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=15 parent=13 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=17 parent=15 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=19 parent=17 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=21 parent=19 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=23 parent=21 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=25 parent=5 weight=183 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=2 parent=23 weight=110 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=27 parent=0 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=29 parent=0 weight=220 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=31 parent=0 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=33 parent=31 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=35 parent=33 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=37 parent=35 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=39 parent=0 weight=256 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=41 parent=37 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=43 parent=0 weight=220 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=45 parent=0 weight=256 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=47 parent=0 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=49 parent=47 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=51 parent=49 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=53 parent=51 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=55 parent=53 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=57 parent=55 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=59 parent=57 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=61 parent=59 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=63 parent=61 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=65 parent=63 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=67 parent=65 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=69 parent=67 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=71 parent=69 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=73 parent=71 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=75 parent=73 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=77 parent=75 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=79 parent=77 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=81 parent=79 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=83 parent=81 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=85 parent=83 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=87 parent=85 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=89 parent=87 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=91 parent=0 weight=220 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=93 parent=89 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=95 parent=93 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=97 parent=95 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=99 parent=97 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=101 parent=99 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=103 parent=101 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=105 parent=103 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=107 parent=105 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=109 parent=107 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=111 parent=109 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=113 parent=111 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=115 parent=113 weight=147 exclusive=1
Mon, 29 May 2017 11:51:38 GMT spdy:priority add node=117 parent=115 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=119 parent=0 weight=220 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=121 parent=0 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=123 parent=121 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=125 parent=123 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=127 parent=125 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=129 parent=127 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=131 parent=129 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=133 parent=131 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=135 parent=133 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=137 parent=135 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=139 parent=137 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=141 parent=139 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=143 parent=141 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=145 parent=143 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=147 parent=145 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=149 parent=147 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=151 parent=149 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=153 parent=151 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=155 parent=153 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=157 parent=155 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=159 parent=157 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=161 parent=159 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=163 parent=161 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=165 parent=163 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=167 parent=165 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=169 parent=167 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=171 parent=169 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=173 parent=171 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=175 parent=173 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=177 parent=175 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=179 parent=177 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=181 parent=179 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=183 parent=181 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=185 parent=183 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=187 parent=185 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=189 parent=187 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=191 parent=189 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=193 parent=191 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=195 parent=193 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=197 parent=195 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority hit maximum remove id=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=199 parent=197 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority hit maximum remove id=3
Mon, 29 May 2017 11:51:39 GMT spdy:priority add node=201 parent=199 weight=147 exclusive=1
Mon, 29 May 2017 11:51:39 GMT spdy:priority hit maximum remove id=2

AssertionError output:

assert.js:85
  throw new assert.AssertionError({
  ^
AssertionError: false == true
    at PriorityNode.removeChild (d:\some\path\node_modules\spdy-transport\lib\spdy-transport\priority.js:72:3)
    at PriorityNode.remove (d:\some\path\node_modules\spdy-transport\lib\spdy-transport\priority.js:61:15)
    at PriorityTree.add (d:\some\path\node_modules\spdy-transport\lib\spdy-transport\priority.js:157:23)
    at Stream._initPriority (d:\some\path\node_modules\spdy-transport\lib\spdy-transport\stream.js:101:25)
    at new Stream (d:\some\path\node_modules\spdy-transport\lib\spdy-transport\stream.js:75:8)
    at Connection._createStream (d:\some\path\node_modules\spdy-transport\lib\spdy-transport\connection.js:391:16)
    at Connection._handleHeaders (d:\some\path\node_modules\spdy-transport\lib\spdy-transport\connection.js:438:21)
    at Connection._handleFrame (d:\some\path\node_modules\spdy-transport\lib\spdy-transport\connection.js:321:10)
    at Parser.<anonymous> (d:\some\path\node_modules\spdy-transport\lib\spdy-transport\connection.js:158:10)
    at emitOne (events.js:96:13)
    at Parser.emit (events.js:188:7)
    at readableAddChunk (d:\some\path\node_modules\readable-stream\lib\_stream_readable.js:212:18)
    at Parser.Readable.push (d:\some\path\node_modules\readable-stream\lib\_stream_readable.js:171:10)
    at Parser.Transform.push (d:\some\path\node_modules\readable-stream\lib\_stream_transform.js:123:32)
    at next (d:\some\path\node_modules\spdy-transport\lib\spdy-transport\protocol\base\parser.js:52:12)
    at d:\some\path\node_modules\spdy-transport\lib\spdy-transport\protocol\http2\parser.js:71:5

My push related code:

let pushedStream = res.push(pushResrcPath, {
    status: 200,
    method: "GET",
    request: {
        accept: "*/*"
    },
    response: {
        "content-type": mime.lookup(pushResrcPath)
    }
});
pushedStream.on("error", (err) => { console.error("Push stream failed", err); });
pushedStream.on("finish", () => { console.log("Push stream finished."); });
let fileStream = fs.createReadStream(path.resolve(__dirname, path.join("../path/to/public/", pushResrcPath.replace(/^\/someprefix/i, ""))));
fileStream.pipe(pushedStream);

npm ls output for spdy:

+-- spdy@3.4.4
| +-- handle-thing@1.2.5
| +-- http-deceiver@1.2.7
| +-- select-hose@2.0.0
| `-- spdy-transport@2.0.18
|   +-- hpack.js@2.1.6
|   +-- obuf@1.1.1
|   `-- wbuf@1.7.2
|     `-- minimalistic-assert@1.0.0

FWIW: I'm using Node.js v6.9.1 in combination with Express v4.15.2 on Windows 10.

abovedave commented 7 years ago

I can replicate this reliably by pushing many assets, which I think simulates the action of this constantly refreshing people are reporting.

Here's my example, perhaps someone could form this into a test case for @diasdavid if it doesn't help on it's own?

WVmf commented 7 years ago

The following single-file example also causes the AssertionError to be thrown on my development machine.

const spdy = require("spdy");
const options = {
    key: `-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA7aSwMfFw5naEJ6MlTS53cYrnkF6DyrQuHWMOTOgtEfY1XWjrHEUdfz4xvn4/LAOWpsFP/YkIaYHlLAez3ZybjEaSH/T/jqpDmO4VSbSfdxzJJHV8sTO7G6gtHkGFiDMOKCBDi1Htrx7e8kY39c8j5ZFfSZEXugZIuUTnd0lipp0dGbsSKoqHVm1NMssm0zvfWnkrv//N7lY0npeqmwcIy5aPN5mhGtt6YK9+LolcwWssyX2e4vBBKpZQVtISSpV8PscmL+iv9nr+LHWbo3VrZ63RHlTuRDhX1Ivv9Hqx+b8T/cZCD94MLT/PA3CS0PO+h7Kdds8LDm0SL3OFi8gAPwIDAQABAoIBAQDRTi4JrvebZGM9bgoakoSNMqSFmVlGna/IHkioIA4iNdIGtbPuMEmsmqDBgPwuzfJQaQ8E5T7NfqTUROx8kcTGphlpoCW+B+SFu5xwUG/rPyVBwWDTyhZQY61papgrv5wGZ3RWLxDDHtOKW6JKE+kv9vwQFYTqSUKgOzoK7E3BJAnTbbQRGMAYPRlsrrwKw3C2WfxCpYhwHSDD/xJbMCjzRL0RG37om8pvTUAn0XU8cmG1kuu5DlOZ2kYXbCU9RE5iuhDSwkj4aQ2gzVpIMV3AM5IxEDrzqe8Uvs5FzpI47gAdX8zusWD8mnbNLickkf8dRANAJXz3yqQy7cif+i0hAoGBAPazElhlCSLB9q8vwTk6h7/ObpoLxWtUgMGldpmf77QS6VnihURAaawyw50lPavWPBT2WXgKPCQvZjCw14fn31SG7PlAFkuiuiF3sYYfYh3pjvRnr58iEbGrP/UyCJbPvEfbYL+MG7tWKJBABzYe0zivJDsqwYNsvSo9qAFUwi05AoGBAPaaNtX3TG7frTAGCUJ3xW5eIGVQspQ/maSa8nhaEeSY01ATjbkuhWmdO9Pi1izg96CsQsG39HZ/WmGLsg0ZF3q83KJxunq0DlMWTl03CACgU6DvXkArhdJrjE9TCtlgdGIfJoNUG4PTW+J4tA5H6VEUudhdxaQ9qSWll46xC5E3AoGAfp2BuOSCP9iVJ2y3GwwzR/pHQcDw3hlMzBaEPGydtipOoddk1pbIpZyYUTsf3+XgiFG3sahvHZNGO49Hz3TuZo+paHO//anTJgIsls3cqcWJnV7qAB6YPjvKY6n+Rojv9WFe0nCyev/Jad+y09AWUG1zhvp2v2E75UYnyCccUeECgYEAsP2cD9OvYwBc79PVP4RxCja6b50MnsRLBM5E6sZSg0yAlb+C/375OAUm1HvBFnLcp9AbFahu58Gd39cAktAIfwogHOMdYUXr5gxjcBm4P6LSgvZqIgpawNx51tEWP1AwF+CdprJuER5Ym2HgcUOBnLUQcc9Ts/6hcSi5byt4zt8CgYB7UYogvtn2UwLcWr4QmThNuLkPrBevZ9buD0k2hTRY1OVej7uCDYC7rI4NVS/Nf7/0brwCUZVsWrwBuIDuxGAn2T9ezvWx2Q7/X50ZuvcXAQWIvELb5VTbrJWKKUaZXxo7IJJ5hZrTj0TPrvpIsECPkVWD6wQy3qroDg6gEgsRqA==
-----END RSA PRIVATE KEY-----
`,
    cert: `-----BEGIN CERTIFICATE-----
MIIDBjCCAe4CCQC1b57lEU3qJTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMB4XDTE3MDUyOTEzNTE1OFoXDTE5MDUyOTEzNTE1OFowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAO2ksDHxcOZ2hCejJU0ud3GK55Beg8q0Lh1jDkzoLRH2NV1o6xxFHX8+Mb5+PywDlqbBT/2JCGmB5SwHs92cm4xGkh/0/46qQ5juFUm0n3ccySR1fLEzuxuoLR5BhYgzDiggQ4tR7a8e3vJGN/XPI+WRX0mRF7oGSLlE53dJYqadHRm7EiqKh1ZtTTLLJtM731p5K7//ze5WNJ6XqpsHCMuWjzeZoRrbemCvfi6JXMFrLMl9nuLwQSqWUFbSEkqVfD7HJi/or/Z6/ix1m6N1a2et0R5U7kQ4V9SL7/R6sfm/E/3GQg/eDC0/zwNwktDzvoeynXbPCw5tEi9zhYvIAD8CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAb4AIPuALBtOEDMhIi2wRDt9b88XewLJDejkl8o1GRs0FlknvYh+wawe4FuZqBhso6Mi/INqWsmFQbQWXX5PGyFhtw1wsGLJ7el+2Tmv3frGTxAJnhmouu60b1Vh8r9jGvbYn4Kdo7+5YrfuUbebl/RuOjYTcom4QdMMehXiWADMrSAa/7SZmKhODskWyRgLFMUsDe8UHJt/8HVgVila9GIVXY/Toq+JMFTU7oEydW2DohrOvERUpx/VnVVwH89AdM1tUDM0sgsSWoM69R+g6cFtMg8/HqSWYrPw0+jACpSgZ8ekYMPk55gYWKccoK8K+DCaFJVQhu0S1FhzTNRw/og==
-----END CERTIFICATE-----`,
    spdy: { protocols: ["h2"], plain: false }
};

let htmlContent = `<html><head><title>Push error page</title><link rel="stylesheet" href="css/main.css"></head><body>`;
for ( let i = 0; i < 100; ++i ) {
    htmlContent += `<img src="img/img${i}.svg">`;
}
htmlContent += `</body></html>`;
const cssContent = `body { background-image: url("../img/hero.svg"); background-size: cover; background-color: gray; } img { float: left; padding: 1vh; width: 5vw; }`;
const heroSvg = `<svg width="25" height="25" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="grad" x1="0" x2="1" y1="0" y2="1"><stop offset="0" stop-color="black"/><stop offset="1" stop-color="darkgrey"/></linearGradient></defs><rect width="25" height="25" fill="url(#grad)"/></svg>`;

function requestHandler(req, res) {
    if ( req.url == "/" || req.url == "/index.html" ) {
        let pushStream = res.push("/img/hero.svg", {
            status: 200,
            method: "GET",
            request: { accept: "*/*" },
            response: { "content-type": "image/svg+xml" }
        });
        pushStream.on("error", (err) => { console.error("Push stream error:", err) });
        // IMPORTANT If we don't introduce a (not-too-low) delay here, then the push AssertionError doesn't seem to be thrown. (On my PC the delay needed to be > ~20ms.)
        setTimeout(() => {
            pushStream.end(heroSvg);
        }, 100);

        res.writeHead(200);
        res.end(htmlContent);
    } else if ( req.url == "/css/main.css" ) {
        res.writeHead(200, { "content-type": "text/css" });
        res.end(cssContent);
    } else if ( req.url.startsWith("/img/") ) {
        // Note: If we wouldn't push "hero.svg" it would also be served as a randomly solid color filled rectangle.
        res.writeHead(200, { "content-type": "image/svg+xml" });
        res.end(`<?xml version="1.0"?><svg width="25" height="25" xmlns="http://www.w3.org/2000/svg" version="1.1"><rect width="25" height="25" fill="rgb(${Math.floor(Math.random()*256)},${Math.floor(Math.random()*256)},${Math.floor(Math.random()*256)})"/></svg>`);
    } else {
        res.writeHead(404);
        res.end();
    }
}

spdy.createServer(options, requestHandler).listen(3000);
console.log("Server running @ https://127.0.0.1:3000/");

One important thing to note is that for the error to occur I had to introduce an artificial delay for the response of the push by using setTimeout(() => { pushStream.end(heroSvg); }, 100). Also the delay needed to be large enough. I.e. on my machine the threshold was approximately 20ms.

(Note: The included key and (self-signed) certificate were generated just for the example.)

stijndeschuymer commented 7 years ago

Any updates on this?

tomalex0 commented 6 years ago

Any update on this issue? What might be causing this issue?

vytautas-pranskunas- commented 6 years ago

Same here. After hitting browser refresh few times i got same error. Any updates on this? Or we would not be able to use push for ages because it seems like this issue is quite old. It Push is very important for PWA can it be preoritized?