I then run the test code with 2 different versions of node, namely v4.5.0 and v6.7.0. Here is the output from the test runs:
anand@Anands-MacBook-Pro:~/github/tmp/spdy-agent-test $ npm install spdy
/Users/anand/github/tmp/spdy-agent-test
└── spdy@3.4.2
npm WARN enoent ENOENT: no such file or directory, open '/Users/anand/github/tmp/spdy-agent-test/package.json'
npm WARN spdy-agent-test No description
npm WARN spdy-agent-test No repository field.
npm WARN spdy-agent-test No README data
npm WARN spdy-agent-test No license field.
anand@Anands-MacBook-Pro:~/github/tmp/spdy-agent-test $ nvm use v4.5.0
Now using node v4.5.0 (npm v3.3.10)
anand@Anands-MacBook-Pro:~/github/tmp/spdy-agent-test $ DEBUG="spdy:*" NODE_DEBUG=https,http,net node test.js
HTTPS 75423: createConnection { NPNProtocols: [ 'h2', 'spdy/3.1', 'spdy/3', 'spdy/2', 'http/1.1', 'http/1.0' ],
ALPNProtocols: [ 'h2', 'spdy/3.1', 'spdy/3', 'spdy/2', 'http/1.1', 'http/1.0' ],
servername: 'api.development.push.apple.com',
port: 443,
host: 'api.development.push.apple.com' }
NET 75423: pipe false undefined
NET 75423: connect: find host api.development.push.apple.com
NET 75423: connect: dns options { family: undefined, hints: 3072 }
HTTP 75423: call onSocket 0 0
NET 75423: _read
NET 75423: Socket._read readStart
HTTP 75423: outgoing message end.
NET 75423: _read
NET 75423: _read wait for connection
NET 75423: onSocketFinish
NET 75423: oSF: not ended, call shutdown()
NET 75423: afterConnect
NET 75423: _read
NET 75423: Socket._read readStart
spdy:client activating fallback +0ms
NET 75423: destroy undefined
NET 75423: destroy
NET 75423: close
NET 75423: close handle
NET 75423: emit close
When testing with node v4.5.0, the test exits after activating fallback mode. My theory here is that the fallback is activated because node v4.5.0 does not support ALPN extensions, while the Apple Push Notification Service doesn’t support NPN extension. In the absence of a common extension to negotiate the application-level protocol, the node-spdy agent activates fallback mode. Given that ALPN support was added in node v5, all prior versions will encounter this problem and activate fallback mode, with the result that node-spdy cannot be used with ALPN-only servers while running < node v5. #280 allows the developer to specify an optional protocol in such cases and proceed. In the absence of a specified protocol, it activates the fallback when no protocol is specified.
Moving on to testing with node v6.7.0, I get the following:
When testing with node v6.7.0, because of the presence of ALPN extensions, the code is able to successfully connect to the APNS server and negotiate the use of the http/2 protocol. However, right after that, is a bug wherein the response fires data, aborted and end events in that sequence. The aborted event causes an otherwise successful response (granted that it returned a 403, but that is a valid HTTP response given that we've not specified any certificate or private key for the agent) to fail.
Consider the following test code:
I then run the test code with 2 different versions of node, namely v4.5.0 and v6.7.0. Here is the output from the test runs:
When testing with node v4.5.0, the test exits after activating fallback mode. My theory here is that the fallback is activated because node v4.5.0 does not support ALPN extensions, while the Apple Push Notification Service doesn’t support NPN extension. In the absence of a common extension to negotiate the application-level protocol, the node-spdy agent activates fallback mode. Given that ALPN support was added in node v5, all prior versions will encounter this problem and activate fallback mode, with the result that node-spdy cannot be used with ALPN-only servers while running < node v5. #280 allows the developer to specify an optional protocol in such cases and proceed. In the absence of a specified
protocol
, it activates the fallback when no protocol is specified.Moving on to testing with node v6.7.0, I get the following:
When testing with node v6.7.0, because of the presence of ALPN extensions, the code is able to successfully connect to the APNS server and negotiate the use of the http/2 protocol. However, right after that, is a bug wherein the response fires
data
,aborted
andend
events in that sequence. Theaborted
event causes an otherwise successful response (granted that it returned a403
, but that is a valid HTTP response given that we've not specified any certificate or private key for the agent) to fail.Searching the node-spdy and related code-bases, I came across https://github.com/indutny/node-spdy/blob/master/lib/spdy/handle.js#L55-L58. Nowhere in any of the code paths executed is
state.ending
set totrue
, resulting in the request being aborted.