diff --git a/README.md b/README.md index 00683c3..2992ae8 100644 --- a/README.md +++ b/README.md @@ -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: diff --git a/bin/vcr.js b/bin/vcr.js index b4233ca..676d14c 100644 --- a/bin/vcr.js +++ b/bin/vcr.js @@ -22,6 +22,10 @@ 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') @@ -29,8 +33,13 @@ var argv = require('yargs') 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); diff --git a/src/__tests__/server.spec.ts b/src/__tests__/server.spec.ts index ed08671..3abf96c 100644 --- a/src/__tests__/server.spec.ts +++ b/src/__tests__/server.spec.ts @@ -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) @@ -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') @@ -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') @@ -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') @@ -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') @@ -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') diff --git a/src/index.ts b/src/index.ts index 0be86e5..a188f34 100644 --- a/src/index.ts +++ b/src/index.ts @@ -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) { diff --git a/src/middlewares/proxy/index.ts b/src/middlewares/proxy/index.ts index 3587e26..60a296e 100644 --- a/src/middlewares/proxy/index.ts +++ b/src/middlewares/proxy/index.ts @@ -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(); @@ -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(); } diff --git a/src/server.ts b/src/server.ts index a4e77fa..fb03e2f 100644 --- a/src/server.ts +++ b/src/server.ts @@ -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()); @@ -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