diff --git a/index.js b/index.js index c49f471..99cd3e7 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,6 @@ -const words = require('shellwords') -const url = require('url') +const words = require('shellwords'); +const url = require('url'); // TODO -F, --form // TODO --data-binary @@ -11,103 +11,103 @@ const url = require('url') * Attempt to parse the given curl string. */ -module.exports = exports.default = function(s) { - if (0 != s.indexOf('curl ')) return - const args = rewrite(words.split(s)) - const out = { method: 'GET', header: {} } - var state = '' - - args.forEach(function(arg){ - switch (true) { - case isURL(arg): - out.url = arg - break; - - case arg == '-A' || arg == '--user-agent': - state = 'user-agent' - break; - - case arg == '-H' || arg == '--header': - state = 'header' - break; - - case arg == '-d' || arg == '--data' || arg == '--data-ascii': - state = 'data' - break; - - case arg == '-u' || arg == '--user': - state = 'user' - break; - - case arg == '-I' || arg == '--head': - out.method = 'HEAD' - break; - - case arg == '-X' || arg == '--request': - state = 'method' - break; - - case arg == '-b' || arg =='--cookie': - state = 'cookie' - break; - - case arg == '--compressed': - out.header['Accept-Encoding'] = out.header['Accept-Encoding'] || 'deflate, gzip' - break; - - case !!arg: - switch (state) { - case 'header': - var field = parseField(arg) - out.header[field[0]] = field[1] - state = '' - break; - case 'user-agent': - out.header['User-Agent'] = arg - state = '' - break; - case 'data': - out.header['Content-Type'] = out.header['Content-Type'] || 'application/x-www-form-urlencoded' - out.body = out.body - ? out.body + '&' + arg - : arg - state = '' - break; - case 'user': - out.header['Authorization'] = 'Basic ' + btoa(arg) - state = '' - break; - case 'method': - out.method = arg - state = '' - break; - case 'cookie': - out.header['Set-Cookie'] = arg - state = '' - break; +module.exports = exports.default = function (s) { + if (0 != s.indexOf('curl ')) return; + const args = rewrite(words.split(s)); + const out = { method: 'GET', header: {} }; + var state = ''; + + args.forEach(function (arg) { + switch (true) { + case isURL(arg): + out.url = arg; + break; + + case arg == '-A' || arg == '--user-agent': + state = 'user-agent'; + break; + + case arg == '-H' || arg == '--header': + state = 'header'; + break; + + case arg == '-d' || arg == '--data' || arg == '--data-ascii': + state = 'data'; + break; + + case arg == '-u' || arg == '--user': + state = 'user'; + break; + + case arg == '-I' || arg == '--head': + out.method = 'HEAD'; + break; + + case arg == '-X' || arg == '--request': + state = 'method'; + break; + + case arg == '-b' || arg == '--cookie': + state = 'cookie'; + break; + + case arg == '--compressed': + out.header['Accept-Encoding'] = out.header['Accept-Encoding'] || 'deflate, gzip'; + break; + + case !!arg: + switch (state) { + case 'header': + var field = parseField(arg); + out.header[field[0]] = field[1]; + state = ''; + break; + case 'user-agent': + out.header['User-Agent'] = arg; + state = ''; + break; + case 'data': + out.header['Content-Type'] = out.header['Content-Type'] || 'application/x-www-form-urlencoded'; + out.body = out.body + ? out.body + '&' + arg + : arg; + state = ''; + break; + case 'user': + out.header['Authorization'] = 'Basic ' + btoa(arg); + state = ''; + break; + case 'method': + out.method = arg; + state = ''; + break; + case 'cookie': + out.header['Set-Cookie'] = arg; + state = ''; + break; + } + break; } - break; - } - }) + }); - return out -} + return out; +}; /** * Rewrite args for special cases such as -XPUT. */ function rewrite(args) { - return args.reduce(function(args, a){ - if (0 == a.indexOf('-X')) { - args.push('-X') - args.push(a.slice(2)) - } else { - args.push(a) - } - - return args - }, []) + return args.reduce(function (args, a) { + if (0 == a.indexOf('-X')) { + args.push('-X'); + args.push(a.slice(2)); + } else { + args.push(a); + } + + return args; + }, []); } /** @@ -115,7 +115,7 @@ function rewrite(args) { */ function parseField(s) { - return s.split(/: */) + return s.split(/: */); } /** @@ -124,5 +124,6 @@ function parseField(s) { function isURL(s) { // TODO: others at some point - return /^https?:\/\//.test(s) + var URLRegxp = /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/; + return URLRegxp.test(s); } diff --git a/test.js b/test.js index 50cfaf7..d95c6ce 100644 --- a/test.js +++ b/test.js @@ -1,195 +1,204 @@ -const assert = require('assert') -const parse = require('./index') +const assert = require('assert'); +const parse = require('./index'); -btoa = s => new Buffer(s).toString('base64') - -const cases = [] +btoa = s => new Buffer(s).toString('base64'); + +const cases = []; + +cases.push({ + input: 'curl http://api.sloths.com', + output: { + method: 'GET', + url: 'http://api.sloths.com', + header: {} + } +}); cases.push({ - input: 'curl http://api.sloths.com', - output: { - method: 'GET', - url: 'http://api.sloths.com', - header: {} - } -}) - -cases.push({ - input: 'curl -I http://api.sloths.com', - output: { - method: 'HEAD', - url: 'http://api.sloths.com', - header: {} - } -}) - -cases.push({ - input: 'curl -I http://api.sloths.com -vvv --foo --whatever bar', - output: { - method: 'HEAD', - url: 'http://api.sloths.com', - header: {} - } -}) - -cases.push({ - input: 'curl --compressed http://api.sloths.com', - output: { - method: 'GET', - url: 'http://api.sloths.com', - header: { - 'Accept-Encoding': 'deflate, gzip' - } - } -}) - -cases.push({ - input: 'curl -H "Accept-Encoding: gzip" --compressed http://api.sloths.com', - output: { - method: 'GET', - url: 'http://api.sloths.com', - header: { - 'Accept-Encoding': 'gzip' - } - } -}) - -cases.push({ - input: 'curl -X DELETE http://api.sloths.com/sloth/4', - output: { - method: 'DELETE', - url: 'http://api.sloths.com/sloth/4', - header: {} - } -}) - -cases.push({ - input: 'curl -XPUT http://api.sloths.com/sloth/4', - output: { - method: 'PUT', - url: 'http://api.sloths.com/sloth/4', - header: {} - } -}) - -cases.push({ - input: 'curl https://api.sloths.com', - output: { - method: 'GET', - url: 'https://api.sloths.com', - header: {} - } -}) - -cases.push({ - input: 'curl -u tobi:ferret https://api.sloths.com', - output: { - method: 'GET', - url: 'https://api.sloths.com', - header: { - Authorization: 'Basic dG9iaTpmZXJyZXQ=' - } - } -}) - -cases.push({ - input: 'curl -d "foo=bar" https://api.sloths.com', - output: { - method: 'GET', - url: 'https://api.sloths.com', - header: { - 'Content-Type': 'application/x-www-form-urlencoded' - }, - body: 'foo=bar' - } -}) - -cases.push({ - input: 'curl -d "foo=bar" -d bar=baz https://api.sloths.com', - output: { - method: 'GET', - url: 'https://api.sloths.com', - header: { - 'Content-Type': 'application/x-www-form-urlencoded' - }, - body: 'foo=bar&bar=baz' - } -}) - -cases.push({ - input: 'curl -H "Accept: text/plain" --header "User-Agent: slothy" https://api.sloths.com', - output: { - method: 'GET', - url: 'https://api.sloths.com', - header: { - 'Accept': 'text/plain', - 'User-Agent': 'slothy' - } - } -}) - -cases.push({ - input: "curl -H 'Accept: text/*' --header 'User-Agent: slothy' https://api.sloths.com", - output: { - method: 'GET', - url: 'https://api.sloths.com', - header: { - 'Accept': 'text/*', - 'User-Agent': 'slothy' - } - } -}) - -cases.push({ - input: "curl -H 'Accept: text/*' -A slothy https://api.sloths.com", - output: { - method: 'GET', - url: 'https://api.sloths.com', - header: { - 'Accept': 'text/*', - 'User-Agent': 'slothy' - } - } -}) - -cases.push({ - input: "curl -b 'foo=bar' slothy https://api.sloths.com", - output: { - method: 'GET', - url: 'https://api.sloths.com', - header: { 'Set-Cookie': 'foo=bar' } - } -}) - -cases.push({ - input: "curl --cookie 'foo=bar' slothy https://api.sloths.com", - output: { - method: 'GET', - url: 'https://api.sloths.com', - header: { 'Set-Cookie': 'foo=bar' } - } -}) - -cases.push({ - input: "curl --cookie 'species=sloth;type=galactic' slothy https://api.sloths.com", - output: { - method: 'GET', - url: 'https://api.sloths.com', - header: { 'Set-Cookie': 'species=sloth;type=galactic' } - } -}) - -cases.forEach(function(c){ - const out = parse(c.input) - - const msg = ` - input: ${c.input} - expected: ${JSON.stringify(c.output)} - received: ${JSON.stringify(out)} - ` - - assert.deepEqual(out, c.output, msg) -}) - -console.log('\n :)\n') + input: 'curl http://localhost', + output: { + method: 'GET', + url: 'http://localhost', + header: {} + } +}); + +cases.push({ + input: 'curl -I http://api.sloths.com', + output: { + method: 'HEAD', + url: 'http://api.sloths.com', + header: {} + } +}); + +cases.push({ + input: 'curl -I http://api.sloths.com -vvv --foo --whatever bar', + output: { + method: 'HEAD', + url: 'http://api.sloths.com', + header: {} + } +}); + +cases.push({ + input: 'curl --compressed http://api.sloths.com', + output: { + method: 'GET', + url: 'http://api.sloths.com', + header: { + 'Accept-Encoding': 'deflate, gzip' + } + } +}); + +cases.push({ + input: 'curl -H "Accept-Encoding: gzip" --compressed http://api.sloths.com', + output: { + method: 'GET', + url: 'http://api.sloths.com', + header: { + 'Accept-Encoding': 'gzip' + } + } +}); + +cases.push({ + input: 'curl -X DELETE http://api.sloths.com/sloth/4', + output: { + method: 'DELETE', + url: 'http://api.sloths.com/sloth/4', + header: {} + } +}); + +cases.push({ + input: 'curl -XPUT http://api.sloths.com/sloth/4', + output: { + method: 'PUT', + url: 'http://api.sloths.com/sloth/4', + header: {} + } +}); + +cases.push({ + input: 'curl https://api.sloths.com', + output: { + method: 'GET', + url: 'https://api.sloths.com', + header: {} + } +}); + +cases.push({ + input: 'curl -u tobi:ferret https://api.sloths.com', + output: { + method: 'GET', + url: 'https://api.sloths.com', + header: { + Authorization: 'Basic dG9iaTpmZXJyZXQ=' + } + } +}); + +cases.push({ + input: 'curl -d "foo=bar" https://api.sloths.com', + output: { + method: 'GET', + url: 'https://api.sloths.com', + header: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + body: 'foo=bar' + } +}); + +cases.push({ + input: 'curl -d "foo=bar" -d bar=baz https://api.sloths.com', + output: { + method: 'GET', + url: 'https://api.sloths.com', + header: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + body: 'foo=bar&bar=baz' + } +}); + +cases.push({ + input: 'curl -H "Accept: text/plain" --header "User-Agent: slothy" https://api.sloths.com', + output: { + method: 'GET', + url: 'https://api.sloths.com', + header: { + Accept: 'text/plain', + 'User-Agent': 'slothy' + } + } +}); + +cases.push({ + input: "curl -H 'Accept: text/*' --header 'User-Agent: slothy' https://api.sloths.com", + output: { + method: 'GET', + url: 'https://api.sloths.com', + header: { + Accept: 'text/*', + 'User-Agent': 'slothy' + } + } +}); + +cases.push({ + input: "curl -H 'Accept: text/*' -A slothy https://api.sloths.com", + output: { + method: 'GET', + url: 'https://api.sloths.com', + header: { + Accept: 'text/*', + 'User-Agent': 'slothy' + } + } +}); + +cases.push({ + input: "curl -b 'foo=bar' slothy https://api.sloths.com", + output: { + method: 'GET', + url: 'https://api.sloths.com', + header: { 'Set-Cookie': 'foo=bar' } + } +}); + +cases.push({ + input: "curl --cookie 'foo=bar' slothy https://api.sloths.com", + output: { + method: 'GET', + url: 'https://api.sloths.com', + header: { 'Set-Cookie': 'foo=bar' } + } +}); + +cases.push({ + input: "curl --cookie 'species=sloth;type=galactic' slothy https://api.sloths.com", + output: { + method: 'GET', + url: 'https://api.sloths.com', + header: { 'Set-Cookie': 'species=sloth;type=galactic' } + } +}); + +cases.forEach(function (c) { + const out = parse(c.input); + + const msg = ` + input: ${ c.input} + expected: ${ JSON.stringify(c.output)} + received: ${ JSON.stringify(out)} + `; + + assert.deepEqual(out, c.output, msg); +}); + +console.log('\n :)\n');