Netmorphic
Netmorphic is a library for testing networked applications, such as REST clients over HTTP, and database clients over TCP.
The easiest way to get started is to use the netmorphic template application.
table of contents
installation
clone the repo
git clone https://github.com/ql-io/netmorphic.git
cd netmorphic
make clean install
use NPM
npm install netmorphic
var netmorphic = require('netmorphic')
Configurations
Configure your proxy with a json file. See the examples below.
HTTP Configuration
RESTful routing is made available through the use of the Router module.
{
"/path/to/endpoint":{
"host":"endpoint.host.example.com",
"port":80,
"type":"slow",
"method":"get",
"latency": 100
},
"/product/{id}":{
"host":"endpoint.host.example.com",
"port":80,
"type":"flakey",
"method":"get",
"hi" : 2000,
"lo" : 500,
},
"addresses" : []
}
TCP configuration
TCP configuration is similar to the above, with two major exceptions. The first is that multi-tenancy is not currently supported, so there is no 'global' key at the top level. The second is that urls are replaced with the the port number that the proxy server will listen on.
{
"10001": {
"host" : "127.0.0.1",
"port" : 3124,
"type" : "normal"
},
"10002": {
"host" : "127.0.0.1",
"port" : 3124,
"type" : "slow",
"latency" : 5000
},
"10003": {
"host" : "127.0.0.1",
"port" : 3124,
"type" : "drop",
"lo" : 1000,
"high" : 5000
},
"10004": {
"host" : "127.0.0.1",
"port" : 3124,
"type" : "bumpy",
"lo" : 3500,
"high" : 7000
}
}
quick start
HTTP
var netmorphic = require('netmorphic').http
, config = require('files/myconfig.json')
, USE_CLUSTER = false
, CUSTOM_HANDLERS = false;
var proxy = netmorphic(CONFIG, CUSTOM_HANDLERS, USE_CLUSTER);
proxy.server.listen(8000)
var netmorphic = require('netmorphic').http
, monitor = require('netmorphic').monitor
, Cluster = requir('cluster2')
, config = require('files/myconfig.json')
, USE_CLUSTER = true
, CUSTOM_HANDLERS = false;
var proxy = netmorphic(CONFIG, CUSTOM_HANDLERS, USE_CLUSTER);
var cluster = new Cluster({
port: 8000,
monitor: monitor()
})
cluster.listen(function(cb){
cb(proxy.server)
})
TCP
var TCProxy = require('netmorphic').tcp
, config = require('files/TCP.config.json')
, CUSTOM_HANDLERS = false
, USE_CLUSTER = false;
var servers = TCProxy(config, CUSTOM_HANDLERS, USE_CLUSTER)
servers.forEach(function(server){
server.app.listen(server.port)
})
var TCProxy = require('netmorphic').tcp
, monitor = require('netmorphic').monitor
, config = require('files/TCP.config.json')
, Cluster = require('cluster2')
, CUSTOM_HANDLERS = false
, USE_CLUSTER = true;
var servers = TCProxy(config, CUSTOM_HANDLERS, USE_CLUSTER)
var cluster = new Cluster({
monitor: monitor()
})
cluster.listen(function(cb){
cb(servers)
})
handlers
Handlers are are the "morph" in netmorphic. They act upon your requests and streams. Parameters for your handlers are set in the config files. Netmorphic ships with a few handlers out of the box, namely:
- normal - plain proxy
- slow - buffers the outgoing request by a minimum latency
- flakey - buffers the request for a random latency between hi and lo values
- drop - drops request immediately or
- unresponsive - does not respond to the request
Additionally, custom handlers can be written to do anything. Pass an object of handler functions to the netmorphic constructor, like so:
var TCProxy = require('netmorphic').tcp
, config = require('files/TCP.config.json')
, CUSTOM_HANDLERS = require('files/my.custom.handlers.js')
, USE_CLUSTER = true;
var servers = TCProxy(config, CUSTOM_HANDLERS, USE_CLUSTER)
a custom HTTP handler file would look like this:
module.exports['just proxy'] = function(req, res){
var config = req.serConfig;
var proxy = req.proxy;
proxy.proxyRequest(req, res, {
host:config.host,
port:config.port
});
}
For TCP, it looks like this:
var ps = require('pause-stream');
module.exports['vanilla tcp proxy'] = function(socket, service){
var buffer = ps();
socket.pipe(buffer.pause());
service.connect(socket._CONFIG.port, socket._CONFIG.host, function(){
buffer.pipe(service);
buffer.resume()
});
service.pipe(socket);
}