Skip to content
This repository has been archived by the owner on Dec 16, 2023. It is now read-only.

Commit

Permalink
Renamed replay.js as index.js
Browse files Browse the repository at this point in the history
  • Loading branch information
assaf committed May 4, 2015
1 parent f647766 commit fd0a677
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 190 deletions.
183 changes: 181 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,184 @@
const Replay = require('./replay');

// The Replay module holds global configution properties and methods.


const Catalog = require('./catalog');
const Chain = require('./chain');
const debug = require('./debug');
const { EventEmitter } = require('events');
const logger = require('./logger');
const passThrough = require('./pass_through');
const recorder = require('./recorder');


// Supported modes.
const MODES = [ 'bloody', 'cheat', 'record', 'replay' ];

// Headers that are recorded/matched during replay.
const MATCH_HEADERS = [ /^accept/, /^authorization/, /^body/, /^content-type/, /^host/, /^if-/, /^x-/ ];


// Instance properties:
//
// catalog - The catalog is responsible for loading pre-recorded responses
// into memory, from where they can be replayed, and storing captured responses.
//
// chain - The proxy chain. Essentially an array of proxies through which
// each request goes, from first to last. You generally don't need
// to use this unless you decide to reconstruct your own chain.
//
// When adding new proxies, you probably want those executing ahead
// of any existing proxies (certainly the pass-through proxy), so
// you'll want to prepend them. The `use` method will prepend a
// proxy to the chain.
//
// headers - Only these headers are matched when recording/replaying. A list
// of regular expressions.
//
// fixtures - Main directory for replay fixtures.
//
// mode - The mode we're running in, one of:
// bloody - Allow outbound HTTP requests, don't replay anything. Use this to
// test your code against changes to 3rd party API.
// cheat - Allow outbound HTTP requests, replay captured responses. This
// mode is particularly useful when new code makes new requests, but
// unstable yet and you don't want these requests saved.
// record - Allow outbound HTTP requests, capture responses for future
// replay. This mode allows you to capture and record new requests,
// e.g. when adding tests or making code changes.
// replay - Do not allow outbound HTTP requests, replay captured responses.
// This is the default mode and the one most useful for running tests
class Replay extends EventEmitter {

constructor(mode) {
super();
if (!~MODES.indexOf(mode))
throw new Error(`Unsupported mode '${mode}', must be one of ${MODES.join(', ')}.`);

this.chain = new Chain();
this.mode = mode;
// Localhost servers: pass request to localhost
this._localhosts = {
'localhost': true,
'127.0.0.1': true
};
// Pass through requests to these servers
this._passThrough = { };
// Dropp connections to these servers
this._dropped = { };
this.catalog = new Catalog(this);
this.headers = MATCH_HEADERS;

// Automatically emit connection errors and such, also prevent process from failing.
this.on('error', function(error) {
debug(`Replay: ${error.message || error}`);
});
}


// Addes a proxy to the beginning of the processing chain, so it executes ahead of any existing proxy.
//
// Example
// replay.use replay.logger()
use(proxy) {
this.chain.prepend(proxy);
return this;
}

// Pass through all requests to these hosts
passThrough(...hosts) {
this.reset(...hosts);
for (let host of hosts)
this._passThrough[host] = true;
return this;
}

// True to pass through requests to this host
isPassThrough(host) {
const domain = host.replace(/^[^.]+/, '*');
return !!(this._passThrough[host] || this._passThrough[domain] || this._passThrough[`*.${host}`]);
}

// Do not allow network access to these hosts (drop connection)
drop(...hosts) {
this.reset(...hosts);
for (let host of hosts)
this._dropped[host] = true;
return this;
}

// True if this host is on the dropped list
isDropped(host) {
const domain = host.replace(/^[^.]+/, '*');
return !!(this._dropped[host] || this._dropped[domain] || this._dropped[`*.${host}`]);
}

// Treats this host as localhost: requests are routed directly to 127.0.0.1, no
// replay. Useful when you want to send requests to the test server using its
// production host name.
localhost(...hosts) {
this.reset(...hosts);
for (let host of hosts)
this._localhosts[host] = true;
return this;
}

// True if this host should be treated as localhost.
isLocalhost(host) {
const domain = host.replace(/^[^.]+/, '*');
return !!(this._localhosts[host] || this._localhosts[domain] || this._localhosts[`*.${host}`]);
}

// Use this when you want to exclude host from dropped/pass-through/localhost
reset(...hosts) {
for (let host of hosts) {
delete this._localhosts[host];
delete this._passThrough[host];
delete this._dropped[host];
}
return this;
}

get fixtures() {
return this.catalog.getFixturesDir();
}

set fixtures(dir) {
// Clears loaded fixtures, and updates to new dir
this.catalog.setFixturesDir(dir);
}

}


const replay = new Replay(process.env.REPLAY || 'replay');


// The default processing chain (from first to last):
// - Pass through requests to localhost
// - Log request to console is `deubg` is true
// - Replay recorded responses
// - Pass through requests in bloody and cheat modes
function passWhenBloodyOrCheat(request) {
return replay.isPassThrough(request.url.hostname) ||
(replay.mode === 'cheat' && !replay.isDropped(request.url.hostname));
}

function passToLocalhost(request) {
return replay.isLocalhost(request.url.hostname) ||
replay.mode === 'bloody';
}

replay
.use(passThrough(passWhenBloodyOrCheat))
.use(recorder(replay))
.use(logger(replay))
.use(passThrough(passToLocalhost));


module.exports = replay;

require('./patch_http_request');
require('./patch_dns_lookup');

module.exports = Replay;

4 changes: 2 additions & 2 deletions src/patch_dns_lookup.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Patch DNS.lookup to resolve all hosts added via Replay.localhost as 127.0.0.1

const DNS = require('dns');
const Replay = require('./replay');
const DNS = require('dns');
const Replay = require('./');


const originalLookup = DNS.lookup;
Expand Down
2 changes: 1 addition & 1 deletion src/patch_http_request.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

const HTTP = require('http');
const ProxyRequest = require('./proxy');
const Replay = require('./replay');
const Replay = require('./');
const URL = require('url');


Expand Down
183 changes: 0 additions & 183 deletions src/replay.js

This file was deleted.

2 changes: 1 addition & 1 deletion test/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const Express = require('express');
const bodyParser = require('body-parser');
const HTTP = require('http');
const HTTPS = require('https');
const Replay = require('../src/replay');
const Replay = require('../src');
const File = require('fs');
const Async = require('async');

Expand Down
Loading

0 comments on commit fd0a677

Please sign in to comment.