csv-curl 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/README.md +54 -0
- data/bin/csv-curl +47 -18
- data/csv-curl.gemspec +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 381850913b0f63297ab7a5186c9108880d09774930604bd965f7958b573bdeca
|
4
|
+
data.tar.gz: df854cee03e5e4f2c1bc68da0d1c37a845ab8ad9fcb9b19aa0c8f024064999c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9582c3888f042d002b1d229d5433c2bfa7c9d4e8cf7845d3caed560219614f393eca5fa659c8f2f286c7222ebcee4b53bbdccbe576356998a2d79df89cd6a755
|
7
|
+
data.tar.gz: c45dd8f7fc333b38b493b2b4904956b678c498c7fa281f41b90a6d7960e3037ab5bdd3732c2a366087e949d3673de0f69aed6ce21e0be18e3bacba443c6109f1
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1 +1,55 @@
|
|
1
1
|
# csv-curl
|
2
|
+
|
3
|
+
Utility for making multiple curl requests using a CSV file.
|
4
|
+
|
5
|
+
### Usage
|
6
|
+
```
|
7
|
+
Usage: csv-curl[OPTIONS] [CURL OPTIONS]
|
8
|
+
--template FILE Path to the template file
|
9
|
+
--csv CSV_FILE Path to the CSV file
|
10
|
+
--exec UTILITY Utility to run on each response
|
11
|
+
```
|
12
|
+
|
13
|
+
### Template
|
14
|
+
|
15
|
+
File containing the payload to pass to the curl command, the "-d@<file>" option.
|
16
|
+
|
17
|
+
### CSV File
|
18
|
+
|
19
|
+
A CSV file containing the replacement values to use. It must have a header. And have a header for all replacement variables.
|
20
|
+
|
21
|
+
### Utility
|
22
|
+
|
23
|
+
This is an additional command to run on the response body from the curl command.
|
24
|
+
|
25
|
+
Example to output only the "id" from a JSON body
|
26
|
+
|
27
|
+
```
|
28
|
+
csv-curl --csv emails.csv 'https://example.com/user_lookup?email={{param:email}}' --exec 'jq ".id" -r'
|
29
|
+
```
|
30
|
+
|
31
|
+
### Replacement variables
|
32
|
+
|
33
|
+
A replacement variable is enclosed in handlebars **{{** **format:** **name** **}}**. Replacement variables can be used in the arguments to curl, in the template and in the utility.
|
34
|
+
|
35
|
+
*(format and name a separated by a colon)*
|
36
|
+
|
37
|
+
- **name** matches a header in the CSV file
|
38
|
+
- **format** escape sequence to apply the the replacement value
|
39
|
+
- _json_ JSON encode
|
40
|
+
- _param_ URL encode
|
41
|
+
- _base64_ Base64 encode
|
42
|
+
- _urlsafe64_ URL safe Base64 encode
|
43
|
+
- _hex_ Hex encode
|
44
|
+
- _shell_ Shell encode
|
45
|
+
|
46
|
+
Example: lookup users by email and save response by user id.
|
47
|
+
|
48
|
+
```
|
49
|
+
csv-curl --csv users.csv 'https://example.com/user_lookup?email={{param:email}}' --exec 'cat > {{id}}.json'
|
50
|
+
|
51
|
+
# users.csv
|
52
|
+
id,email
|
53
|
+
5,bob@example.com
|
54
|
+
8,johndoe@example.com
|
55
|
+
```
|
data/bin/csv-curl
CHANGED
@@ -11,30 +11,51 @@ require 'digest/md5'
|
|
11
11
|
options = {
|
12
12
|
template_file: nil,
|
13
13
|
csv_file: nil,
|
14
|
-
|
14
|
+
exec: nil,
|
15
15
|
default_format: 'json'
|
16
16
|
}
|
17
17
|
|
18
|
-
OptionParser.new do |opts|
|
19
|
-
opts.banner = "Usage: " + File.basename(__FILE__) + " [CURL OPTIONS]"
|
18
|
+
OPTPARSE = OptionParser.new do |opts|
|
19
|
+
opts.banner = "Usage: " + File.basename(__FILE__) + "[OPTIONS] [CURL OPTIONS]"
|
20
20
|
|
21
|
-
opts.on('--template
|
21
|
+
opts.on('--template FILE', 'Path to the template file') do |v|
|
22
22
|
options[:template_file] = v
|
23
23
|
end
|
24
24
|
|
25
|
-
opts.on('--csv CSV_FILE', '
|
25
|
+
opts.on('--csv CSV_FILE', 'Path to the CSV file') do |v|
|
26
26
|
options[:csv_file] = v
|
27
27
|
end
|
28
28
|
|
29
|
-
opts.on('--
|
30
|
-
options[:
|
29
|
+
opts.on('--exec UTILITY', 'Utility to run on each response') do |v|
|
30
|
+
options[:exec] = v
|
31
31
|
end
|
32
|
-
end
|
32
|
+
end
|
33
|
+
|
34
|
+
CSV_CURL_ARGV = []
|
35
|
+
ARGV.size.times.to_a.reverse.each do |idx|
|
36
|
+
case ARGV[idx]
|
37
|
+
when '--template',
|
38
|
+
'--csv',
|
39
|
+
'--exec'
|
40
|
+
CSV_CURL_ARGV << ARGV.delete_at(idx)
|
41
|
+
CSV_CURL_ARGV << ARGV.delete_at(idx)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
OPTPARSE.parse(CSV_CURL_ARGV)
|
45
|
+
|
46
|
+
def failed(msg, errno = 1)
|
47
|
+
$stderr.puts msg
|
48
|
+
if errno == 1
|
49
|
+
puts ""
|
50
|
+
puts OPTPARSE
|
51
|
+
end
|
52
|
+
exit errno
|
53
|
+
end
|
33
54
|
|
34
|
-
|
35
|
-
|
55
|
+
failed('no csv input file specified') unless options[:csv_file]
|
56
|
+
failed("csv input file #{options[:csv_file]} not found") unless File.exist?(options[:csv_file])
|
36
57
|
|
37
|
-
|
58
|
+
failed("template file #{options[:template_file]} not found") if options[:template_file] && !File.exist?(options[:template_file])
|
38
59
|
|
39
60
|
template = options[:template_file] ? File.read(options[:template_file]) : nil
|
40
61
|
input = CSV.open(options[:csv_file])
|
@@ -44,18 +65,20 @@ required_replacements = ARGV.map do |arg|
|
|
44
65
|
arg.scan(/\{\{(.*?)\}\}/)
|
45
66
|
end
|
46
67
|
|
47
|
-
required_replacements += options[:
|
68
|
+
required_replacements += options[:exec].scan(/\{\{(.*?)\}\}/) if options[:exec]
|
48
69
|
required_replacements += template.scan(/\{\{(.*?)\}\}/) if template
|
49
70
|
required_replacements.flatten!
|
50
71
|
required_replacements.map! { |v| v.split(':', 2).last }
|
51
72
|
required_replacements.uniq!
|
52
73
|
|
53
74
|
missing_replacements = required_replacements - input_headers
|
54
|
-
|
75
|
+
failed("missing replacement values for #{missing_replacements.join(', ')}", 2) unless missing_replacements.empty?
|
55
76
|
|
56
77
|
TMP_REQUEST_BODY_FILE = 'csv-utils.request'
|
57
78
|
|
58
79
|
def format_value(value, format)
|
80
|
+
return '' unless value
|
81
|
+
|
59
82
|
case format
|
60
83
|
when 'json'
|
61
84
|
value = value.to_json
|
@@ -67,6 +90,8 @@ def format_value(value, format)
|
|
67
90
|
CGI.escape(value)
|
68
91
|
when 'base64'
|
69
92
|
Base64.strict_encode64(value)
|
93
|
+
when 'urlsafe64'
|
94
|
+
Base64.urlsafe_encode64(value)
|
70
95
|
when 'hex'
|
71
96
|
value.unpack('H*').first
|
72
97
|
when 'shellword',
|
@@ -92,7 +117,7 @@ end
|
|
92
117
|
|
93
118
|
def run_command_safely(cmd)
|
94
119
|
res = `#{cmd}`
|
95
|
-
|
120
|
+
failed("failed to run command: #{cmd}", 2) unless $?.success?
|
96
121
|
res
|
97
122
|
end
|
98
123
|
|
@@ -104,9 +129,9 @@ def build_curl_command(curl_args, data, request_file, response_file)
|
|
104
129
|
cmd
|
105
130
|
end
|
106
131
|
|
107
|
-
def
|
132
|
+
def build_exec_command(exec, data, response_file)
|
108
133
|
cmd = "cat #{response_file} | "
|
109
|
-
cmd += generate_string(
|
134
|
+
cmd += generate_string(exec, data)
|
110
135
|
cmd
|
111
136
|
end
|
112
137
|
|
@@ -128,12 +153,16 @@ while (row = input.shift)
|
|
128
153
|
run_command_safely(cmd)
|
129
154
|
|
130
155
|
output =
|
131
|
-
if options[:
|
132
|
-
cmd =
|
156
|
+
if options[:exec]
|
157
|
+
cmd = build_exec_command(options[:exec], data, response_file)
|
133
158
|
run_command_safely(cmd)
|
134
159
|
else
|
135
160
|
File.read(response_file)
|
136
161
|
end
|
137
162
|
|
138
163
|
puts output
|
164
|
+
|
165
|
+
File.unlink(response_file) if File.exist?(response_file)
|
139
166
|
end
|
167
|
+
|
168
|
+
File.unlink(TMP_REQUEST_BODY_FILE) if File.exist?(TMP_REQUEST_BODY_FILE)
|
data/csv-curl.gemspec
CHANGED
@@ -2,14 +2,14 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'csv-curl'
|
5
|
-
s.version = '0.
|
5
|
+
s.version = '0.2.0'
|
6
6
|
s.licenses = ['MIT']
|
7
7
|
s.summary = 'CSV Curl'
|
8
8
|
s.description = 'Tools making mulitple calls using curl'
|
9
9
|
s.authors = ['Doug Youch']
|
10
10
|
s.email = 'dougyouch@gmail.com'
|
11
11
|
s.homepage = 'https://github.com/dougyouch/csv-curl'
|
12
|
-
s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
12
|
+
s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|examples)/}) }
|
13
13
|
s.bindir = 'bin'
|
14
14
|
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
15
15
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: csv-curl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Doug Youch
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-08-
|
11
|
+
date: 2019-08-23 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Tools making mulitple calls using curl
|
14
14
|
email: dougyouch@gmail.com
|