Add environment to plugin (#443)

* Allow request in plugin to access current context

Signed-off-by: Xuanwo <xuanwo.cn@gmail.com>

* Add getAllHeaders API for context request

Signed-off-by: Xuanwo <xuanwo.cn@gmail.com>

* Use JSON to parse npm show's output

Signed-off-by: Xuanwo <xuanwo.cn@gmail.com>
This commit is contained in:
Xuanwo 2017-08-22 01:34:25 +08:00 committed by Gregory Schier
parent 012b1f757b
commit e805d86c32
4 changed files with 68 additions and 22 deletions

View File

@ -17,7 +17,7 @@ import * as querystring from '../common/querystring';
import * as util from '../common/misc.js';
import {AUTH_AWS_IAM, AUTH_BASIC, AUTH_DIGEST, AUTH_NETRC, AUTH_NTLM, CONTENT_TYPE_FORM_DATA, CONTENT_TYPE_FORM_URLENCODED, getAppVersion, STATUS_CODE_PLUGIN_ERROR} from '../common/constants';
import {describeByteSize, hasAuthHeader, hasContentTypeHeader, hasUserAgentHeader, setDefaultProtocol} from '../common/misc';
import {getRenderedRequest} from '../common/render';
import {getRenderedRequest, getRenderContext} from '../common/render';
import fs from 'fs';
import * as db from '../common/database';
import * as CACerts from './cacert';
@ -634,10 +634,11 @@ export async function send (requestId: string, environmentId: string) {
}
const renderedRequestBeforePlugins = await getRenderedRequest(request, environmentId);
const renderedContextBeforePlugins = await getRenderContext(request, environmentId, ancestors);
let renderedRequest: RenderedRequest;
try {
renderedRequest = await _applyRequestPluginHooks(renderedRequestBeforePlugins);
renderedRequest = await _applyRequestPluginHooks(renderedRequestBeforePlugins, renderedContextBeforePlugins);
} catch (err) {
return {
response: {
@ -661,14 +662,14 @@ export async function send (requestId: string, environmentId: string) {
return _actuallySend(renderedRequest, workspace, settings);
}
async function _applyRequestPluginHooks (renderedRequest: RenderedRequest): Promise<RenderedRequest> {
async function _applyRequestPluginHooks (renderedRequest: RenderedRequest, renderedContext: Object): Promise<RenderedRequest> {
let newRenderedRequest = renderedRequest;
for (const {plugin, hook} of await plugins.getRequestHooks()) {
newRenderedRequest = clone(newRenderedRequest);
const context = {
...pluginContexts.app.init(plugin),
...pluginContexts.request.init(plugin, newRenderedRequest)
...pluginContexts.request.init(plugin, newRenderedRequest, renderedContext)
};
try {

View File

@ -9,6 +9,14 @@ const PLUGIN = {
module: {}
};
const CONTEXT = {
user_key: 'my_user_key',
hello: 'world',
array_test: ['a', 'b'],
object_test: {a: 'A', b: 'B'},
null_test: null
};
describe('init()', () => {
beforeEach(async () => {
await globalBeforeEach();
@ -17,7 +25,7 @@ describe('init()', () => {
});
it('initializes correctly', async () => {
const result = plugin.init(PLUGIN, await models.request.getById('req_1'));
const result = plugin.init(PLUGIN, await models.request.getById('req_1'), CONTEXT);
expect(Object.keys(result)).toEqual(['request']);
expect(Object.keys(result.request)).toEqual([
'getId',
@ -25,11 +33,14 @@ describe('init()', () => {
'getUrl',
'getMethod',
'getHeader',
'getHeaders',
'hasHeader',
'removeHeader',
'setHeader',
'addHeader',
'setCookie'
'setCookie',
'getEnvironmentVariable',
'getEnvironment'
]);
});
@ -55,7 +66,7 @@ describe('request.*', () => {
});
it('works for basic getters', async () => {
const result = plugin.init(PLUGIN, await models.request.getById('req_1'));
const result = plugin.init(PLUGIN, await models.request.getById('req_1'), CONTEXT);
expect(result.request.getId()).toBe('req_1');
expect(result.request.getName()).toBe('My Request');
expect(result.request.getUrl()).toBe('');
@ -63,7 +74,13 @@ describe('request.*', () => {
});
it('works for headers', async () => {
const result = plugin.init(PLUGIN, await models.request.getById('req_1'));
const result = plugin.init(PLUGIN, await models.request.getById('req_1'), CONTEXT);
// getHeaders()
expect(result.request.getHeaders()).toEqual([
{name: 'hello', value: 'world'},
{name: 'Content-Type', value: 'application/json'}
]);
// getHeader()
expect(result.request.getHeader('content-type')).toBe('application/json');
@ -91,10 +108,33 @@ describe('request.*', () => {
const request = await models.request.getById('req_1');
request.cookies = []; // Because the plugin technically needs a RenderedRequest
const result = plugin.init(PLUGIN, request);
const result = plugin.init(PLUGIN, request, CONTEXT);
result.request.setCookie('foo', 'bar');
result.request.setCookie('foo', 'baz');
expect(request.cookies).toEqual([{name: 'foo', value: 'baz'}]);
});
it('works for environment', async () => {
const request = await models.request.getById('req_1');
request.cookies = []; // Because the plugin technically needs a RenderedRequest
const result = plugin.init(PLUGIN, request, CONTEXT);
// getEnvironment
expect(result.request.getEnvironment()).toEqual({
user_key: 'my_user_key',
hello: 'world',
array_test: ['a', 'b'],
object_test: {a: 'A', b: 'B'},
null_test: null
});
// getEnvironmentVariable
expect(result.request.getEnvironmentVariable('user_key')).toBe('my_user_key');
expect(result.request.getEnvironmentVariable('hello')).toBe('world');
expect(result.request.getEnvironmentVariable('array_test')).toEqual(['a', 'b']);
expect(result.request.getEnvironmentVariable('object_test')).toEqual({a: 'A', b: 'B'});
expect(result.request.getEnvironmentVariable('null_test')).toBe(null);
});
});

View File

@ -3,7 +3,11 @@ import type {Plugin} from '../';
import type {RenderedRequest} from '../../common/render';
import * as misc from '../../common/misc';
export function init (plugin: Plugin, renderedRequest: RenderedRequest): {request: Object} {
export function init (
plugin: Plugin,
renderedRequest: RenderedRequest,
renderedContext: Object
): {request: Object} {
if (!renderedRequest) {
throw new Error('contexts.request initialized without request');
}
@ -33,6 +37,9 @@ export function init (plugin: Plugin, renderedRequest: RenderedRequest): {reques
return null;
}
},
getHeaders (): Array<{name: string, value: string}> {
return renderedRequest.headers.map(h => ({ name: h.name, value: h.value }));
},
hasHeader (name: string): boolean {
return this.getHeader(name) !== null;
},
@ -63,6 +70,12 @@ export function init (plugin: Plugin, renderedRequest: RenderedRequest): {reques
} else {
renderedRequest.cookies.push({name, value});
}
},
getEnvironmentVariable (name: string): string | number | boolean | Object | Array<any> | null {
return renderedContext[name];
},
getEnvironment (): string | number | boolean | Object | Array<any> | null {
return renderedContext;
}
// NOTE: For these to make sense, we'd need to account for cookies in the jar as well

View File

@ -71,21 +71,13 @@ export default async function (moduleName: string): Promise<void> {
async function _isInsomniaPlugin (moduleName: string): Promise<Object> {
return new Promise((resolve, reject) => {
childProcess.exec(
`npm show ${moduleName} insomnia version name dist.shasum dist.tarball`,
(err, stdout, stderr) => {
`npm show ${moduleName} --json`, (err, stdout, stderr) => {
if (err && stderr.includes('E404')) {
reject(new Error(`${moduleName} not found on npm`));
return;
}
const lines = stdout.split('\n').filter(l => !!l);
const info = {};
for (const line of lines) {
const match = line.match(/(.*) = '(.*)'/);
// Strip quotes off of the value
info[match[1]] = match[2];
}
const info = JSON.parse(stdout);
if (!info.hasOwnProperty('insomnia')) {
reject(new Error(`"${moduleName}" not a plugin! Package missing "insomnia" attribute`));
@ -97,8 +89,8 @@ async function _isInsomniaPlugin (moduleName: string): Promise<Object> {
name: info.name,
version: info.version,
dist: {
shasum: info['dist.shasum'],
tarball: info['dist.tarball']
shasum: info.dist.shasum,
tarball: info.dist.tarball
}
});
}