diff --git a/src/attacker.js b/src/attacker.js index 933d403..41f5550 100644 --- a/src/attacker.js +++ b/src/attacker.js @@ -5,6 +5,17 @@ const Reporter = require('./reporter'); const convertToDuration = (value) => typeof value === 'number' ? `${value}ms` : value; +const availableMethods = [ + 'GET', + 'HEAD', + 'POST', + 'PUT', + 'DELETE', + 'CONNECT', + 'OPTIONS', + 'TRACE', +]; + class Attacker extends Command { constructor(priorCommands, options) { super('attack', priorCommands, options); @@ -120,11 +131,23 @@ class Attacker extends Command { return this.addFlag('workers', value); } request(method, url) { - const command = createCommand(this.currentCmd.name, this.currentCmd.flags, this.currentCmd.globalFlags); - command.stdin.setEncoding('utf-8'); - command.stdin.write(`${method.toUpperCase()} ${url}\n`); - command.std.end(); - return command; + if (typeof method !== 'string') { + throw Error('method must be a string'); + } + if (typeof url !== 'string') { + throw Error('url must be a string'); + } + const newCopy = this.generateCopy(); + const upperCasedMethod = method.toUpperCase(); + if (!availableMethods.includes(upperCasedMethod)) { + throw Error('invalid method supplied'); + } + newCopy.commands.splice( + newCopy.commands.length - 1, + 0, + {name: `${upperCasedMethod} ${url}`, command: 'echo', flags: [], globalFlags: []} + ); + return newCopy; } dump() { return new Dumper(this.commands); diff --git a/src/command.js b/src/command.js index 75c6d15..1c5c4ef 100644 --- a/src/command.js +++ b/src/command.js @@ -9,16 +9,22 @@ const GLOBAL_FLAGS = { class Command { constructor(name = null, priorCommands = [], options = {flags: [], globalFlags: []}) { - this.commands = priorCommands.slice().map((command) => ({ - name: command.name, - flags: command.flags.slice(), - globalFlags: command.globalFlags.slice(), - })); + this.commands = priorCommands.slice().map((command) => { + const newCommand = { + name: command.name, + flags: command.flags.slice(), + globalFlags: command.globalFlags.slice(), + } + if (command.command) { + newCommand.command = command.command; + } + return newCommand; + }); const flags = options.flags || []; this.currentCmd = { name, flags, - globalFlags: options.globalFlags || [] + globalFlags: options.globalFlags || [], }; this.flagsHash = flags.reduce((prev, curr) => { if(curr.name) { @@ -32,7 +38,7 @@ class Command { const CurrentCommand = this.constructor; const args = [ this.commands.slice(0, this.commands.length - 1), - {flags: this.currentCmd.flags, globalFlags: this.currentCmd.globalFlags} + {flags: this.currentCmd.flags, globalFlags: this.currentCmd.globalFlags, command: this.currentCmd.command} ]; if (CurrentCommand === Command) { args.unshift(this.currentCmd.name); @@ -68,9 +74,7 @@ class Command { } process() { return this.commands.reduce((prev, command, i) => { - const flags = command.flags; - const globalFlags = command.globalFlags; - let commandToGiveBack = createCommand(command.name, flags, globalFlags); + let commandToGiveBack = createCommand(command); if (prev) { prev.stdout.pipe(commandToGiveBack.stdin); } @@ -79,9 +83,7 @@ class Command { } stream() { return this.commands.reduce((prev, command, i) => { - const flags = command.flags; - const globalFlags = command.globalFlags; - let commandToGiveBack = createStream(command.name, flags, globalFlags); + let commandToGiveBack = createStream(command); if (prev) { prev.pipe(commandToGiveBack); } @@ -101,12 +103,6 @@ class Command { const currentCommand = this.stream(); return currentCommand.on(event, cb); } - out() { - return this.process().stdout; - } - in() { - return this.process().stdin; - } } module.exports = Command; \ No newline at end of file diff --git a/src/utils.js b/src/utils.js index 511dbb8..91c83af 100644 --- a/src/utils.js +++ b/src/utils.js @@ -15,18 +15,23 @@ const transformFlags = (flags) => { return flags.map((flag) => transformFlag(flag.name, flag.value)); } -const createCommand = (command, flags, globalFlags) => { +const createCommandObj = (config) => { + const {name, flags, globalFlags} = config; + const command = config.command ? config.command : 'vegeta'; const parsedGlobalFlags = transformFlags(globalFlags); const parsedCommandFlags = transformFlags(flags); - const allOptions = parsedGlobalFlags.concat([command], parsedCommandFlags); - return spawn('vegeta', allOptions); + const allOptions = parsedGlobalFlags.concat([name], parsedCommandFlags); + return { command, options: allOptions}; } -const createStream = (command, flags, globalFlags) => { - const parsedGlobalFlags = transformFlags(globalFlags); - const parsedCommandFlags = transformFlags(flags); - const allOptions = parsedGlobalFlags.concat([command], parsedCommandFlags); - return duplexSpawn('vegeta', allOptions); +const createCommand = (config) => { + const { command, options } = createCommandObj(config); + return spawn(command, options); +} + +const createStream = (config) => { + const { command, options } = createCommandObj(config); + return duplexSpawn(command, options); } module.exports = {