mirror of
https://github.com/http-party/node-http-proxy.git
synced 2025-12-08 20:59:18 +00:00
Merge branch 'master' of github.com:nodejitsu/node-http-proxy
This commit is contained in:
commit
f20b3740b1
12
README.md
12
README.md
@ -363,6 +363,12 @@ By default, `node-http-proxy` will set a 100 socket limit for all `host:port` pr
|
||||
1. By passing the `maxSockets` option to `httpProxy.createServer()`
|
||||
2. By calling `httpProxy.setMaxSockets(n)`, where `n` is the number of sockets you with to use.
|
||||
|
||||
## POST requests and buffering
|
||||
|
||||
express.bodyParser will interfere with proxying of POST requests (and other methods that have a request
|
||||
body). With bodyParser active, proxied requests will never send anything to the upstream server, and
|
||||
the original client will just hang. See https://github.com/nodejitsu/node-http-proxy/issues/180 for options.
|
||||
|
||||
## Using node-http-proxy from the command line
|
||||
When you install this package with npm, a node-http-proxy binary will become available to you. Using this binary is easy with some simple options:
|
||||
|
||||
@ -426,9 +432,9 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
[0]: http://nodejitsu.com
|
||||
[1]: https://github.com/nodejitsu/node-http-proxy/blob/master/examples/web-socket-proxy.js
|
||||
[2]: https://github.com/nodejitsu/node-http-proxy/blob/master/examples/basic-proxy-https.js
|
||||
[3]: https://github.com/nodejitsu/node-http-proxy/tree/v0.5.0/examples
|
||||
[1]: https://github.com/nodejitsu/node-http-proxy/blob/master/examples/websocket/websocket-proxy.js
|
||||
[2]: https://github.com/nodejitsu/node-http-proxy/blob/master/examples/http/proxy-https-to-http.js
|
||||
[3]: https://github.com/nodejitsu/node-http-proxy/tree/master/examples
|
||||
[4]: http://www.ietf.org/rfc/rfc2616.txt
|
||||
[5]: http://socket.io
|
||||
[6]: http://github.com/nodejitsu/node-http-proxy/issues
|
||||
|
||||
@ -34,7 +34,7 @@ var https = require('https'),
|
||||
var opts = helpers.loadHttps();
|
||||
|
||||
//
|
||||
// Crete the target HTTPS server
|
||||
// Create the target HTTPS server
|
||||
//
|
||||
http.createServer(function (req, res) {
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||
@ -43,7 +43,7 @@ http.createServer(function (req, res) {
|
||||
}).listen(8000);
|
||||
|
||||
//
|
||||
// Create the proxy server listening on port 443.
|
||||
// Create the proxy server listening on port 443
|
||||
//
|
||||
httpProxy.createServer(8000, 'localhost', {
|
||||
https: opts
|
||||
|
||||
@ -34,7 +34,7 @@ var https = require('https'),
|
||||
var opts = helpers.loadHttps();
|
||||
|
||||
//
|
||||
// Crete the target HTTPS server
|
||||
// Create the target HTTPS server
|
||||
//
|
||||
https.createServer(opts, function (req, res) {
|
||||
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||
@ -43,7 +43,7 @@ https.createServer(opts, function (req, res) {
|
||||
}).listen(8000);
|
||||
|
||||
//
|
||||
// Create the proxy server listening on port 443.
|
||||
// Create the proxy server listening on port 443
|
||||
//
|
||||
httpProxy.createServer(8000, 'localhost', {
|
||||
https: opts,
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
|
||||
*/
|
||||
|
||||
var sys = require('sys'),
|
||||
var util = require('util'),
|
||||
http = require('http'),
|
||||
colors = require('colors'),
|
||||
websocket = require('../../vendor/websocket'),
|
||||
@ -55,10 +55,10 @@ server.listen(8080);
|
||||
//
|
||||
var socket = io.listen(server);
|
||||
socket.on('connection', function (client) {
|
||||
sys.debug('Got websocket connection');
|
||||
util.debug('Got websocket connection');
|
||||
|
||||
client.on('message', function (msg) {
|
||||
sys.debug('Got message from client: ' + msg);
|
||||
util.debug('Got message from client: ' + msg);
|
||||
});
|
||||
|
||||
socket.broadcast('from server');
|
||||
@ -101,5 +101,5 @@ ws.on('open', function () {
|
||||
});
|
||||
|
||||
ws.on('message', function (msg) {
|
||||
sys.debug('Got message: ' + utils.decode(msg));
|
||||
util.debug('Got message: ' + utils.decode(msg));
|
||||
});
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
|
||||
*/
|
||||
|
||||
var sys = require('sys'),
|
||||
var util = require('util'),
|
||||
http = require('http'),
|
||||
colors = require('colors'),
|
||||
websocket = require('../../vendor/websocket'),
|
||||
@ -55,10 +55,10 @@ server.listen(8080);
|
||||
//
|
||||
var socket = io.listen(server);
|
||||
socket.on('connection', function (client) {
|
||||
sys.debug('Got websocket connection');
|
||||
util.debug('Got websocket connection');
|
||||
|
||||
client.on('message', function (msg) {
|
||||
sys.debug('Got message from client: ' + msg);
|
||||
util.debug('Got message from client: ' + msg);
|
||||
});
|
||||
|
||||
socket.broadcast('from server');
|
||||
@ -97,5 +97,5 @@ ws.on('open', function () {
|
||||
});
|
||||
|
||||
ws.on('message', function (msg) {
|
||||
sys.debug('Got message: ' + utils.decode(msg));
|
||||
util.debug('Got message: ' + utils.decode(msg));
|
||||
});
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
|
||||
*/
|
||||
|
||||
var sys = require('sys'),
|
||||
var util = require('util'),
|
||||
http = require('http'),
|
||||
colors = require('colors'),
|
||||
websocket = require('../../vendor/websocket'),
|
||||
@ -55,10 +55,10 @@ server.listen(8080);
|
||||
//
|
||||
var socket = io.listen(server);
|
||||
socket.on('connection', function (client) {
|
||||
sys.debug('Got websocket connection');
|
||||
util.debug('Got websocket connection');
|
||||
|
||||
client.on('message', function (msg) {
|
||||
sys.debug('Got message from client: ' + msg);
|
||||
util.debug('Got message from client: ' + msg);
|
||||
});
|
||||
|
||||
socket.broadcast('from server');
|
||||
@ -80,5 +80,5 @@ ws.on('open', function () {
|
||||
});
|
||||
|
||||
ws.on('message', function (msg) {
|
||||
sys.debug('Got message: ' + utils.decode(msg));
|
||||
util.debug('Got message: ' + utils.decode(msg));
|
||||
});
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
*/
|
||||
|
||||
var events = require('events'),
|
||||
http = require('http'),
|
||||
util = require('util'),
|
||||
httpProxy = require('../node-http-proxy');
|
||||
|
||||
@ -122,17 +123,37 @@ HttpProxy.prototype.proxyRequest = function (req, res, buffer) {
|
||||
|
||||
//
|
||||
// Add common proxy headers to the request so that they can
|
||||
// be availible to the proxy target server:
|
||||
// be availible to the proxy target server. If the proxy is
|
||||
// part of proxy chain it will append the address:
|
||||
//
|
||||
// * `x-forwarded-for`: IP Address of the original request
|
||||
// * `x-forwarded-proto`: Protocol of the original request
|
||||
// * `x-forwarded-port`: Port of the original request.
|
||||
//
|
||||
|
||||
if (this.enable.xforward && req.connection && req.socket) {
|
||||
req.headers['x-forwarded-for'] = req.connection.remoteAddress || req.socket.remoteAddress;
|
||||
req.headers['x-forwarded-port'] = req.connection.remotePort || req.socket.remotePort;
|
||||
req.headers['x-forwarded-proto'] = req.connection.pair ? 'https' : 'http';
|
||||
if (req.headers['x-forwarded-for']){
|
||||
var addressToAppend = "," + req.connection.remoteAddress || req.socket.remoteAddress;
|
||||
req.headers['x-forwarded-for'] += addressToAppend;
|
||||
}
|
||||
else {
|
||||
req.headers['x-forwarded-for'] = req.connection.remoteAddress || req.socket.remoteAddress;
|
||||
}
|
||||
|
||||
if (req.headers['x-forwarded-port']){
|
||||
var portToAppend = "," + req.connection.remotePort || req.socket.remotePort;
|
||||
req.headers['x-forwarded-port'] += portToAppend;
|
||||
}
|
||||
else {
|
||||
req.headers['x-forwarded-port'] = req.connection.remotePort || req.socket.remotePort;
|
||||
}
|
||||
|
||||
if (req.headers['x-forwarded-proto']){
|
||||
var protoToAppend = "," + req.connection.pair ? 'https' : 'http';
|
||||
req.headers['x-forwarded-proto'] += protoToAppend;
|
||||
}
|
||||
else {
|
||||
req.headers['x-forwarded-proto'] = req.connection.pair ? 'https' : 'http';
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@ -213,6 +234,15 @@ HttpProxy.prototype.proxyRequest = function (req, res, buffer) {
|
||||
delete response.headers['transfer-encoding'];
|
||||
}
|
||||
|
||||
if ((response.statusCode === 301) || (response.statusCode === 302)) {
|
||||
if (self.source.https && !self.target.https) {
|
||||
response.headers.location = response.headers.location.replace(/^http\:/, 'https:');
|
||||
}
|
||||
if (self.target.https && !self.source.https) {
|
||||
response.headers.location = response.headers.location.replace(/^https\:/, 'http:');
|
||||
}
|
||||
}
|
||||
|
||||
// Set the headers of the client response
|
||||
res.writeHead(response.statusCode, response.headers);
|
||||
|
||||
@ -271,11 +301,19 @@ HttpProxy.prototype.proxyRequest = function (req, res, buffer) {
|
||||
//
|
||||
reverseProxy.once('error', proxyError);
|
||||
|
||||
//
|
||||
// If `req` is aborted, we abort our `reverseProxy` request as well.
|
||||
//
|
||||
req.on('aborted', function () {
|
||||
reverseProxy.abort();
|
||||
});
|
||||
|
||||
//
|
||||
// For each data `chunk` received from the incoming
|
||||
// `req` write it to the `reverseProxy` request.
|
||||
//
|
||||
req.on('data', function (chunk) {
|
||||
|
||||
if (!errState) {
|
||||
var flushed = reverseProxy.write(chunk);
|
||||
if (!flushed) {
|
||||
@ -352,16 +390,37 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, buffer)
|
||||
|
||||
//
|
||||
// Add common proxy headers to the request so that they can
|
||||
// be availible to the proxy target server:
|
||||
// be availible to the proxy target server. If the proxy is
|
||||
// part of proxy chain it will append the address:
|
||||
//
|
||||
// * `x-forwarded-for`: IP Address of the original request
|
||||
// * `x-forwarded-proto`: Protocol of the original request
|
||||
// * `x-forwarded-port`: Port of the original request.
|
||||
//
|
||||
if (this.enable.xforward && req.connection && req.connection.socket) {
|
||||
req.headers['x-forwarded-for'] = req.connection.remoteAddress || req.connection.socket.remoteAddress;
|
||||
req.headers['x-forwarded-port'] = req.connection.remotePort || req.connection.socket.remotePort;
|
||||
req.headers['x-forwarded-proto'] = req.connection.pair ? 'https' : 'http';
|
||||
if (req.headers['x-forwarded-for']){
|
||||
var addressToAppend = "," + req.connection.remoteAddress || req.connection.socket.remoteAddress;
|
||||
req.headers['x-forwarded-for'] += addressToAppend;
|
||||
}
|
||||
else {
|
||||
req.headers['x-forwarded-for'] = req.connection.remoteAddress || req.connection.socket.remoteAddress;
|
||||
}
|
||||
|
||||
if (req.headers['x-forwarded-port']){
|
||||
var portToAppend = "," + req.connection.remotePort || req.connection.socket.remotePort;
|
||||
req.headers['x-forwarded-port'] += portToAppend;
|
||||
}
|
||||
else {
|
||||
req.headers['x-forwarded-port'] = req.connection.remotePort || req.connection.socket.remotePort;
|
||||
}
|
||||
|
||||
if (req.headers['x-forwarded-proto']){
|
||||
var protoToAppend = "," + req.connection.pair ? 'wss' : 'ws';
|
||||
req.headers['x-forwarded-proto'] += protoToAppend;
|
||||
}
|
||||
else {
|
||||
req.headers['x-forwarded-proto'] = req.connection.pair ? 'wss' : 'ws';
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@ -527,11 +586,13 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, buffer)
|
||||
//
|
||||
outgoing.host = this.target.host;
|
||||
outgoing.port = this.target.port;
|
||||
outgoing.agent = agent;
|
||||
outgoing.method = 'GET';
|
||||
outgoing.path = req.url;
|
||||
outgoing.headers = req.headers;
|
||||
outgoing.agent = agent;
|
||||
|
||||
var reverseProxy = agent.appendMessage(outgoing);
|
||||
var reverseProxy = this.target.protocol.request(outgoing);
|
||||
|
||||
//
|
||||
// On any errors from the `reverseProxy` emit the
|
||||
@ -553,7 +614,6 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, buffer)
|
||||
// available to the `upgrade` event. This bookkeeping is not tracked anywhere
|
||||
// in nodejs core and is **very** specific to proxying WebSockets.
|
||||
//
|
||||
reverseProxy.agent = agent;
|
||||
reverseProxy.incoming = {
|
||||
request: req,
|
||||
socket: socket,
|
||||
@ -568,24 +628,22 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, buffer)
|
||||
// In addition, it's important to note the closure scope here. Since
|
||||
// there is no mapping of the socket to the request bound to it.
|
||||
//
|
||||
if (!agent._events || agent._events['upgrade'].length === 0) {
|
||||
agent.on('upgrade', function (_, remoteSocket, head) {
|
||||
//
|
||||
// Prepare the socket for the reverseProxy request and begin to
|
||||
// stream data between the two sockets. Here it is important to
|
||||
// note that `remoteSocket._httpMessage === reverseProxy`.
|
||||
//
|
||||
_socket(remoteSocket, true);
|
||||
onUpgrade(remoteSocket._httpMessage, remoteSocket);
|
||||
});
|
||||
}
|
||||
reverseProxy.on('upgrade', function (_, remoteSocket, head) {
|
||||
//
|
||||
// Prepare the socket for the reverseProxy request and begin to
|
||||
// stream data between the two sockets. Here it is important to
|
||||
// note that `remoteSocket._httpMessage === reverseProxy`.
|
||||
//
|
||||
_socket(remoteSocket, true);
|
||||
onUpgrade(remoteSocket._httpMessage, remoteSocket);
|
||||
});
|
||||
|
||||
//
|
||||
// If the reverseProxy connection has an underlying socket,
|
||||
// then execute the WebSocket handshake.
|
||||
//
|
||||
if (typeof reverseProxy.socket !== 'undefined') {
|
||||
reverseProxy.socket.on('data', function handshake (data) {
|
||||
reverseProxy.once('socket', function (revSocket) {
|
||||
revSocket.on('data', function handshake (data) {
|
||||
//
|
||||
// Ok, kind of harmfull part of code. Socket.IO sends a hash
|
||||
// at the end of handshake if protocol === 76, but we need
|
||||
@ -618,12 +676,12 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, buffer)
|
||||
socket.write(sdata);
|
||||
var flushed = socket.write(data);
|
||||
if (!flushed) {
|
||||
reverseProxy.socket.pause();
|
||||
revSocket.pause();
|
||||
socket.once('drain', function () {
|
||||
try { reverseProxy.socket.resume() }
|
||||
try { revSocket.resume() }
|
||||
catch (er) { console.error("reverseProxy.socket.resume error: %s", er.message) }
|
||||
});
|
||||
|
||||
|
||||
//
|
||||
// Force the `drain` event in 100ms if it hasn't
|
||||
// happened on its own.
|
||||
@ -638,7 +696,7 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, buffer)
|
||||
// Remove data listener on socket error because the
|
||||
// 'handshake' has failed.
|
||||
//
|
||||
reverseProxy.socket.removeListener('data', handshake);
|
||||
revSocket.removeListener('data', handshake);
|
||||
return proxyError(ex);
|
||||
}
|
||||
|
||||
@ -648,9 +706,9 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, buffer)
|
||||
//
|
||||
// Remove data listener now that the 'handshake' is complete
|
||||
//
|
||||
reverseProxy.socket.removeListener('data', handshake);
|
||||
revSocket.removeListener('data', handshake);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
reverseProxy.on('error', proxyError);
|
||||
|
||||
@ -689,9 +747,11 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, buffer)
|
||||
HttpProxy.prototype.close = function () {
|
||||
[this.forward, this.target].forEach(function (proxy) {
|
||||
if (proxy && proxy.agent) {
|
||||
proxy.agent.sockets.forEach(function (socket) {
|
||||
socket.end();
|
||||
});
|
||||
for (var host in proxy.agent.sockets) {
|
||||
proxy.agent.sockets[host].forEach(function (socket) {
|
||||
socket.end();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@ -97,7 +97,7 @@ ProxyTable.prototype.setRoutes = function (router) {
|
||||
this.routes = [];
|
||||
|
||||
Object.keys(router).forEach(function (path) {
|
||||
var route = new RegExp(path, 'i');
|
||||
var route = new RegExp('^' + path, 'i');
|
||||
|
||||
self.routes.push({
|
||||
route: route,
|
||||
@ -137,7 +137,6 @@ ProxyTable.prototype.getProxyLocation = function (req) {
|
||||
for (var i in this.routes) {
|
||||
var route = this.routes[i];
|
||||
if (target.match(route.route)) {
|
||||
|
||||
var pathSegments = route.path.split('/');
|
||||
|
||||
if (pathSegments.length > 1) {
|
||||
|
||||
@ -180,8 +180,8 @@ RoutingProxy.prototype.proxyRequest = function (req, res, options) {
|
||||
options.host = location.host;
|
||||
}
|
||||
|
||||
var key = options.host + ':' + options.port,
|
||||
proxy;
|
||||
var key = this._getKey(options),
|
||||
proxy;
|
||||
|
||||
if (!this.proxies[key]) {
|
||||
this.add(options);
|
||||
@ -218,8 +218,8 @@ RoutingProxy.prototype.proxyWebSocketRequest = function (req, socket, head, opti
|
||||
options.host = location.host;
|
||||
}
|
||||
|
||||
var key = options.host + ':' + options.port,
|
||||
proxy;
|
||||
var key = this._getKey(options),
|
||||
proxy;
|
||||
|
||||
if (!this.proxies[key]) {
|
||||
this.add(options);
|
||||
|
||||
10
package.json
10
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "http-proxy",
|
||||
"version": "0.7.6",
|
||||
"version": "0.8.0",
|
||||
"description": "A full-featured http reverse proxy for node.js",
|
||||
"author": "Charlie Robbins <charlie.robbins@gmail.com>",
|
||||
"contributors": [
|
||||
@ -22,14 +22,16 @@
|
||||
"devDependencies": {
|
||||
"request": "1.9.x",
|
||||
"vows": "0.5.x",
|
||||
"async": "0.1.x",
|
||||
"socket.io": "0.6.x"
|
||||
},
|
||||
"main": "./lib/node-http-proxy",
|
||||
"bin": { "node-http-proxy": "./bin/node-http-proxy" },
|
||||
"scripts": {
|
||||
"test": "npm run-script test-http && npm run-script test-https",
|
||||
"test": "npm run-script test-http && npm run-script test-https && npm run-script test-core",
|
||||
"test-http": "vows --spec && vows --spec --target=secure",
|
||||
"test-https": "vows --spec --source=secure && vows --spec --source=secure --target=secure"
|
||||
"test-https": "vows --spec --source=secure && vows --spec --source=secure --target=secure",
|
||||
"test-core": "test/core/run"
|
||||
},
|
||||
"engines": { "node": "0.4.x || 0.5.x" }
|
||||
"engines": { "node": ">= 0.6.6" }
|
||||
}
|
||||
|
||||
10
test/core/README.md
Normal file
10
test/core/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
# `test/core`
|
||||
|
||||
`test/core` directory is a place where tests from node.js core go. They are
|
||||
here to ensure that node-http-proxy works just fine with all kinds of
|
||||
different situations, which are covered in core tests, but are not covered in
|
||||
our tests.
|
||||
|
||||
All these tests require little modifications to make them test node-http-proxy,
|
||||
but we try to keep them as vanilla as possible.
|
||||
|
||||
145
test/core/common.js
Normal file
145
test/core/common.js
Normal file
@ -0,0 +1,145 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var path = require('path');
|
||||
var assert = require('assert');
|
||||
|
||||
exports.testDir = path.dirname(__filename);
|
||||
exports.fixturesDir = path.join(exports.testDir, 'fixtures');
|
||||
exports.libDir = path.join(exports.testDir, '../lib');
|
||||
exports.tmpDir = path.join(exports.testDir, 'tmp');
|
||||
exports.PORT = 12346;
|
||||
exports.PROXY_PORT = 1234567;
|
||||
|
||||
if (process.platform == 'win32') {
|
||||
exports.PIPE = '\\\\.\\pipe\\libuv-test';
|
||||
} else {
|
||||
exports.PIPE = exports.tmpDir + '/test.sock';
|
||||
}
|
||||
|
||||
var util = require('util');
|
||||
for (var i in util) exports[i] = util[i];
|
||||
//for (var i in exports) global[i] = exports[i];
|
||||
|
||||
function protoCtrChain(o) {
|
||||
var result = [];
|
||||
for (; o; o = o.__proto__) { result.push(o.constructor); }
|
||||
return result.join();
|
||||
}
|
||||
|
||||
exports.indirectInstanceOf = function(obj, cls) {
|
||||
if (obj instanceof cls) { return true; }
|
||||
var clsChain = protoCtrChain(cls.prototype);
|
||||
var objChain = protoCtrChain(obj);
|
||||
return objChain.slice(-clsChain.length) === clsChain;
|
||||
};
|
||||
|
||||
|
||||
exports.ddCommand = function(filename, kilobytes) {
|
||||
if (process.platform == 'win32') {
|
||||
return '"' + process.argv[0] + '" "' + path.resolve(exports.fixturesDir,
|
||||
'create-file.js') + '" "' + filename + '" ' + (kilobytes * 1024);
|
||||
} else {
|
||||
return 'dd if=/dev/zero of="' + filename + '" bs=1024 count=' + kilobytes;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
exports.spawnPwd = function(options) {
|
||||
var spawn = require('child_process').spawn;
|
||||
|
||||
if (process.platform == 'win32') {
|
||||
return spawn('cmd.exe', ['/c', 'cd'], options);
|
||||
} else {
|
||||
return spawn('pwd', [], options);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Turn this off if the test should not check for global leaks.
|
||||
exports.globalCheck = true;
|
||||
|
||||
process.on('exit', function() {
|
||||
if (!exports.globalCheck) return;
|
||||
var knownGlobals = [setTimeout,
|
||||
setInterval,
|
||||
clearTimeout,
|
||||
clearInterval,
|
||||
console,
|
||||
Buffer,
|
||||
process,
|
||||
global];
|
||||
|
||||
if (global.errno) {
|
||||
knownGlobals.push(errno);
|
||||
}
|
||||
|
||||
if (global.gc) {
|
||||
knownGlobals.push(gc);
|
||||
}
|
||||
|
||||
if (global.DTRACE_HTTP_SERVER_RESPONSE) {
|
||||
knownGlobals.push(DTRACE_HTTP_SERVER_RESPONSE);
|
||||
knownGlobals.push(DTRACE_HTTP_SERVER_REQUEST);
|
||||
knownGlobals.push(DTRACE_HTTP_CLIENT_RESPONSE);
|
||||
knownGlobals.push(DTRACE_HTTP_CLIENT_REQUEST);
|
||||
knownGlobals.push(DTRACE_NET_STREAM_END);
|
||||
knownGlobals.push(DTRACE_NET_SERVER_CONNECTION);
|
||||
knownGlobals.push(DTRACE_NET_SOCKET_READ);
|
||||
knownGlobals.push(DTRACE_NET_SOCKET_WRITE);
|
||||
}
|
||||
|
||||
if (global.ArrayBuffer) {
|
||||
knownGlobals.push(ArrayBuffer);
|
||||
knownGlobals.push(Int8Array);
|
||||
knownGlobals.push(Uint8Array);
|
||||
knownGlobals.push(Int16Array);
|
||||
knownGlobals.push(Uint16Array);
|
||||
knownGlobals.push(Int32Array);
|
||||
knownGlobals.push(Uint32Array);
|
||||
knownGlobals.push(Float32Array);
|
||||
knownGlobals.push(Float64Array);
|
||||
knownGlobals.push(DataView);
|
||||
}
|
||||
|
||||
for (var x in global) {
|
||||
var found = false;
|
||||
|
||||
for (var y in knownGlobals) {
|
||||
if (global[x] === knownGlobals[y]) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
console.error('Unknown global: %s', x);
|
||||
assert.ok(false, 'Unknown global found');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// This function allows one two run an HTTP test agaist both HTTPS and
|
||||
// normal HTTP modules. This ensures they fit the same API.
|
||||
exports.httpTest = function httpTest(cb) {
|
||||
};
|
||||
|
||||
69
test/core/pummel/test-http-upload-timeout.js
Normal file
69
test/core/pummel/test-http-upload-timeout.js
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// This tests setTimeout() by having multiple clients connecting and sending
|
||||
// data in random intervals. Clients are also randomly disconnecting until there
|
||||
// are no more clients left. If no false timeout occurs, this test has passed.
|
||||
var common = require('../common'),
|
||||
assert = require('assert'),
|
||||
http = require('http'),
|
||||
server = http.createServer(),
|
||||
connections = 0;
|
||||
|
||||
server.on('request', function(req, res) {
|
||||
req.socket.setTimeout(1000);
|
||||
req.socket.on('timeout', function() {
|
||||
throw new Error('Unexpected timeout');
|
||||
});
|
||||
req.on('end', function() {
|
||||
connections--;
|
||||
res.writeHead(200);
|
||||
res.end('done\n');
|
||||
if (connections == 0) {
|
||||
server.close();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
server.listen(common.PORT, '127.0.0.1', function() {
|
||||
for (var i = 0; i < 10; i++) {
|
||||
connections++;
|
||||
|
||||
setTimeout(function() {
|
||||
var request = http.request({
|
||||
port: common.PROXY_PORT,
|
||||
method: 'POST',
|
||||
path: '/'
|
||||
});
|
||||
|
||||
function ping() {
|
||||
var nextPing = (Math.random() * 900).toFixed();
|
||||
if (nextPing > 600) {
|
||||
request.end();
|
||||
return;
|
||||
}
|
||||
request.write('ping');
|
||||
setTimeout(ping, nextPing);
|
||||
}
|
||||
ping();
|
||||
}, i * 50);
|
||||
}
|
||||
});
|
||||
90
test/core/run
Executable file
90
test/core/run
Executable file
@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env node
|
||||
/*
|
||||
run.js: test runner for core tests
|
||||
|
||||
Copyright (c) 2011 Nodejitsu
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
var fs = require('fs'),
|
||||
path = require('path'),
|
||||
spawn = require('child_process').spawn,
|
||||
async = require('async'),
|
||||
colors = require('colors'),
|
||||
optimist = require('optimist');
|
||||
|
||||
optimist.argv.color && (colors.mode = optimist.argv.color);
|
||||
|
||||
var testTimeout = 15000;
|
||||
var results = {};
|
||||
|
||||
function runTest(test, callback) {
|
||||
var child = spawn(path.join(__dirname, 'run-single'), [ test ]);
|
||||
|
||||
var killTimeout = setTimeout(function () {
|
||||
child.kill();
|
||||
console.log(' ' + path.basename(test).yellow + ' timed out'.red);
|
||||
}, testTimeout);
|
||||
|
||||
child.on('exit', function (exitCode) {
|
||||
clearTimeout(killTimeout);
|
||||
|
||||
console.log(' ' + ((exitCode) ? '✘'.red : '✔'.green) + ' ' +
|
||||
path.basename(test) +
|
||||
(exitCode ? (' (exit code: ' + exitCode + ')') : ''));
|
||||
results[test] = { exitCode: exitCode };
|
||||
callback();
|
||||
//
|
||||
// We don't want tests to be stopped after first failure, and that's what
|
||||
// async does when it receives truthy value in callback.
|
||||
//
|
||||
});
|
||||
};
|
||||
|
||||
var tests = process.argv.slice(2).filter(function (test) {
|
||||
return test.substr(0, 2) != '--';
|
||||
});
|
||||
|
||||
if (!tests.length) {
|
||||
var pathPrefix = path.join(__dirname, 'simple');
|
||||
tests = fs.readdirSync(pathPrefix).map(function (test) {
|
||||
return path.join(pathPrefix, test);
|
||||
});
|
||||
//
|
||||
// We only run simple tests by default.
|
||||
//
|
||||
}
|
||||
|
||||
console.log('Running tests:'.bold);
|
||||
async.forEachSeries(tests, runTest, function () {
|
||||
var failed = [], ok = [];
|
||||
for (var test in results) {
|
||||
(results[test].exitCode != 0 ? failed : ok).push(test);
|
||||
}
|
||||
|
||||
console.log('\nSummary:'.bold);
|
||||
console.log((' ' + ok.length + '\tpassed tests').green);
|
||||
console.log((' ' + failed.length + '\tfailed tests').red);
|
||||
});
|
||||
|
||||
// vim:filetype=javascript
|
||||
|
||||
62
test/core/run-single
Executable file
62
test/core/run-single
Executable file
@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env node
|
||||
/*
|
||||
run-single.js: test runner for core tests
|
||||
|
||||
Copyright (c) 2011 Nodejitsu
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
//
|
||||
// Basic idea behind core test runner is to modify core tests as little as
|
||||
// possible. That's why we start up node-http-proxy here instead of embeeding
|
||||
// this code in tests.
|
||||
//
|
||||
// In most cases only modification to core tests you'll need is changing port
|
||||
// of http client to common.PROXY_PORT.
|
||||
//
|
||||
|
||||
var path = require('path'),
|
||||
spawn = require('child_process').spawn,
|
||||
httpProxy = require('../../'),
|
||||
common = require('./common');
|
||||
|
||||
var test = process.argv[2];
|
||||
|
||||
if (!test) {
|
||||
return console.error('Need test to run');
|
||||
}
|
||||
|
||||
console.log('Running test ' + test);
|
||||
|
||||
var proxy = httpProxy.createServer(common.PORT, 'localhost');
|
||||
proxy.listen(common.PROXY_PORT);
|
||||
|
||||
proxy.on('listening', function () {
|
||||
console.log('Proxy server listening on ' + common.PROXY_PORT);
|
||||
var testProcess = spawn(process.argv[0], [ process.argv[2] ]);
|
||||
testProcess.stdout.pipe(process.stdout);
|
||||
testProcess.stderr.pipe(process.stderr);
|
||||
testProcess.on('exit', process.exit);
|
||||
});
|
||||
|
||||
// vim:filetype=javascript
|
||||
|
||||
63
test/core/simple/test-http-chunked.js
Normal file
63
test/core/simple/test-http-chunked.js
Normal file
@ -0,0 +1,63 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var http = require('http');
|
||||
|
||||
var UTF8_STRING = '南越国是前203年至前111年存在于岭南地区的一个国家,' +
|
||||
'国都位于番禺,疆域包括今天中国的广东、广西两省区的大部份地区,福建省、湖南、' +
|
||||
'贵州、云南的一小部份地区和越南的北部。南越国是秦朝灭亡后,' +
|
||||
'由南海郡尉赵佗于前203年起兵兼并桂林郡和象郡后建立。前196年和前179年,' +
|
||||
'南越国曾先后两次名义上臣属于西汉,成为西汉的“外臣”。前112年,' +
|
||||
'南越国末代君主赵建德与西汉发生战争,被汉武帝于前111年所灭。' +
|
||||
'南越国共存在93年,历经五代君主。南越国是岭南地区的第一个有记载的政权国家,' +
|
||||
'采用封建制和郡县制并存的制度,它的建立保证了秦末乱世岭南地区社会秩序的稳定,' +
|
||||
'有效的改善了岭南地区落后的政治、经济现状。';
|
||||
|
||||
var server = http.createServer(function(req, res) {
|
||||
res.writeHead(200, {'Content-Type': 'text/plain; charset=utf8'});
|
||||
res.end(UTF8_STRING, 'utf8');
|
||||
});
|
||||
server.listen(common.PORT, function() {
|
||||
var data = '';
|
||||
var get = http.get({
|
||||
path: '/',
|
||||
host: 'localhost',
|
||||
port: common.PROXY_PORT
|
||||
}, function(x) {
|
||||
x.setEncoding('utf8');
|
||||
x.on('data', function(c) {data += c});
|
||||
x.on('error', function(e) {
|
||||
throw e;
|
||||
});
|
||||
x.on('end', function() {
|
||||
assert.equal('string', typeof data);
|
||||
console.log('here is the response:');
|
||||
assert.equal(UTF8_STRING, data);
|
||||
console.log(data);
|
||||
server.close();
|
||||
});
|
||||
});
|
||||
get.on('error', function(e) {throw e});
|
||||
get.end();
|
||||
|
||||
});
|
||||
80
test/core/simple/test-http-client-abort.js
Normal file
80
test/core/simple/test-http-client-abort.js
Normal file
@ -0,0 +1,80 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var http = require('http');
|
||||
|
||||
var clientAborts = 0;
|
||||
|
||||
var server = http.Server(function(req, res) {
|
||||
console.log('Got connection');
|
||||
res.writeHead(200);
|
||||
res.write('Working on it...');
|
||||
|
||||
// I would expect an error event from req or res that the client aborted
|
||||
// before completing the HTTP request / response cycle, or maybe a new
|
||||
// event like "aborted" or something.
|
||||
req.on('aborted', function() {
|
||||
clientAborts++;
|
||||
console.log('Got abort ' + clientAborts);
|
||||
if (clientAborts === N) {
|
||||
console.log('All aborts detected, you win.');
|
||||
server.close();
|
||||
}
|
||||
});
|
||||
|
||||
// since there is already clientError, maybe that would be appropriate,
|
||||
// since "error" is magical
|
||||
req.on('clientError', function() {
|
||||
console.log('Got clientError');
|
||||
});
|
||||
});
|
||||
|
||||
var responses = 0;
|
||||
var N = http.Agent.defaultMaxSockets - 1;
|
||||
var requests = [];
|
||||
|
||||
server.listen(common.PORT, function() {
|
||||
console.log('Server listening.');
|
||||
|
||||
for (var i = 0; i < N; i++) {
|
||||
console.log('Making client ' + i);
|
||||
var options = { port: common.PROXY_PORT, path: '/?id=' + i };
|
||||
var req = http.get(options, function(res) {
|
||||
console.log('Client response code ' + res.statusCode);
|
||||
|
||||
if (++responses == N) {
|
||||
console.log('All clients connected, destroying.');
|
||||
requests.forEach(function(outReq) {
|
||||
console.log('abort');
|
||||
outReq.abort();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
requests.push(req);
|
||||
}
|
||||
});
|
||||
|
||||
process.on('exit', function() {
|
||||
assert.equal(N, clientAborts);
|
||||
});
|
||||
41
test/core/simple/test-http-client-abort2.js
Normal file
41
test/core/simple/test-http-client-abort2.js
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// libuv-broken
|
||||
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var http = require('http');
|
||||
|
||||
var server = http.createServer(function(req, res) {
|
||||
res.end('Hello');
|
||||
});
|
||||
|
||||
server.listen(common.PORT, function() {
|
||||
var req = http.get({port: common.PROXY_PORT}, function(res) {
|
||||
res.on('data', function(data) {
|
||||
req.abort();
|
||||
server.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
74
test/core/simple/test-http-client-upload-buf.js
Normal file
74
test/core/simple/test-http-client-upload-buf.js
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var http = require('http');
|
||||
|
||||
var N = 1024;
|
||||
var bytesRecieved = 0;
|
||||
var server_req_complete = false;
|
||||
var client_res_complete = false;
|
||||
|
||||
var server = http.createServer(function(req, res) {
|
||||
assert.equal('POST', req.method);
|
||||
|
||||
req.on('data', function(chunk) {
|
||||
bytesRecieved += chunk.length;
|
||||
});
|
||||
|
||||
req.on('end', function() {
|
||||
server_req_complete = true;
|
||||
console.log('request complete from server');
|
||||
res.writeHead(200, {'Content-Type': 'text/plain'});
|
||||
res.write('hello\n');
|
||||
res.end();
|
||||
});
|
||||
});
|
||||
server.listen(common.PORT);
|
||||
|
||||
server.on('listening', function() {
|
||||
var req = http.request({
|
||||
port: common.PROXY_PORT,
|
||||
method: 'POST',
|
||||
path: '/'
|
||||
}, function(res) {
|
||||
res.setEncoding('utf8');
|
||||
res.on('data', function(chunk) {
|
||||
console.log(chunk);
|
||||
});
|
||||
res.on('end', function() {
|
||||
client_res_complete = true;
|
||||
server.close();
|
||||
});
|
||||
});
|
||||
|
||||
req.write(new Buffer(N));
|
||||
req.end();
|
||||
|
||||
common.error('client finished sending request');
|
||||
});
|
||||
|
||||
process.on('exit', function() {
|
||||
assert.equal(N, bytesRecieved);
|
||||
assert.equal(true, server_req_complete);
|
||||
assert.equal(true, client_res_complete);
|
||||
});
|
||||
77
test/core/simple/test-http-client-upload.js
Normal file
77
test/core/simple/test-http-client-upload.js
Normal file
@ -0,0 +1,77 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var http = require('http');
|
||||
|
||||
var sent_body = '';
|
||||
var server_req_complete = false;
|
||||
var client_res_complete = false;
|
||||
|
||||
var server = http.createServer(function(req, res) {
|
||||
assert.equal('POST', req.method);
|
||||
req.setEncoding('utf8');
|
||||
|
||||
req.on('data', function(chunk) {
|
||||
console.log('server got: ' + JSON.stringify(chunk));
|
||||
sent_body += chunk;
|
||||
});
|
||||
|
||||
req.on('end', function() {
|
||||
server_req_complete = true;
|
||||
console.log('request complete from server');
|
||||
res.writeHead(200, {'Content-Type': 'text/plain'});
|
||||
res.write('hello\n');
|
||||
res.end();
|
||||
});
|
||||
});
|
||||
server.listen(common.PORT);
|
||||
|
||||
server.on('listening', function() {
|
||||
var req = http.request({
|
||||
port: common.PROXY_PORT,
|
||||
method: 'POST',
|
||||
path: '/'
|
||||
}, function(res) {
|
||||
res.setEncoding('utf8');
|
||||
res.on('data', function(chunk) {
|
||||
console.log(chunk);
|
||||
});
|
||||
res.on('end', function() {
|
||||
client_res_complete = true;
|
||||
server.close();
|
||||
});
|
||||
});
|
||||
|
||||
req.write('1\n');
|
||||
req.write('2\n');
|
||||
req.write('3\n');
|
||||
req.end();
|
||||
|
||||
common.error('client finished sending request');
|
||||
});
|
||||
|
||||
process.on('exit', function() {
|
||||
assert.equal('1\n2\n3\n', sent_body);
|
||||
assert.equal(true, server_req_complete);
|
||||
assert.equal(true, client_res_complete);
|
||||
});
|
||||
42
test/core/simple/test-http-contentLength0.js
Normal file
42
test/core/simple/test-http-contentLength0.js
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var http = require('http');
|
||||
|
||||
// Simple test of Node's HTTP Client choking on a response
|
||||
// with a 'Content-Length: 0 ' response header.
|
||||
// I.E. a space character after the 'Content-Length' throws an `error` event.
|
||||
|
||||
|
||||
var s = http.createServer(function(req, res) {
|
||||
res.writeHead(200, {'Content-Length': '0 '});
|
||||
res.end();
|
||||
});
|
||||
s.listen(common.PORT, function() {
|
||||
|
||||
var request = http.request({ port: common.PROXY_PORT }, function(response) {
|
||||
console.log('STATUS: ' + response.statusCode);
|
||||
s.close();
|
||||
});
|
||||
|
||||
request.end();
|
||||
});
|
||||
40
test/core/simple/test-http-eof-on-connect.js
Normal file
40
test/core/simple/test-http-eof-on-connect.js
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var net = require('net');
|
||||
var http = require('http');
|
||||
|
||||
// This is a regression test for http://github.com/ry/node/issues/#issue/44
|
||||
// It is separate from test-http-malformed-request.js because it is only
|
||||
// reproduceable on the first packet on the first connection to a server.
|
||||
|
||||
var server = http.createServer(function(req, res) {});
|
||||
server.listen(common.PORT);
|
||||
|
||||
server.on('listening', function() {
|
||||
net.createConnection(common.PROXY_PORT).on('connect', function() {
|
||||
this.destroy();
|
||||
}).on('close', function() {
|
||||
server.close();
|
||||
});
|
||||
});
|
||||
86
test/core/simple/test-http-extra-response.js
Normal file
86
test/core/simple/test-http-extra-response.js
Normal file
@ -0,0 +1,86 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var http = require('http');
|
||||
var net = require('net');
|
||||
|
||||
// If an HTTP server is broken and sends data after the end of the response,
|
||||
// node should ignore it and drop the connection.
|
||||
// Demos this bug: https://github.com/ry/node/issues/680
|
||||
|
||||
var body = 'hello world\r\n';
|
||||
var fullResponse =
|
||||
'HTTP/1.1 500 Internal Server Error\r\n' +
|
||||
'Content-Length: ' + body.length + '\r\n' +
|
||||
'Content-Type: text/plain\r\n' +
|
||||
'Date: Fri + 18 Feb 2011 06:22:45 GMT\r\n' +
|
||||
'Host: 10.20.149.2\r\n' +
|
||||
'Access-Control-Allow-Credentials: true\r\n' +
|
||||
'Server: badly broken/0.1 (OS NAME)\r\n' +
|
||||
'\r\n' +
|
||||
body;
|
||||
|
||||
var gotResponse = false;
|
||||
|
||||
|
||||
var server = net.createServer(function(socket) {
|
||||
var postBody = '';
|
||||
|
||||
socket.setEncoding('utf8');
|
||||
|
||||
socket.on('data', function(chunk) {
|
||||
postBody += chunk;
|
||||
|
||||
if (postBody.indexOf('\r\n') > -1) {
|
||||
socket.write(fullResponse);
|
||||
// omg, I wrote the response twice, what a terrible HTTP server I am.
|
||||
socket.end(fullResponse);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
server.listen(common.PORT, function() {
|
||||
http.get({ port: common.PROXY_PORT }, function(res) {
|
||||
var buffer = '';
|
||||
console.log('Got res code: ' + res.statusCode);
|
||||
|
||||
res.setEncoding('utf8');
|
||||
res.on('data', function(chunk) {
|
||||
buffer += chunk;
|
||||
});
|
||||
|
||||
res.on('end', function() {
|
||||
console.log('Response ended, read ' + buffer.length + ' bytes');
|
||||
assert.equal(body, buffer);
|
||||
server.close();
|
||||
gotResponse = true;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
process.on('exit', function() {
|
||||
assert.ok(gotResponse);
|
||||
});
|
||||
|
||||
56
test/core/simple/test-http-head-request.js
Normal file
56
test/core/simple/test-http-head-request.js
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var http = require('http');
|
||||
var util = require('util');
|
||||
|
||||
|
||||
var body = 'hello world\n';
|
||||
|
||||
var server = http.createServer(function(req, res) {
|
||||
common.error('req: ' + req.method);
|
||||
res.writeHead(200, {'Content-Length': body.length});
|
||||
res.end();
|
||||
server.close();
|
||||
});
|
||||
|
||||
var gotEnd = false;
|
||||
|
||||
server.listen(common.PORT, function() {
|
||||
var request = http.request({
|
||||
port: common.PROXY_PORT,
|
||||
method: 'HEAD',
|
||||
path: '/'
|
||||
}, function(response) {
|
||||
common.error('response start');
|
||||
response.on('end', function() {
|
||||
common.error('response end');
|
||||
gotEnd = true;
|
||||
});
|
||||
});
|
||||
request.end();
|
||||
});
|
||||
|
||||
process.on('exit', function() {
|
||||
assert.ok(gotEnd);
|
||||
});
|
||||
61
test/core/simple/test-http-head-response-has-no-body-end.js
Normal file
61
test/core/simple/test-http-head-response-has-no-body-end.js
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// libuv-broken
|
||||
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
|
||||
var http = require('http');
|
||||
|
||||
// This test is to make sure that when the HTTP server
|
||||
// responds to a HEAD request with data to res.end,
|
||||
// it does not send any body.
|
||||
|
||||
var server = http.createServer(function(req, res) {
|
||||
res.writeHead(200);
|
||||
res.end('FAIL'); // broken: sends FAIL from hot path.
|
||||
});
|
||||
server.listen(common.PORT);
|
||||
|
||||
var responseComplete = false;
|
||||
|
||||
server.on('listening', function() {
|
||||
var req = http.request({
|
||||
port: common.PROXY_PORT,
|
||||
method: 'HEAD',
|
||||
path: '/'
|
||||
}, function(res) {
|
||||
common.error('response');
|
||||
res.on('end', function() {
|
||||
common.error('response end');
|
||||
server.close();
|
||||
responseComplete = true;
|
||||
});
|
||||
});
|
||||
common.error('req');
|
||||
req.end();
|
||||
});
|
||||
|
||||
process.on('exit', function() {
|
||||
assert.ok(responseComplete);
|
||||
});
|
||||
58
test/core/simple/test-http-head-response-has-no-body.js
Normal file
58
test/core/simple/test-http-head-response-has-no-body.js
Normal file
@ -0,0 +1,58 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
|
||||
var http = require('http');
|
||||
|
||||
// This test is to make sure that when the HTTP server
|
||||
// responds to a HEAD request, it does not send any body.
|
||||
// In this case it was sending '0\r\n\r\n'
|
||||
|
||||
var server = http.createServer(function(req, res) {
|
||||
res.writeHead(200); // broken: defaults to TE chunked
|
||||
res.end();
|
||||
});
|
||||
server.listen(common.PORT);
|
||||
|
||||
var responseComplete = false;
|
||||
|
||||
server.on('listening', function() {
|
||||
var req = http.request({
|
||||
port: common.PROXY_PORT,
|
||||
method: 'HEAD',
|
||||
path: '/'
|
||||
}, function(res) {
|
||||
common.error('response');
|
||||
res.on('end', function() {
|
||||
common.error('response end');
|
||||
server.close();
|
||||
responseComplete = true;
|
||||
});
|
||||
});
|
||||
common.error('req');
|
||||
req.end();
|
||||
});
|
||||
|
||||
process.on('exit', function() {
|
||||
assert.ok(responseComplete);
|
||||
});
|
||||
101
test/core/simple/test-http-host-headers.js
Normal file
101
test/core/simple/test-http-host-headers.js
Normal file
@ -0,0 +1,101 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// libuv-broken
|
||||
|
||||
|
||||
var http = require('http'),
|
||||
common = require('../common'),
|
||||
assert = require('assert'),
|
||||
httpServer = http.createServer(reqHandler);
|
||||
|
||||
function reqHandler(req, res) {
|
||||
console.log('Got request: ' + req.headers.host + ' ' + req.url);
|
||||
if (req.url === '/setHostFalse5') {
|
||||
assert.equal(req.headers.host, undefined);
|
||||
} else {
|
||||
assert.equal(req.headers.host, 'localhost:' + common.PROXY_PORT,
|
||||
'Wrong host header for req[' + req.url + ']: ' +
|
||||
req.headers.host);
|
||||
}
|
||||
res.writeHead(200, {});
|
||||
//process.nextTick(function() { res.end('ok'); });
|
||||
res.end('ok');
|
||||
}
|
||||
|
||||
function thrower(er) {
|
||||
throw er;
|
||||
}
|
||||
|
||||
testHttp();
|
||||
|
||||
function testHttp() {
|
||||
|
||||
console.log('testing http on port ' + common.PROXY_PORT + ' (proxied to ' +
|
||||
common.PORT + ')');
|
||||
|
||||
var counter = 0;
|
||||
|
||||
function cb() {
|
||||
counter--;
|
||||
console.log('back from http request. counter = ' + counter);
|
||||
if (counter === 0) {
|
||||
httpServer.close();
|
||||
}
|
||||
}
|
||||
|
||||
httpServer.listen(common.PORT, function(er) {
|
||||
console.error('listening on ' + common.PORT);
|
||||
|
||||
if (er) throw er;
|
||||
|
||||
http.get({ method: 'GET',
|
||||
path: '/' + (counter++),
|
||||
host: 'localhost',
|
||||
//agent: false,
|
||||
port: common.PROXY_PORT }, cb).on('error', thrower);
|
||||
|
||||
http.request({ method: 'GET',
|
||||
path: '/' + (counter++),
|
||||
host: 'localhost',
|
||||
//agent: false,
|
||||
port: common.PROXY_PORT }, cb).on('error', thrower).end();
|
||||
|
||||
http.request({ method: 'POST',
|
||||
path: '/' + (counter++),
|
||||
host: 'localhost',
|
||||
//agent: false,
|
||||
port: common.PROXY_PORT }, cb).on('error', thrower).end();
|
||||
|
||||
http.request({ method: 'PUT',
|
||||
path: '/' + (counter++),
|
||||
host: 'localhost',
|
||||
//agent: false,
|
||||
port: common.PROXY_PORT }, cb).on('error', thrower).end();
|
||||
|
||||
http.request({ method: 'DELETE',
|
||||
path: '/' + (counter++),
|
||||
host: 'localhost',
|
||||
//agent: false,
|
||||
port: common.PROXY_PORT }, cb).on('error', thrower).end();
|
||||
});
|
||||
}
|
||||
|
||||
57
test/core/simple/test-http-malformed-request.js
Normal file
57
test/core/simple/test-http-malformed-request.js
Normal file
@ -0,0 +1,57 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var net = require('net');
|
||||
var http = require('http');
|
||||
var url = require('url');
|
||||
|
||||
// Make sure no exceptions are thrown when receiving malformed HTTP
|
||||
// requests.
|
||||
|
||||
var nrequests_completed = 0;
|
||||
var nrequests_expected = 1;
|
||||
|
||||
var server = http.createServer(function(req, res) {
|
||||
console.log('req: ' + JSON.stringify(url.parse(req.url)));
|
||||
|
||||
res.writeHead(200, {'Content-Type': 'text/plain'});
|
||||
res.write('Hello World');
|
||||
res.end();
|
||||
|
||||
if (++nrequests_completed == nrequests_expected) server.close();
|
||||
});
|
||||
server.listen(common.PORT);
|
||||
|
||||
server.on('listening', function() {
|
||||
var c = net.createConnection(common.PROXY_PORT);
|
||||
c.on('connect', function() {
|
||||
c.write('GET /hello?foo=%99bar HTTP/1.1\r\n\r\n');
|
||||
c.end();
|
||||
});
|
||||
|
||||
// TODO add more!
|
||||
});
|
||||
|
||||
process.on('exit', function() {
|
||||
assert.equal(nrequests_expected, nrequests_completed);
|
||||
});
|
||||
68
test/core/simple/test-http-many-keep-alive-connections.js
Normal file
68
test/core/simple/test-http-many-keep-alive-connections.js
Normal file
@ -0,0 +1,68 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var http = require('http');
|
||||
|
||||
var expected = 10000;
|
||||
var responses = 0;
|
||||
var requests = 0;
|
||||
var connection;
|
||||
|
||||
var server = http.Server(function(req, res) {
|
||||
requests++;
|
||||
assert.equal(req.connection, connection);
|
||||
res.writeHead(200);
|
||||
res.end('hello world\n');
|
||||
});
|
||||
|
||||
server.once('connection', function(c) {
|
||||
connection = c;
|
||||
});
|
||||
|
||||
server.listen(common.PORT, function() {
|
||||
var callee = arguments.callee;
|
||||
var request = http.get({
|
||||
port: common.PROXY_PORT,
|
||||
path: '/',
|
||||
headers: {
|
||||
'Connection': 'Keep-alive'
|
||||
}
|
||||
}, function(res) {
|
||||
res.on('end', function() {
|
||||
if (++responses < expected) {
|
||||
callee();
|
||||
} else {
|
||||
process.exit();
|
||||
}
|
||||
});
|
||||
}).on('error', function(e) {
|
||||
console.log(e.message);
|
||||
process.exit(1);
|
||||
});
|
||||
request.agent.maxSockets = 1;
|
||||
});
|
||||
|
||||
process.on('exit', function() {
|
||||
assert.equal(expected, responses);
|
||||
assert.equal(expected, requests);
|
||||
});
|
||||
59
test/core/simple/test-http-multi-line-headers.js
Normal file
59
test/core/simple/test-http-multi-line-headers.js
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
|
||||
var http = require('http');
|
||||
var net = require('net');
|
||||
|
||||
var gotResponse = false;
|
||||
|
||||
var server = net.createServer(function(conn) {
|
||||
var body = 'Yet another node.js server.';
|
||||
|
||||
var response =
|
||||
'HTTP/1.1 200 OK\r\n' +
|
||||
'Connection: close\r\n' +
|
||||
'Content-Length: ' + body.length + '\r\n' +
|
||||
'Content-Type: text/plain;\r\n' +
|
||||
' x-unix-mode=0600;\r\n' +
|
||||
' name=\"hello.txt\"\r\n' +
|
||||
'\r\n' +
|
||||
body;
|
||||
|
||||
conn.write(response, function() {
|
||||
conn.destroy();
|
||||
server.close();
|
||||
});
|
||||
});
|
||||
|
||||
server.listen(common.PORT, function() {
|
||||
http.get({host: '127.0.0.1', port: common.PROXY_PORT}, function(res) {
|
||||
assert.equal(res.headers['content-type'],
|
||||
'text/plain;x-unix-mode=0600;name="hello.txt"');
|
||||
gotResponse = true;
|
||||
});
|
||||
});
|
||||
|
||||
process.on('exit', function() {
|
||||
assert.ok(gotResponse);
|
||||
});
|
||||
109
test/core/simple/test-http-proxy.js
Normal file
109
test/core/simple/test-http-proxy.js
Normal file
@ -0,0 +1,109 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var http = require('http');
|
||||
var url = require('url');
|
||||
|
||||
var PROXY_PORT = common.PORT;
|
||||
var BACKEND_PORT = common.PORT + 1;
|
||||
|
||||
var cookies = [
|
||||
'session_token=; path=/; expires=Sun, 15-Sep-2030 13:48:52 GMT',
|
||||
'prefers_open_id=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT'
|
||||
];
|
||||
|
||||
var headers = {'content-type': 'text/plain',
|
||||
'set-cookie': cookies,
|
||||
'hello': 'world' };
|
||||
|
||||
var backend = http.createServer(function(req, res) {
|
||||
common.debug('backend request');
|
||||
res.writeHead(200, headers);
|
||||
res.write('hello world\n');
|
||||
res.end();
|
||||
});
|
||||
|
||||
var proxy = http.createServer(function(req, res) {
|
||||
common.debug('proxy req headers: ' + JSON.stringify(req.headers));
|
||||
var proxy_req = http.get({
|
||||
port: BACKEND_PORT,
|
||||
path: url.parse(req.url).pathname
|
||||
}, function(proxy_res) {
|
||||
|
||||
common.debug('proxy res headers: ' + JSON.stringify(proxy_res.headers));
|
||||
|
||||
assert.equal('world', proxy_res.headers['hello']);
|
||||
assert.equal('text/plain', proxy_res.headers['content-type']);
|
||||
assert.deepEqual(cookies, proxy_res.headers['set-cookie']);
|
||||
|
||||
res.writeHead(proxy_res.statusCode, proxy_res.headers);
|
||||
|
||||
proxy_res.on('data', function(chunk) {
|
||||
res.write(chunk);
|
||||
});
|
||||
|
||||
proxy_res.on('end', function() {
|
||||
res.end();
|
||||
common.debug('proxy res');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
var body = '';
|
||||
|
||||
var nlistening = 0;
|
||||
function startReq() {
|
||||
nlistening++;
|
||||
if (nlistening < 2) return;
|
||||
|
||||
var client = http.get({
|
||||
port: common.PROXY_PORT,
|
||||
path: '/test'
|
||||
}, function(res) {
|
||||
common.debug('got res');
|
||||
assert.equal(200, res.statusCode);
|
||||
|
||||
assert.equal('world', res.headers['hello']);
|
||||
assert.equal('text/plain', res.headers['content-type']);
|
||||
assert.deepEqual(cookies, res.headers['set-cookie']);
|
||||
|
||||
res.setEncoding('utf8');
|
||||
res.on('data', function(chunk) { body += chunk; });
|
||||
res.on('end', function() {
|
||||
proxy.close();
|
||||
backend.close();
|
||||
common.debug('closed both');
|
||||
});
|
||||
});
|
||||
common.debug('client req');
|
||||
}
|
||||
|
||||
common.debug('listen proxy');
|
||||
proxy.listen(PROXY_PORT, startReq);
|
||||
|
||||
common.debug('listen backend');
|
||||
backend.listen(BACKEND_PORT, startReq);
|
||||
|
||||
process.on('exit', function() {
|
||||
assert.equal(body, 'hello world\n');
|
||||
});
|
||||
55
test/core/simple/test-http-response-close.js
Normal file
55
test/core/simple/test-http-response-close.js
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var http = require('http');
|
||||
|
||||
var gotEnd = false;
|
||||
|
||||
var server = http.createServer(function(req, res) {
|
||||
res.writeHead(200);
|
||||
res.write('a');
|
||||
|
||||
req.on('close', function() {
|
||||
console.error('aborted');
|
||||
gotEnd = true;
|
||||
});
|
||||
});
|
||||
server.listen(common.PORT);
|
||||
|
||||
server.on('listening', function() {
|
||||
console.error('make req');
|
||||
http.get({
|
||||
port: common.PROXY_PORT
|
||||
}, function(res) {
|
||||
console.error('got res');
|
||||
res.on('data', function(data) {
|
||||
console.error('destroy res');
|
||||
res.destroy();
|
||||
server.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
process.on('exit', function() {
|
||||
assert.ok(gotEnd);
|
||||
});
|
||||
59
test/core/simple/test-http-server-multiheaders.js
Normal file
59
test/core/simple/test-http-server-multiheaders.js
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// Verify that the HTTP server implementation handles multiple instances
|
||||
// of the same header as per RFC2616: joining the handful of fields by ', '
|
||||
// that support it, and dropping duplicates for other fields.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var http = require('http');
|
||||
|
||||
var srv = http.createServer(function(req, res) {
|
||||
assert.equal(req.headers.accept, 'abc, def, ghijklmnopqrst');
|
||||
assert.equal(req.headers.host, 'foo');
|
||||
assert.equal(req.headers['x-foo'], 'bingo');
|
||||
assert.equal(req.headers['x-bar'], 'banjo, bango');
|
||||
|
||||
res.writeHead(200, {'Content-Type' : 'text/plain'});
|
||||
res.end('EOF');
|
||||
|
||||
srv.close();
|
||||
});
|
||||
|
||||
srv.listen(common.PORT, function() {
|
||||
http.get({
|
||||
host: 'localhost',
|
||||
port: common.PROXY_PORT,
|
||||
path: '/',
|
||||
headers: [
|
||||
['accept', 'abc'],
|
||||
['accept', 'def'],
|
||||
['Accept', 'ghijklmnopqrst'],
|
||||
['host', 'foo'],
|
||||
['Host', 'bar'],
|
||||
['hOst', 'baz'],
|
||||
['x-foo', 'bingo'],
|
||||
['x-bar', 'banjo'],
|
||||
['x-bar', 'bango']
|
||||
]
|
||||
});
|
||||
});
|
||||
84
test/core/simple/test-http-set-cookies.js
Normal file
84
test/core/simple/test-http-set-cookies.js
Normal file
@ -0,0 +1,84 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var http = require('http');
|
||||
|
||||
var nresponses = 0;
|
||||
|
||||
var server = http.createServer(function(req, res) {
|
||||
if (req.url == '/one') {
|
||||
res.writeHead(200, [['set-cookie', 'A'],
|
||||
['content-type', 'text/plain']]);
|
||||
res.end('one\n');
|
||||
} else {
|
||||
res.writeHead(200, [['set-cookie', 'A'],
|
||||
['set-cookie', 'B'],
|
||||
['content-type', 'text/plain']]);
|
||||
res.end('two\n');
|
||||
}
|
||||
});
|
||||
server.listen(common.PORT);
|
||||
|
||||
server.on('listening', function() {
|
||||
//
|
||||
// one set-cookie header
|
||||
//
|
||||
http.get({ port: common.PROXY_PORT, path: '/one' }, function(res) {
|
||||
// set-cookie headers are always return in an array.
|
||||
// even if there is only one.
|
||||
assert.deepEqual(['A'], res.headers['set-cookie']);
|
||||
assert.equal('text/plain', res.headers['content-type']);
|
||||
|
||||
res.on('data', function(chunk) {
|
||||
console.log(chunk.toString());
|
||||
});
|
||||
|
||||
res.on('end', function() {
|
||||
if (++nresponses == 2) {
|
||||
server.close();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// two set-cookie headers
|
||||
|
||||
http.get({ port: common.PROXY_PORT, path: '/two' }, function(res) {
|
||||
assert.deepEqual(['A', 'B'], res.headers['set-cookie']);
|
||||
assert.equal('text/plain', res.headers['content-type']);
|
||||
|
||||
res.on('data', function(chunk) {
|
||||
console.log(chunk.toString());
|
||||
});
|
||||
|
||||
res.on('end', function() {
|
||||
if (++nresponses == 2) {
|
||||
server.close();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
process.on('exit', function() {
|
||||
assert.equal(2, nresponses);
|
||||
});
|
||||
69
test/core/simple/test-http-status-code.js
Normal file
69
test/core/simple/test-http-status-code.js
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// libuv-broken
|
||||
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var http = require('http');
|
||||
|
||||
// Simple test of Node's HTTP ServerResponse.statusCode
|
||||
// ServerResponse.prototype.statusCode
|
||||
|
||||
var testsComplete = 0;
|
||||
var tests = [200, 202, 300, 404, 500];
|
||||
var testIdx = 0;
|
||||
|
||||
var s = http.createServer(function(req, res) {
|
||||
var t = tests[testIdx];
|
||||
res.writeHead(t, {'Content-Type': 'text/plain'});
|
||||
console.log('--\nserver: statusCode after writeHead: ' + res.statusCode);
|
||||
assert.equal(res.statusCode, t);
|
||||
res.end('hello world\n');
|
||||
});
|
||||
|
||||
s.listen(common.PORT, nextTest);
|
||||
|
||||
|
||||
function nextTest() {
|
||||
if (testIdx + 1 === tests.length) {
|
||||
return s.close();
|
||||
}
|
||||
var test = tests[testIdx];
|
||||
|
||||
http.get({ port: common.PROXY_PORT }, function(response) {
|
||||
console.log('client: expected status: ' + test);
|
||||
console.log('client: statusCode: ' + response.statusCode);
|
||||
assert.equal(response.statusCode, test);
|
||||
response.on('end', function() {
|
||||
testsComplete++;
|
||||
testIdx += 1;
|
||||
nextTest();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
process.on('exit', function() {
|
||||
assert.equal(4, testsComplete);
|
||||
});
|
||||
|
||||
72
test/core/simple/test-http-upgrade-server2.js
Normal file
72
test/core/simple/test-http-upgrade-server2.js
Normal file
@ -0,0 +1,72 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var http = require('http');
|
||||
var net = require('net');
|
||||
|
||||
var server = http.createServer(function(req, res) {
|
||||
common.error('got req');
|
||||
throw new Error('This shouldn\'t happen.');
|
||||
});
|
||||
|
||||
server.on('upgrade', function(req, socket, upgradeHead) {
|
||||
common.error('got upgrade event');
|
||||
// test that throwing an error from upgrade gets
|
||||
// is uncaught
|
||||
throw new Error('upgrade error');
|
||||
});
|
||||
|
||||
var gotError = false;
|
||||
|
||||
process.on('uncaughtException', function(e) {
|
||||
common.error('got \'clientError\' event');
|
||||
assert.equal('upgrade error', e.message);
|
||||
gotError = true;
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
|
||||
server.listen(common.PORT, function() {
|
||||
var c = net.createConnection(common.PROXY_PORT);
|
||||
|
||||
c.on('connect', function() {
|
||||
common.error('client wrote message');
|
||||
c.write('GET /blah HTTP/1.1\r\n' +
|
||||
'Upgrade: WebSocket\r\n' +
|
||||
'Connection: Upgrade\r\n' +
|
||||
'\r\n\r\nhello world');
|
||||
});
|
||||
|
||||
c.on('end', function() {
|
||||
c.end();
|
||||
});
|
||||
|
||||
c.on('close', function() {
|
||||
common.error('client close');
|
||||
server.close();
|
||||
});
|
||||
});
|
||||
|
||||
process.on('exit', function() {
|
||||
assert.ok(gotError);
|
||||
});
|
||||
108
test/core/simple/test-http.js
Normal file
108
test/core/simple/test-http.js
Normal file
@ -0,0 +1,108 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var http = require('http');
|
||||
var url = require('url');
|
||||
|
||||
function p(x) {
|
||||
common.error(common.inspect(x));
|
||||
}
|
||||
|
||||
var responses_sent = 0;
|
||||
var responses_recvd = 0;
|
||||
var body0 = '';
|
||||
var body1 = '';
|
||||
|
||||
var server = http.Server(function(req, res) {
|
||||
if (responses_sent == 0) {
|
||||
assert.equal('GET', req.method);
|
||||
assert.equal('/hello', url.parse(req.url).pathname);
|
||||
|
||||
console.dir(req.headers);
|
||||
assert.equal(true, 'accept' in req.headers);
|
||||
assert.equal('*/*', req.headers['accept']);
|
||||
|
||||
assert.equal(true, 'foo' in req.headers);
|
||||
assert.equal('bar', req.headers['foo']);
|
||||
}
|
||||
|
||||
if (responses_sent == 1) {
|
||||
assert.equal('POST', req.method);
|
||||
assert.equal('/world', url.parse(req.url).pathname);
|
||||
this.close();
|
||||
}
|
||||
|
||||
req.on('end', function() {
|
||||
res.writeHead(200, {'Content-Type': 'text/plain'});
|
||||
res.write('The path was ' + url.parse(req.url).pathname);
|
||||
res.end();
|
||||
responses_sent += 1;
|
||||
});
|
||||
|
||||
//assert.equal('127.0.0.1', res.connection.remoteAddress);
|
||||
});
|
||||
server.listen(common.PORT);
|
||||
|
||||
server.on('listening', function() {
|
||||
var agent = new http.Agent({ port: common.PROXY_PORT, maxSockets: 1 });
|
||||
http.get({
|
||||
port: common.PROXY_PORT,
|
||||
path: '/hello',
|
||||
headers: {'Accept': '*/*', 'Foo': 'bar'},
|
||||
agent: agent
|
||||
}, function(res) {
|
||||
assert.equal(200, res.statusCode);
|
||||
responses_recvd += 1;
|
||||
res.setEncoding('utf8');
|
||||
res.on('data', function(chunk) { body0 += chunk; });
|
||||
common.debug('Got /hello response');
|
||||
});
|
||||
|
||||
setTimeout(function() {
|
||||
var req = http.request({
|
||||
port: common.PROXY_PORT,
|
||||
method: 'POST',
|
||||
path: '/world',
|
||||
agent: agent
|
||||
}, function(res) {
|
||||
assert.equal(200, res.statusCode);
|
||||
responses_recvd += 1;
|
||||
res.setEncoding('utf8');
|
||||
res.on('data', function(chunk) { body1 += chunk; });
|
||||
common.debug('Got /world response');
|
||||
});
|
||||
req.end();
|
||||
}, 1);
|
||||
});
|
||||
|
||||
process.on('exit', function() {
|
||||
common.debug('responses_recvd: ' + responses_recvd);
|
||||
assert.equal(2, responses_recvd);
|
||||
|
||||
common.debug('responses_sent: ' + responses_sent);
|
||||
assert.equal(2, responses_sent);
|
||||
|
||||
assert.equal('The path was /hello', body0);
|
||||
assert.equal('The path was /world', body1);
|
||||
});
|
||||
|
||||
198
vendor/websocket.js
vendored
198
vendor/websocket.js
vendored
@ -496,7 +496,7 @@ var WebSocket = function(url, proto, opts) {
|
||||
if (u.protocol === 'ws:' || u.protocol === 'wss:') {
|
||||
protocol = u.protocol === 'ws:' ? http : https;
|
||||
port = u.protocol === 'ws:' ? 80 : 443;
|
||||
agent = u.protocol === 'ws:' ? protocol.getAgent(u.hostname, u.port || port) : protocol.getAgent({
|
||||
agent = u.protocol === new protocol.Agent({
|
||||
host: u.hostname,
|
||||
port: u.port || port
|
||||
});
|
||||
@ -514,105 +514,6 @@ var WebSocket = function(url, proto, opts) {
|
||||
throw new Error('Invalid URL scheme \'' + urlScheme + '\' specified.');
|
||||
}
|
||||
|
||||
if (!agent._events || agent._events['upgrade'].length === 0) {
|
||||
agent.on('upgrade', (function() {
|
||||
var data = undefined;
|
||||
|
||||
return function(res, s, head) {
|
||||
stream = s;
|
||||
|
||||
//
|
||||
// Emit the `wsupgrade` event to inspect the raw
|
||||
// arguments returned from the websocket request.
|
||||
//
|
||||
self.emit('wsupgrade', httpHeaders, res, s, head);
|
||||
|
||||
stream.on('data', function(d) {
|
||||
if (d.length <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
data = d;
|
||||
} else {
|
||||
var data2 = new buffer.Buffer(data.length + d.length);
|
||||
|
||||
data.copy(data2, 0, 0, data.length);
|
||||
d.copy(data2, data.length, 0, d.length);
|
||||
|
||||
data = data2;
|
||||
}
|
||||
|
||||
if (data.length >= 16) {
|
||||
var expected = computeSecretKeySignature(key1, key2, challenge);
|
||||
var actual = data.slice(0, 16).toString('binary');
|
||||
|
||||
// Handshaking fails; we're donezo
|
||||
if (actual != expected) {
|
||||
debug(
|
||||
'expected=\'' + str2hex(expected) + '\'; ' +
|
||||
'actual=\'' + str2hex(actual) + '\''
|
||||
);
|
||||
|
||||
process.nextTick(function() {
|
||||
// N.B. Emit 'wserror' here, as 'error' is a reserved word in the
|
||||
// EventEmitter world, and gets thrown.
|
||||
self.emit(
|
||||
'wserror',
|
||||
new Error('Invalid handshake from server:' +
|
||||
'expected \'' + str2hex(expected) + '\', ' +
|
||||
'actual \'' + str2hex(actual) + '\''
|
||||
)
|
||||
);
|
||||
|
||||
if (self.onerror) {
|
||||
self.onerror();
|
||||
}
|
||||
|
||||
finishClose();
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Un-register our data handler and add the one to be used
|
||||
// for the normal, non-handshaking case. If we have extra
|
||||
// data left over, manually fire off the handler on
|
||||
// whatever remains.
|
||||
//
|
||||
stream.removeAllListeners('data');
|
||||
stream.on('data', dataListener);
|
||||
|
||||
readyState = OPEN;
|
||||
|
||||
process.nextTick(function() {
|
||||
self.emit('open');
|
||||
|
||||
if (self.onopen) {
|
||||
self.onopen();
|
||||
}
|
||||
});
|
||||
|
||||
// Consume any leftover data
|
||||
if (data.length > 16) {
|
||||
stream.emit('data', data.slice(16, data.length));
|
||||
}
|
||||
}
|
||||
});
|
||||
stream.on('fd', fdListener);
|
||||
stream.on('error', errorListener);
|
||||
stream.on('close', function() {
|
||||
errorListener(new Error('Stream closed unexpectedly.'));
|
||||
});
|
||||
|
||||
stream.emit('data', head);
|
||||
};
|
||||
})());
|
||||
}
|
||||
|
||||
agent.on('error', function (e) {
|
||||
errorListener(e);
|
||||
});
|
||||
|
||||
var httpReq = protocol.request({
|
||||
host: u.hostname,
|
||||
method: 'GET',
|
||||
@ -622,6 +523,103 @@ var WebSocket = function(url, proto, opts) {
|
||||
headers: httpHeaders
|
||||
});
|
||||
|
||||
httpReq.on('error', function (e) {
|
||||
errorListener(e);
|
||||
});
|
||||
|
||||
httpReq.on('upgrade', (function() {
|
||||
var data = undefined;
|
||||
|
||||
return function(res, s, head) {
|
||||
stream = s;
|
||||
|
||||
//
|
||||
// Emit the `wsupgrade` event to inspect the raw
|
||||
// arguments returned from the websocket request.
|
||||
//
|
||||
self.emit('wsupgrade', httpHeaders, res, s, head);
|
||||
|
||||
stream.on('data', function(d) {
|
||||
if (d.length <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
data = d;
|
||||
} else {
|
||||
var data2 = new buffer.Buffer(data.length + d.length);
|
||||
|
||||
data.copy(data2, 0, 0, data.length);
|
||||
d.copy(data2, data.length, 0, d.length);
|
||||
|
||||
data = data2;
|
||||
}
|
||||
|
||||
if (data.length >= 16) {
|
||||
var expected = computeSecretKeySignature(key1, key2, challenge);
|
||||
var actual = data.slice(0, 16).toString('binary');
|
||||
|
||||
// Handshaking fails; we're donezo
|
||||
if (actual != expected) {
|
||||
debug(
|
||||
'expected=\'' + str2hex(expected) + '\'; ' +
|
||||
'actual=\'' + str2hex(actual) + '\''
|
||||
);
|
||||
|
||||
process.nextTick(function() {
|
||||
// N.B. Emit 'wserror' here, as 'error' is a reserved word in the
|
||||
// EventEmitter world, and gets thrown.
|
||||
self.emit(
|
||||
'wserror',
|
||||
new Error('Invalid handshake from server:' +
|
||||
'expected \'' + str2hex(expected) + '\', ' +
|
||||
'actual \'' + str2hex(actual) + '\''
|
||||
)
|
||||
);
|
||||
|
||||
if (self.onerror) {
|
||||
self.onerror();
|
||||
}
|
||||
|
||||
finishClose();
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Un-register our data handler and add the one to be used
|
||||
// for the normal, non-handshaking case. If we have extra
|
||||
// data left over, manually fire off the handler on
|
||||
// whatever remains.
|
||||
//
|
||||
stream.removeAllListeners('data');
|
||||
stream.on('data', dataListener);
|
||||
|
||||
readyState = OPEN;
|
||||
|
||||
process.nextTick(function() {
|
||||
self.emit('open');
|
||||
|
||||
if (self.onopen) {
|
||||
self.onopen();
|
||||
}
|
||||
});
|
||||
|
||||
// Consume any leftover data
|
||||
if (data.length > 16) {
|
||||
stream.emit('data', data.slice(16, data.length));
|
||||
}
|
||||
}
|
||||
});
|
||||
stream.on('fd', fdListener);
|
||||
stream.on('error', errorListener);
|
||||
stream.on('close', function() {
|
||||
errorListener(new Error('Stream closed unexpectedly.'));
|
||||
});
|
||||
|
||||
stream.emit('data', head);
|
||||
};
|
||||
})());
|
||||
|
||||
httpReq.write(challenge, 'binary');
|
||||
httpReq.end();
|
||||
})();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user