testing/xpcshell/node-spdy/lib/spdy/response.js

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:b3085f5e4fa6
1 var spdy = require('../spdy'),
2 http = require('http'),
3 res = http.ServerResponse.prototype;
4
5 //
6 // ### function _renderHeaders ()
7 // Copy pasted from lib/http.js
8 // (added lowercase)
9 //
10 exports._renderHeaders = function() {
11 if (this._header) {
12 throw new Error("Can't render headers after they are sent to the client.");
13 }
14
15 var keys = Object.keys(this._headerNames);
16 for (var i = 0, l = keys.length; i < l; i++) {
17 var key = keys[i];
18 this._headerNames[key] = this._headerNames[key].toLowerCase();
19 }
20
21 return res._renderHeaders.call(this);
22 };
23
24 //
25 // ### function writeHead (statusCode)
26 // #### @statusCode {Number} HTTP Status code
27 // .writeHead() wrapper
28 // (Sorry, copy pasted from lib/http.js)
29 //
30 exports.writeHead = function(statusCode) {
31 if (this._headerSent) return;
32 this._headerSent = true;
33
34 var reasonPhrase, headers, headerIndex;
35
36 if (typeof arguments[1] == 'string') {
37 reasonPhrase = arguments[1];
38 headerIndex = 2;
39 } else {
40 reasonPhrase = http.STATUS_CODES[statusCode] || 'unknown';
41 headerIndex = 1;
42 }
43 this.statusCode = statusCode;
44
45 var obj = arguments[headerIndex];
46
47 if (obj && this._headers) {
48 // Slow-case: when progressive API and header fields are passed.
49 headers = this._renderHeaders();
50
51 // handle object case
52 var keys = Object.keys(obj);
53 for (var i = 0; i < keys.length; i++) {
54 var k = keys[i];
55 if (k) headers[k] = obj[k];
56 }
57 } else if (this._headers) {
58 // only progressive api is used
59 headers = this._renderHeaders();
60 } else {
61 // only writeHead() called
62 headers = obj;
63 }
64
65 // cleanup
66 this._header = '';
67
68 // Do not send data to new connections after GOAWAY
69 if (this.socket._isGoaway()) return;
70
71 this.socket._lock(function() {
72 var socket = this;
73
74 this._framer.replyFrame(
75 this.id,
76 statusCode,
77 reasonPhrase,
78 headers,
79 function (err, frame) {
80 // TODO: Handle err
81 socket.connection.write(frame);
82 socket._unlock();
83 }
84 );
85 });
86 };
87
88 //
89 // ### function push (url, headers, callback)
90 // #### @url {String} absolute or relative url (from root anyway)
91 // #### @headers {Object} response headers
92 // #### @callbacks {Function} continuation that will receive stream object
93 // Initiates push stream
94 //
95 exports.push = function push(url, headers, priority, callback) {
96 if (this.socket._destroyed) {
97 return callback(Error('Can\'t open push stream, parent socket destroyed'));
98 }
99
100 if (!callback && typeof priority === 'function') {
101 callback = priority;
102 priority = 0;
103 }
104
105 if (!callback) callback = function() {};
106
107 this.socket._lock(function() {
108 var socket = this,
109 id = socket.connection.pushId += 2,
110 scheme = this._frame.headers.scheme,
111 host = this._frame.headers.host || 'localhost',
112 fullUrl = /^\//.test(url) ? scheme + '://' + host + url : url;
113
114 this._framer.streamFrame(
115 id,
116 this.id,
117 {
118 method: 'GET',
119 path: url,
120 url: fullUrl,
121 scheme: scheme,
122 host: host,
123 version: 'HTTP/1.1',
124 priority: priority || 0
125 },
126 headers,
127 function(err, frame) {
128 if (err) {
129 socket._unlock();
130 callback(err);
131 } else {
132 socket.connection.write(frame);
133 socket._unlock();
134
135 var stream = new spdy.server.Stream(socket.connection, {
136 type: 'SYN_STREAM',
137 push: true,
138 id: id,
139 assoc: socket.id,
140 priority: 0,
141 headers: {}
142 });
143
144 socket.connection.streams[id] = stream;
145 socket.pushes.push(stream);
146
147 callback(null, stream);
148 }
149 }
150 );
151 });
152 };

mercurial