Comparing version 3.1.2 to 3.2.0
Version history | ||
=============== | ||
### 3.2.0 (2015-02-19) ### | ||
* Update ALPN token to final RFC version (h2). | ||
* Update altsvc implementation to draft 06: [draft-ietf-httpbis-alt-svc-06] | ||
[draft-ietf-httpbis-altsvc-06]: http://tools.ietf.org/html/draft-ietf-httpbis-alt-svc-06 | ||
### 3.1.2 (2015-02-17) ### | ||
@@ -5,0 +12,0 @@ |
@@ -788,3 +788,3 @@ // The framer consists of two [Transform Stream][1] subclasses that operate in [object mode][2]: | ||
// [ALTSVC](http://tools.ietf.org/html/draft-ietf-httpbis-alt-svc-04#section-4) | ||
// [ALTSVC](http://tools.ietf.org/html/draft-ietf-httpbis-alt-svc-06#section-4) | ||
// ------------------------------------------------------------ | ||
@@ -803,11 +803,5 @@ // | ||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
// | Max-Age (32) | | ||
// | Origin-Len (16) | Origin? (*) ... | ||
// +-------------------------------+----------------+--------------+ | ||
// | Port (16) | Reserved (8) | PID_LEN (8) | | ||
// +-------------------------------+----------------+--------------+ | ||
// | Protocol-ID (*) | | ||
// +---------------+-----------------------------------------------+ | ||
// | HOST_LEN (8) | Host (*) ... | ||
// +---------------+-----------------------------------------------+ | ||
// | Origin? (*) ... | ||
// | Alt-Svc-Field-Value (*) ... | ||
// +---------------------------------------------------------------+ | ||
@@ -817,31 +811,14 @@ // | ||
// | ||
// Max-Age: An unsigned, 32-bit integer indicating the freshness | ||
// lifetime of the alternative service association, as per [ALT-SVC](http://tools.ietf.org/html/draft-ietf-httpbis-alt-svc-01) | ||
// section 2.2. | ||
// Origin-Len: An unsigned, 16-bit integer indicating the length, in | ||
// octets, of the Origin field. | ||
// | ||
// Port: An unsigned, 16-bit integer indicating the port that the | ||
// alternative service is available upon. | ||
// Origin: An OPTIONAL sequence of characters containing ASCII | ||
// serialisation of an origin ([RFC6454](http://tools.ietf.org/html/rfc6454), | ||
// Section 6.2) that the alternate service is applicable to. | ||
// | ||
// Reserved: For future use. Senders MUST set these bits to '0', and | ||
// recipients MUST ignore them. | ||
// | ||
// PID_LEN: An unsigned, 8-bit integer indicating the length, in | ||
// octets, of the Protocol-ID field. | ||
// | ||
// Protocol-ID: A sequence of bytes (length determined by PID_LEN) | ||
// containing the ALPN protocol identifier of the alternative | ||
// service. | ||
// | ||
// HOST_LEN: An unsigned, 8-bit integer indicating the length, in | ||
// octets, of the Host field. | ||
// | ||
// Host: A sequence of characters (length determined by HOST_LEN) | ||
// containing an ASCII string indicating the host that the | ||
// alternative service is available upon. An internationalized | ||
// domain [IDNA] MUST be expressed using A-labels. | ||
// | ||
// Origin: An optional sequence of characters (length determined by | ||
// subtracting the length of all lpreceding fields from the frame | ||
// length) containing ASCII serialisation of an origin ([RFC6454](http://tools.ietf.org/html/rfc6454), | ||
// Section 6.2) that the alternate service is applicable to. | ||
// Alt-Svc-Field-Value: A sequence of octets (length determined by | ||
// subtracting the length of all preceding fields from the frame | ||
// length) containing a value identical to the Alt-Svc field value | ||
// defined in (Section 3)[http://tools.ietf.org/html/draft-ietf-httpbis-alt-svc-06#section-3] | ||
// (ABNF production "Alt-Svc"). | ||
@@ -851,29 +828,192 @@ typeSpecificAttributes.ALTSVC = ['maxAge', 'port', 'protocolID', 'host', | ||
Serializer.ALTSVC = function writeAltSvc(frame, buffers) { | ||
var buffer = new Buffer(8); | ||
buffer.writeUInt32BE(frame.maxAge, 0); | ||
buffer.writeUInt16BE(frame.port, 4); | ||
buffer.writeUInt8(0, 6); | ||
buffer.writeUInt8(frame.protocolID.length, 7); | ||
buffers.push(buffer); | ||
function istchar(c) { | ||
return ('!#$&\'*+-.^_`|~1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.indexOf(c) > -1); | ||
} | ||
buffers.push(new Buffer(frame.protocolID, 'ascii')); | ||
function hexencode(s) { | ||
var t = ''; | ||
for (var i = 0; i < s.length; i++) { | ||
if (!istchar(s[i])) { | ||
t += '%'; | ||
t += new Buffer(s[i]).toString('hex'); | ||
} else { | ||
t += s[i]; | ||
} | ||
} | ||
return t; | ||
} | ||
buffer = new Buffer(1); | ||
buffer.writeUInt8(frame.host.length, 0); | ||
Serializer.ALTSVC = function writeAltSvc(frame, buffers) { | ||
var buffer = new Buffer(2); | ||
buffer.writeUInt16BE(frame.origin.length, 0); | ||
buffers.push(buffer); | ||
buffers.push(new Buffer(frame.origin, 'ascii')); | ||
buffers.push(new Buffer(frame.host, 'ascii')); | ||
var fieldValue = hexencode(frame.protocolID) + '="' + frame.host + ':' + frame.port + '"'; | ||
if (frame.maxAge !== 86400) { // 86400 is the default | ||
fieldValue += "; ma=" + frame.maxAge; | ||
} | ||
buffers.push(new Buffer(frame.origin, 'ascii')); | ||
buffers.push(new Buffer(fieldValue, 'ascii')); | ||
}; | ||
function stripquotes(s) { | ||
var start = 0; | ||
var end = s.length; | ||
while ((start < end) && (s[start] === '"')) { | ||
start++; | ||
} | ||
while ((end > start) && (s[end - 1] === '"')) { | ||
end--; | ||
} | ||
if (start >= end) { | ||
return ""; | ||
} | ||
return s.substring(start, end); | ||
} | ||
function splitNameValue(nvpair) { | ||
var eq = -1; | ||
var inQuotes = false; | ||
for (var i = 0; i < nvpair.length; i++) { | ||
if (nvpair[i] === '"') { | ||
inQuotes = !inQuotes; | ||
continue; | ||
} | ||
if (inQuotes) { | ||
continue; | ||
} | ||
if (nvpair[i] === '=') { | ||
eq = i; | ||
break; | ||
} | ||
} | ||
if (eq === -1) { | ||
return {'name': nvpair, 'value': null}; | ||
} | ||
var name = stripquotes(nvpair.substring(0, eq).trim()); | ||
var value = stripquotes(nvpair.substring(eq + 1).trim()); | ||
return {'name': name, 'value': value}; | ||
} | ||
function splitHeaderParameters(hv) { | ||
return parseHeaderValue(hv, ';', splitNameValue); | ||
} | ||
function parseHeaderValue(hv, separator, callback) { | ||
var start = 0; | ||
var inQuotes = false; | ||
var values = []; | ||
for (var i = 0; i < hv.length; i++) { | ||
if (hv[i] === '"') { | ||
inQuotes = !inQuotes; | ||
continue; | ||
} | ||
if (inQuotes) { | ||
// Just skip this | ||
continue; | ||
} | ||
if (hv[i] === separator) { | ||
var newValue = hv.substring(start, i).trim(); | ||
if (newValue.length > 0) { | ||
newValue = callback(newValue); | ||
values.push(newValue); | ||
} | ||
start = i + 1; | ||
} | ||
} | ||
var newValue = hv.substring(start).trim(); | ||
if (newValue.length > 0) { | ||
newValue = callback(newValue); | ||
values.push(newValue); | ||
} | ||
return values; | ||
} | ||
function rsplit(s, delim, count) { | ||
var nsplits = 0; | ||
var end = s.length; | ||
var rval = []; | ||
for (var i = s.length - 1; i >= 0; i--) { | ||
if (s[i] === delim) { | ||
var t = s.substring(i + 1, end); | ||
end = i; | ||
rval.unshift(t); | ||
nsplits++; | ||
if (nsplits === count) { | ||
break; | ||
} | ||
} | ||
} | ||
if (end !== 0) { | ||
rval.unshift(s.substring(0, end)); | ||
} | ||
return rval; | ||
} | ||
function ishex(c) { | ||
return ('0123456789ABCDEFabcdef'.indexOf(c) > -1); | ||
} | ||
function unescape(s) { | ||
var i = 0; | ||
var t = ''; | ||
while (i < s.length) { | ||
if (s[i] != '%' || !ishex(s[i + 1]) || !ishex(s[i + 2])) { | ||
t += s[i]; | ||
} else { | ||
++i; | ||
var hexvalue = ''; | ||
if (i < s.length) { | ||
hexvalue += s[i]; | ||
++i; | ||
} | ||
if (i < s.length) { | ||
hexvalue += s[i]; | ||
} | ||
if (hexvalue.length > 0) { | ||
t += new Buffer(hexvalue, 'hex').toString(); | ||
} else { | ||
t += '%'; | ||
} | ||
} | ||
++i; | ||
} | ||
return t; | ||
} | ||
Deserializer.ALTSVC = function readAltSvc(buffer, frame) { | ||
frame.maxAge = buffer.readUInt32BE(0); | ||
frame.port = buffer.readUInt16BE(4); | ||
var pidLength = buffer.readUInt8(7); | ||
frame.protocolID = buffer.toString('ascii', 8, 8 + pidLength); | ||
var hostLength = buffer.readUInt8(8 + pidLength); | ||
frame.host = buffer.toString('ascii', 9 + pidLength, 9 + pidLength + hostLength); | ||
frame.origin = buffer.toString('ascii', 9 + pidLength + hostLength); | ||
var originLength = buffer.readUInt16BE(0); | ||
frame.origin = buffer.toString('ascii', 2, 2 + originLength); | ||
var fieldValue = buffer.toString('ascii', 2 + originLength); | ||
var values = parseHeaderValue(fieldValue, ',', splitHeaderParameters); | ||
if (values.length > 1) { | ||
// TODO - warn that we only use one here | ||
} | ||
if (values.length === 0) { | ||
// Well that's a malformed frame. Just ignore it. | ||
return; | ||
} | ||
var chosenAltSvc = values[0]; | ||
frame.maxAge = 86400; // Default | ||
for (var i = 0; i < chosenAltSvc.length; i++) { | ||
if (i === 0) { | ||
// This corresponds to the protocolID="<host>:<port>" item | ||
frame.protocolID = unescape(chosenAltSvc[i].name); | ||
var hostport = rsplit(chosenAltSvc[i].value, ':', 1); | ||
frame.host = hostport[0]; | ||
frame.port = parseInt(hostport[1], 10); | ||
} else if (chosenAltSvc[i].name == 'ma') { | ||
frame.maxAge = parseInt(chosenAltSvc[i].value, 10); | ||
} | ||
// Otherwise, we just ignore this | ||
} | ||
}; | ||
@@ -880,0 +1020,0 @@ |
@@ -40,3 +40,3 @@ // [node-http2-protocol][homepage] is an implementation of the [HTTP/2 (draft 16)][http2] | ||
exports.VERSION = 'h2-16'; | ||
exports.VERSION = 'h2'; | ||
@@ -43,0 +43,0 @@ exports.Endpoint = require('./endpoint').Endpoint; |
{ | ||
"name": "http2", | ||
"version": "3.1.2", | ||
"version": "3.2.0", | ||
"description": "An HTTP/2 client and server implementation", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
@@ -18,3 +18,4 @@ var expect = require('chai').expect; | ||
WINDOW_UPDATE: ['window_size'], | ||
CONTINUATION: ['data'] | ||
CONTINUATION: ['data'], | ||
ALTSVC: ['protocolID', 'host', 'port', 'origin', 'maxAge'] | ||
}; | ||
@@ -192,3 +193,3 @@ | ||
}, | ||
buffer: new Buffer('00001D' + '0A' + '00' + '00000000' + '01E13380' + '115B' + '00' + '02' + '6832' + '12' + '616C747376632E6578616D706C652E636F6D', 'hex') | ||
buffer: new Buffer(new Buffer('00002B' + '0A' + '00' + '00000000' + '0000', 'hex') + new Buffer('h2="altsvc.example.com:4443"; ma=31536000', 'ascii')) | ||
}, { | ||
@@ -206,3 +207,3 @@ frame: { | ||
}, | ||
buffer: new Buffer('000037' + '0A' + '00' + '00000000' + '01E13380' + '115B' + '00' + '02' + '6832' + '12' + '616C747376632E6578616D706C652E636F6D' + '68747470733A2F2F6F6E6C796D652E6578616D706C652E636F6D', 'hex') | ||
buffer: new Buffer(new Buffer('000045' + '0A' + '00' + '00000000' + '001A', 'hex') + new Buffer('https://onlyme.example.comh2="altsvc.example.com:4443"; ma=31536000', 'ascii')) | ||
@@ -209,0 +210,0 @@ }, { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
308246
7271