1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/testing/xpcshell/node-spdy/lib/spdy/response.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,152 @@ 1.4 +var spdy = require('../spdy'), 1.5 + http = require('http'), 1.6 + res = http.ServerResponse.prototype; 1.7 + 1.8 +// 1.9 +// ### function _renderHeaders () 1.10 +// Copy pasted from lib/http.js 1.11 +// (added lowercase) 1.12 +// 1.13 +exports._renderHeaders = function() { 1.14 + if (this._header) { 1.15 + throw new Error("Can't render headers after they are sent to the client."); 1.16 + } 1.17 + 1.18 + var keys = Object.keys(this._headerNames); 1.19 + for (var i = 0, l = keys.length; i < l; i++) { 1.20 + var key = keys[i]; 1.21 + this._headerNames[key] = this._headerNames[key].toLowerCase(); 1.22 + } 1.23 + 1.24 + return res._renderHeaders.call(this); 1.25 +}; 1.26 + 1.27 +// 1.28 +// ### function writeHead (statusCode) 1.29 +// #### @statusCode {Number} HTTP Status code 1.30 +// .writeHead() wrapper 1.31 +// (Sorry, copy pasted from lib/http.js) 1.32 +// 1.33 +exports.writeHead = function(statusCode) { 1.34 + if (this._headerSent) return; 1.35 + this._headerSent = true; 1.36 + 1.37 + var reasonPhrase, headers, headerIndex; 1.38 + 1.39 + if (typeof arguments[1] == 'string') { 1.40 + reasonPhrase = arguments[1]; 1.41 + headerIndex = 2; 1.42 + } else { 1.43 + reasonPhrase = http.STATUS_CODES[statusCode] || 'unknown'; 1.44 + headerIndex = 1; 1.45 + } 1.46 + this.statusCode = statusCode; 1.47 + 1.48 + var obj = arguments[headerIndex]; 1.49 + 1.50 + if (obj && this._headers) { 1.51 + // Slow-case: when progressive API and header fields are passed. 1.52 + headers = this._renderHeaders(); 1.53 + 1.54 + // handle object case 1.55 + var keys = Object.keys(obj); 1.56 + for (var i = 0; i < keys.length; i++) { 1.57 + var k = keys[i]; 1.58 + if (k) headers[k] = obj[k]; 1.59 + } 1.60 + } else if (this._headers) { 1.61 + // only progressive api is used 1.62 + headers = this._renderHeaders(); 1.63 + } else { 1.64 + // only writeHead() called 1.65 + headers = obj; 1.66 + } 1.67 + 1.68 + // cleanup 1.69 + this._header = ''; 1.70 + 1.71 + // Do not send data to new connections after GOAWAY 1.72 + if (this.socket._isGoaway()) return; 1.73 + 1.74 + this.socket._lock(function() { 1.75 + var socket = this; 1.76 + 1.77 + this._framer.replyFrame( 1.78 + this.id, 1.79 + statusCode, 1.80 + reasonPhrase, 1.81 + headers, 1.82 + function (err, frame) { 1.83 + // TODO: Handle err 1.84 + socket.connection.write(frame); 1.85 + socket._unlock(); 1.86 + } 1.87 + ); 1.88 + }); 1.89 +}; 1.90 + 1.91 +// 1.92 +// ### function push (url, headers, callback) 1.93 +// #### @url {String} absolute or relative url (from root anyway) 1.94 +// #### @headers {Object} response headers 1.95 +// #### @callbacks {Function} continuation that will receive stream object 1.96 +// Initiates push stream 1.97 +// 1.98 +exports.push = function push(url, headers, priority, callback) { 1.99 + if (this.socket._destroyed) { 1.100 + return callback(Error('Can\'t open push stream, parent socket destroyed')); 1.101 + } 1.102 + 1.103 + if (!callback && typeof priority === 'function') { 1.104 + callback = priority; 1.105 + priority = 0; 1.106 + } 1.107 + 1.108 + if (!callback) callback = function() {}; 1.109 + 1.110 + this.socket._lock(function() { 1.111 + var socket = this, 1.112 + id = socket.connection.pushId += 2, 1.113 + scheme = this._frame.headers.scheme, 1.114 + host = this._frame.headers.host || 'localhost', 1.115 + fullUrl = /^\//.test(url) ? scheme + '://' + host + url : url; 1.116 + 1.117 + this._framer.streamFrame( 1.118 + id, 1.119 + this.id, 1.120 + { 1.121 + method: 'GET', 1.122 + path: url, 1.123 + url: fullUrl, 1.124 + scheme: scheme, 1.125 + host: host, 1.126 + version: 'HTTP/1.1', 1.127 + priority: priority || 0 1.128 + }, 1.129 + headers, 1.130 + function(err, frame) { 1.131 + if (err) { 1.132 + socket._unlock(); 1.133 + callback(err); 1.134 + } else { 1.135 + socket.connection.write(frame); 1.136 + socket._unlock(); 1.137 + 1.138 + var stream = new spdy.server.Stream(socket.connection, { 1.139 + type: 'SYN_STREAM', 1.140 + push: true, 1.141 + id: id, 1.142 + assoc: socket.id, 1.143 + priority: 0, 1.144 + headers: {} 1.145 + }); 1.146 + 1.147 + socket.connection.streams[id] = stream; 1.148 + socket.pushes.push(stream); 1.149 + 1.150 + callback(null, stream); 1.151 + } 1.152 + } 1.153 + ); 1.154 + }); 1.155 +};