Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,14 @@ Output:
yarn vcr -- --fixturesDir [./fixtures]

Options:
-h, --help Show help [boolean]
-f, --fixturesDir Directory where to load fixtures [default: "./fixtures"]
-p, --proxy URL to real API
-r, --record Record proxied responses to fixtures dir [boolean]
-h, --help Show help [boolean]
-f, --fixturesDir Directory where to load fixtures
[default: "./fixtures"]
-p, --proxy URL to real API
-r, --record Record proxied responses to fixtures dir [boolean]
-a, --proxyFailedResponses Record and proxy response independently on status
code, including 5xx, 4xx, 3xx. Nice for debug.
[boolean]
--port [default: 8100]

Examples:
Expand Down
11 changes: 10 additions & 1 deletion bin/vcr.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,24 @@ var argv = require('yargs')
.alias('r', 'record')
.describe('r', 'Record proxied responses to fixtures dir')

.boolean('proxyFailedResponses')
.alias('a', 'proxyFailedResponses')
.describe('a', 'Record and proxy response independently on status code, including 5xx, 4xx, 3xx. Nice for debug.')

.default('port', 8100)

.example('-f ./fixtures -p https://ur.l/base -r', 'Load fixtures from directory, proxy not found fixtures to ur.l/base and success responses record back to fixtures directory')
.argv;

var app = express();
var fixturesDir = path.join(process.cwd(), argv.fixturesDir);
var options = {
realApiBaseUrl: argv.proxy,
outputDir: argv.record && fixturesDir,
proxyFailedResponses: argv.proxyFailedResponses,
};

app.use(server([fixturesDir], argv.proxy, argv.record && fixturesDir))
app.use(server([fixturesDir], options))
app.listen(argv.port, function(err) {
if (err) {
return console.error(err);
Expand Down
12 changes: 6 additions & 6 deletions src/__tests__/server.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ afterAll(async () => {
});

describe('Stub server', () => {
const app = server([path.join(__dirname, 'fixtures')], 'https://jsonplaceholder.typicode.com');
const app = server([path.join(__dirname, 'fixtures')], {realApiBaseUrl: 'https://jsonplaceholder.typicode.com'});

it('should respond with index', async () =>
await request(app)
Expand Down Expand Up @@ -213,7 +213,7 @@ describe('Stub server in proxy mode', async () => {
});

it('should proxy requests and keep correct encoding - gzip', async () => {
const appserver = server(fixtureDirs, 'http://localhost:5000', outputFixturesDir);
const appserver = server(fixtureDirs, {realApiBaseUrl: 'http://localhost:5000', outputDir: outputFixturesDir});
await request.agent(appserver)
.get('/mocked')
.set('accept-encoding', 'gzip')
Expand All @@ -223,7 +223,7 @@ describe('Stub server in proxy mode', async () => {
});

it('should proxy requests and keep correct encoding - deflate', async () => {
const appserver = server(fixtureDirs, 'http://localhost:5000', outputFixturesDir);
const appserver = server(fixtureDirs, {realApiBaseUrl: 'http://localhost:5000', outputDir: outputFixturesDir});
await request.agent(appserver)
.get('/mocked')
.set('accept-encoding', 'deflate')
Expand All @@ -233,7 +233,7 @@ describe('Stub server in proxy mode', async () => {
});

it('should proxy requests and keep correct encoding - gzip, deflate', async () => {
const appserver = server(fixtureDirs, 'http://localhost:5000', outputFixturesDir);
const appserver = server(fixtureDirs, {realApiBaseUrl: 'http://localhost:5000', outputDir: outputFixturesDir});
await request.agent(appserver)
.get('/mocked')
.set('accept-encoding', 'deflate, gzip')
Expand All @@ -243,7 +243,7 @@ describe('Stub server in proxy mode', async () => {
});

it('should save correctly decoded fixture to fixturePath ', async () => {
const appserver = server(fixtureDirs, 'http://localhost:5000', outputFixturesDir);
const appserver = server(fixtureDirs, {realApiBaseUrl: 'http://localhost:5000', outputDir: outputFixturesDir});

await request.agent(appserver)
.get('/mocked')
Expand All @@ -261,7 +261,7 @@ describe('Stub server in proxy mode', async () => {
});

it('should proxy and save custom variant when cookie record_fixture_variant is set but default fixture is present', async () => {
const appserver = server(fixtureDirs, 'http://localhost:5000', outputFixturesDir);
const appserver = server(fixtureDirs, {realApiBaseUrl: 'http://localhost:5000', outputDir: outputFixturesDir});

await request.agent(appserver)
.get('/mocked')
Expand Down
9 changes: 7 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@ const app = express();
const PORT = process.env.PORT || 3000;

// const realApiUrl = 'https://js-developer-second-round.herokuapp.com/api/v1';
const realApiUrl = 'http://localhost:5000';

app.use(server([path.join(__dirname, 'fixtures')], realApiUrl, path.join(__dirname, 'generatedFixtures')));
const options = {
realApiBaseUrl: 'http://localhost:5000',
outputDir: path.join(__dirname, 'generatedFixtures'),
proxyFailedResponses: false,
};

app.use(server([path.join(__dirname, 'fixtures')], options));

app.listen(PORT, function(err: Error) {
if (err) {
Expand Down
5 changes: 3 additions & 2 deletions src/middlewares/proxy/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import writeFixture from './writeFixture';
import {IncomingMessage} from 'http';
import {Request, Response, NextFunction, RequestHandler} from 'express';

export default (realApiBaseUrl: string, outputDir?: string): RequestHandler =>
export default (realApiBaseUrl: string, outputDir?: string, proxyFailedResponses?: boolean): RequestHandler =>
(req: Request, res: Response, next: NextFunction): void => {
if (req.path === '/') return next();

Expand All @@ -19,7 +19,8 @@ export default (realApiBaseUrl: string, outputDir?: string): RequestHandler =>
.on('error', (e: Error) => next(e))
.on('response', (proxyRes: IncomingMessage) => {
// response from real API, if not OK, pass control to next
if (!proxyRes.statusCode || proxyRes.statusCode < 200 || proxyRes.statusCode >= 300) {
const isFailStatusCode = !proxyRes.statusCode || proxyRes.statusCode < 200 || proxyRes.statusCode >= 300;
if (!proxyFailedResponses && isFailStatusCode) {
console.log(`${chalk.magenta('[Stub server]')} proxy request to ${chalk.yellow(realApiBaseUrl + req.path)} ended up with ${chalk.red(`${proxyRes.statusCode}`)}`);
return next();
}
Expand Down
10 changes: 8 additions & 2 deletions src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ import {Endpoint, extractEndpoints} from './endpoints';
import {findEndpoint, findFixture, extract, extractVariantsFromRequest} from './matcher';
import {Request, Response, NextFunction} from 'express';

export default (fixtureDirs: string[] = [], realApiBaseUrl?: string, outputDir?: string) => {
interface Options {
realApiBaseUrl?: string;
outputDir?: string;
proxyFailedResponses?: boolean;
}

export default (fixtureDirs: string[] = [], { realApiBaseUrl, outputDir, proxyFailedResponses }: Options = {}) => {
const app = express();
app.use(cors());
app.use(cookieParser());
Expand Down Expand Up @@ -74,7 +80,7 @@ export default (fixtureDirs: string[] = [], realApiBaseUrl?: string, outputDir?:

// Proxy to real API
if (realApiBaseUrl) {
app.use(proxyMiddleware(realApiBaseUrl, outputDir));
app.use(proxyMiddleware(realApiBaseUrl, outputDir, proxyFailedResponses));
}

// Fallback path for displaying all possible endpoints
Expand Down