Skip to content

Commit 1126b4b

Browse files
committed
♻️ refactor: Refactor curl parser
Signed-off-by: sqrtthree <[email protected]>
1 parent 3b45966 commit 1126b4b

File tree

2 files changed

+112
-91
lines changed

2 files changed

+112
-91
lines changed

components/CURL/index.vue

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import nprogress from 'nprogress'
1212
1313
import request from '../../request'
1414
import { isJSON, isQueryString, parseQueryString } from '../../utils'
15-
import { isCURL, resolveArgs, resolveHeaders } from '../../curl'
15+
import curl from '../../curl'
1616
1717
// configure progress bar
1818
nprogress.configure({ showSpinner: false })
@@ -29,35 +29,13 @@ export default {
2929
sendRequest() {
3030
const cmd = this.$refs.curl.outerText.trim()
3131
32-
if (!isCURL(cmd)) return
33-
3432
if (this.loading) return
3533
36-
const args = resolveArgs(cmd)
37-
38-
const options = {
39-
url: args.url,
40-
method: args.request ? args.request.toLowerCase() : 'get',
41-
}
42-
43-
if (args.header) {
44-
options.headers = resolveHeaders(args.header)
45-
}
46-
47-
if (args.data) {
48-
let data
49-
50-
if (isJSON(args.data)) {
51-
data = JSON.parse(args.data)
52-
} else if (isQueryString(args.data)) {
53-
data = parseQueryString(args.data)
54-
}
34+
const options = curl(cmd)
5535
56-
if (options.method === 'get' || options.method === 'delete') {
57-
options.params = data
58-
} else {
59-
options.data = data
60-
}
36+
if (!options) {
37+
this.$message.error('Got an invalid CURL command, please check it and try again.')
38+
return
6139
}
6240
6341
console.clear()

curl.js

Lines changed: 107 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,7 @@
1-
const normalize = args => {
2-
const shortMap = {
3-
X: 'request',
4-
A: 'user-agent',
5-
e: 'referer',
6-
G: 'get',
7-
F: 'form',
8-
H: 'header',
9-
d: 'data',
10-
}
11-
12-
const result = []
13-
14-
args.forEach((item, index) => {
15-
if (isURL(item)) {
16-
result.push('--url', item)
17-
} else if (item.length > 1 && item[0] === '-' && item[1] !== '-') {
18-
result.push(`--${shortMap[item.substring(1)]}`)
19-
} else if (/^[\'\"](.*\s*)*[\'\"]$/.test(item)) {
20-
result.push(item.slice(1, -1))
21-
} else {
22-
result.push(item)
23-
}
24-
})
25-
26-
return result
27-
}
28-
29-
const parseOptions = args => {
30-
const result = {}
31-
let lastOption = ''
32-
33-
args.forEach(item => {
34-
if (/^--/.test(item)) {
35-
lastOption = item.substring(2)
36-
} else if (parametersSupportingMultipleValues.includes(lastOption)) {
37-
if (!result[lastOption]) {
38-
result[lastOption] = []
39-
}
40-
41-
result[lastOption].push(item)
42-
} else {
43-
result[lastOption] = item
44-
}
45-
})
46-
47-
return result
48-
}
49-
50-
export const parametersSupportingMultipleValues = ['header']
1+
import { isJSON, isQueryString, parseQueryString } from './utils'
512

52-
export function isCURL(cmd) {
53-
return cmd.startsWith('curl')
3+
const parseField = (s) => {
4+
return s.split(/: (.+)/)
545
}
556

567
export function isURL(url) {
@@ -63,22 +14,114 @@ export function isURL(url) {
6314
return urlRegexp.test(url) || localhost.test(url)
6415
}
6516

66-
export function resolveArgs(cmd) {
67-
const rawArgs = cmd.substring(5)
68-
const argsList = rawArgs
69-
.match(/"[^"]+"|'[^']+'|\S+/g)
70-
.filter(item => item.trim() !== '\\')
71-
72-
return parseOptions(normalize(argsList))
17+
export function isCURL(cmd) {
18+
return cmd.startsWith('curl ')
7319
}
7420

75-
export function resolveHeaders(headers) {
76-
const result = {}
21+
export default function curl(cmd) {
22+
if (!isCURL(cmd)) return
23+
24+
const args = cmd
25+
.match(/"[^"]+"|'[^']+'|\S+/g)
26+
.filter(item => item.trim() !== '\\')
7727

78-
headers.forEach(item => {
79-
const [attr, value] = item.split(':')
28+
const result = {
29+
method: 'GET',
30+
headers: {},
31+
}
8032

81-
result[attr.trim()] = value.trim()
33+
let state = ''
34+
35+
args.forEach(function(arg){
36+
switch (true) {
37+
case isURL(arg):
38+
result.url = arg
39+
break;
40+
41+
case arg == '-A' || arg == '--user-agent':
42+
state = 'user-agent'
43+
break;
44+
45+
case arg == '-H' || arg == '--header':
46+
state = 'header'
47+
break;
48+
49+
case arg == '-d' || arg == '--data' || arg == '--data-ascii':
50+
state = 'data'
51+
break;
52+
53+
case arg == '-u' || arg == '--user':
54+
state = 'user'
55+
break;
56+
57+
case arg == '-I' || arg == '--head':
58+
result.method = 'HEAD'
59+
break;
60+
61+
case arg == '-X' || arg == '--request':
62+
state = 'method'
63+
break;
64+
65+
case arg == '-b' || arg =='--cookie':
66+
state = 'cookie'
67+
break;
68+
69+
case arg == '--compressed':
70+
result.headers['Accept-Encoding'] = result.headers['Accept-Encoding'] || 'deflate, gzip'
71+
break;
72+
73+
case !!arg:
74+
// Delete the start position and the end of the quotation mark
75+
if (/^['"]/.test(arg)) {
76+
arg = arg.slice(1, -1)
77+
}
78+
79+
switch (state) {
80+
case 'header':
81+
var field = parseField(arg)
82+
result.headers[field[0]] = field[1]
83+
state = ''
84+
break;
85+
case 'user-agent':
86+
result.headers['User-Agent'] = arg
87+
state = ''
88+
break;
89+
case 'data':
90+
if (result.method.toUpperCase() === 'GET' || result.method.toUpperCase() === 'HEAD') {
91+
result.method = 'POST'
92+
}
93+
94+
result.headers['Content-Type'] = result.headers['Content-Type'] || 'application/json'
95+
96+
if (isJSON(arg)) {
97+
const data = JSON.parse(arg)
98+
99+
result.data = result.data
100+
? Object.assign(result.data, data)
101+
: data
102+
} else if (isQueryString(arg)) {
103+
result.data = result.data
104+
? result.data + '&' + arg
105+
: arg
106+
}
107+
108+
state = ''
109+
break;
110+
case 'user':
111+
result.headers['Authorization'] = 'Basic ' + btoa(arg)
112+
state = ''
113+
break;
114+
case 'method':
115+
result.method = arg.toLowerCase()
116+
state = ''
117+
break;
118+
case 'cookie':
119+
result.headers['Set-Cookie'] = arg
120+
state = ''
121+
break;
122+
}
123+
break;
124+
}
82125
})
83126

84127
return result

0 commit comments

Comments
 (0)