kronk 1.0.3 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/{History.txt → History.rdoc} +22 -0
- data/Manifest.txt +14 -2
- data/README.rdoc +258 -0
- data/Rakefile +4 -0
- data/lib/kronk.rb +239 -102
- data/lib/kronk/diff.rb +2 -2
- data/lib/kronk/request.rb +146 -20
- data/lib/kronk/xml_parser.rb +1 -1
- data/test/mocks/200_response.json +28 -0
- data/test/mocks/200_response.plist +97 -0
- data/test/mocks/200_response.txt +23 -0
- data/test/mocks/200_response.xml +58 -0
- data/test/mocks/301_response.txt +16 -0
- data/test/mocks/302_response.txt +17 -0
- data/test/test_kronk.rb +142 -32
- data/test/test_request.rb +319 -12
- metadata +36 -20
- data/README.txt +0 -122
@@ -1,3 +1,25 @@
|
|
1
|
+
=== 1.1.0 / 2010-12-12
|
2
|
+
|
3
|
+
* Enhancements:
|
4
|
+
|
5
|
+
* Support for http ssl, proxy, and basic auth.
|
6
|
+
|
7
|
+
* Support for cookies and sessions.
|
8
|
+
|
9
|
+
* URL queries can now be set from the command line or the config file.
|
10
|
+
|
11
|
+
* Support for piping to the kronk bin.
|
12
|
+
|
13
|
+
* Support for customizing User-Agent and added user agent aliases.
|
14
|
+
|
15
|
+
* Bugfixes:
|
16
|
+
|
17
|
+
* No longer need to explicitely specify raw mode for content types
|
18
|
+
with no parsers.
|
19
|
+
|
20
|
+
* Updated how --prev option does cache retrieval, so cache is always
|
21
|
+
the left side of the diff.
|
22
|
+
|
1
23
|
=== 1.0.3 / 2010-12-09
|
2
24
|
|
3
25
|
* Enhancements:
|
data/Manifest.txt
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
.autotest
|
2
|
-
History.
|
2
|
+
History.rdoc
|
3
3
|
Manifest.txt
|
4
|
-
README.
|
4
|
+
README.rdoc
|
5
5
|
Rakefile
|
6
6
|
bin/kronk
|
7
7
|
lib/kronk.rb
|
@@ -11,4 +11,16 @@ lib/kronk/plist_parser.rb
|
|
11
11
|
lib/kronk/request.rb
|
12
12
|
lib/kronk/response.rb
|
13
13
|
lib/kronk/xml_parser.rb
|
14
|
+
test/mocks/200_response.json
|
15
|
+
test/mocks/200_response.plist
|
16
|
+
test/mocks/200_response.txt
|
17
|
+
test/mocks/200_response.xml
|
18
|
+
test/mocks/301_response.txt
|
19
|
+
test/mocks/302_response.txt
|
20
|
+
test/test_data_set.rb
|
21
|
+
test/test_diff.rb
|
22
|
+
test/test_helper.rb
|
14
23
|
test/test_kronk.rb
|
24
|
+
test/test_request.rb
|
25
|
+
test/test_response.rb
|
26
|
+
test/test_xml_parser.rb
|
data/README.rdoc
ADDED
@@ -0,0 +1,258 @@
|
|
1
|
+
= Kronk
|
2
|
+
|
3
|
+
* https://github.com/yaksnrainbows/kronk
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
Kronk runs diffs against data from live and cached http responses.
|
8
|
+
Kronk was made possible by the sponsoring of AT&T Interactive.
|
9
|
+
|
10
|
+
== FEATURES:
|
11
|
+
|
12
|
+
* Parse and display or diff data from http response body and/or headers.
|
13
|
+
|
14
|
+
* Follow redirects automatically.
|
15
|
+
|
16
|
+
* Include or exclude specific data points with file-glob-like paths.
|
17
|
+
|
18
|
+
* Supports json, rails-ish xml, and plist.
|
19
|
+
|
20
|
+
* Support for custom data parsers and diff formatters.
|
21
|
+
|
22
|
+
* Support for proxies, ssl, and basic auth.
|
23
|
+
|
24
|
+
* Cookie/session handling.
|
25
|
+
|
26
|
+
* Easy-to-read output (color or ascii, line numbers, etc).
|
27
|
+
|
28
|
+
== FUTURE:
|
29
|
+
|
30
|
+
* Auto-queryer with optional param randomizing.
|
31
|
+
|
32
|
+
* Support for test suites.
|
33
|
+
|
34
|
+
== SYNOPSIS:
|
35
|
+
|
36
|
+
Check if your json response returns the same data as your xml variety:
|
37
|
+
|
38
|
+
$ kronk http://host.com/path.json http://host.com/path.xml
|
39
|
+
|
40
|
+
Compare body structure only (uses datatypes instead of values):
|
41
|
+
|
42
|
+
$ kronk http://host.com/path.json http://host.com/path.xml --struct
|
43
|
+
|
44
|
+
Call comparison with similar uri suffixes:
|
45
|
+
|
46
|
+
$ kronk http://host.com/path.json http://host.com/path.xml --suff '?page=1'
|
47
|
+
|
48
|
+
Compare response with the previous call:
|
49
|
+
|
50
|
+
$ kronk http://host.com/path --prev
|
51
|
+
|
52
|
+
Compare response with a local file:
|
53
|
+
|
54
|
+
$ kronk http://host.com/path.json ./saved_response.json
|
55
|
+
|
56
|
+
Do a simple text diff on the http response, including headers:
|
57
|
+
|
58
|
+
$ kronk http://host.com/A/path.json http://host.com/B/path.json --raw -i
|
59
|
+
|
60
|
+
Run it to display formatted data:
|
61
|
+
|
62
|
+
$ kronk http://host.com/path.json
|
63
|
+
|
64
|
+
Run it to display raw data with headers:
|
65
|
+
|
66
|
+
$ kronk http://host.com/path.json --raw -i
|
67
|
+
|
68
|
+
== CONFIGURATION:
|
69
|
+
|
70
|
+
Kronk pulls it's config from $HOME/.kronk and supports the following:
|
71
|
+
|
72
|
+
Set the file to save the last http response retrieved in:
|
73
|
+
|
74
|
+
:cache_file: ~/.kronk_cache
|
75
|
+
|
76
|
+
Content types to match to a parser. Keys are used as a part of
|
77
|
+
a regexp and values are evaluated by const_get.
|
78
|
+
|
79
|
+
:content_types:
|
80
|
+
xml: XMLParser
|
81
|
+
plist: PlistParser
|
82
|
+
json: JSON
|
83
|
+
|
84
|
+
How to format the diff output. Supports the "special" values
|
85
|
+
:ascii_diff and :color_diff or any string that will correctly
|
86
|
+
resolve to a constant:
|
87
|
+
|
88
|
+
:diff_format: :ascii_diff
|
89
|
+
|
90
|
+
Adding User-Agent aliases is useful and simple!
|
91
|
+
|
92
|
+
:user_agents:
|
93
|
+
win_ie9: Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.0)
|
94
|
+
|
95
|
+
Disabling cookies altogether may be done as so:
|
96
|
+
|
97
|
+
:use_cookies: false
|
98
|
+
|
99
|
+
Setting URI-specific config options - useful if you always need to send
|
100
|
+
headers or use one-off configs. Each URI option key is dropped in a regexp
|
101
|
+
to match against the given URIs so this also works for local files.
|
102
|
+
See Kronk::Request.retrieve and Kronk::Response#selective_data
|
103
|
+
for all options supported:
|
104
|
+
|
105
|
+
:uri_options:
|
106
|
+
example.com:
|
107
|
+
:parser: XMLParser
|
108
|
+
:http_method: POST
|
109
|
+
|
110
|
+
:follow_redirects: true
|
111
|
+
|
112
|
+
:ignore_data:
|
113
|
+
- path/to/data/point
|
114
|
+
|
115
|
+
:headers:
|
116
|
+
X-Something: custom header value
|
117
|
+
|
118
|
+
:query:
|
119
|
+
offset: 1
|
120
|
+
limit: 10
|
121
|
+
|
122
|
+
Require specific files or gems in the ruby runtime:
|
123
|
+
|
124
|
+
:requires:
|
125
|
+
- kronk-my_custom_parser
|
126
|
+
- kronk-my_custom_diff_formatter
|
127
|
+
|
128
|
+
Show line numbers in the output:
|
129
|
+
|
130
|
+
:show_lines: true
|
131
|
+
|
132
|
+
== DATA TRAVERSING:
|
133
|
+
|
134
|
+
One of Kronk's most powerful features is its ability to segregate data.
|
135
|
+
From the command line, this is done by passing data paths after '--':
|
136
|
+
|
137
|
+
$ kronk http://host.com -- data/path1 data/path2/1/child
|
138
|
+
|
139
|
+
The previous example will narrow down the parsed data returned to
|
140
|
+
something like:
|
141
|
+
|
142
|
+
{
|
143
|
+
"data" => {
|
144
|
+
"path1" => "value1",
|
145
|
+
"path2" => [
|
146
|
+
nil,
|
147
|
+
{
|
148
|
+
"child" => "child value"
|
149
|
+
},
|
150
|
+
nil,
|
151
|
+
nil
|
152
|
+
]
|
153
|
+
}
|
154
|
+
}
|
155
|
+
|
156
|
+
If excluding data points is preferred, prepending a '-' to the path will
|
157
|
+
flag it to remove data:
|
158
|
+
|
159
|
+
$ kronk http://host.com -- -data/path2
|
160
|
+
|
161
|
+
{
|
162
|
+
"data" => {
|
163
|
+
"path1" => "value1",
|
164
|
+
"path3" => "value3",
|
165
|
+
"path4" => "value4"
|
166
|
+
}
|
167
|
+
}
|
168
|
+
|
169
|
+
If you would like to exclude or include only items with a specific child
|
170
|
+
attribute, you can do so by prepending the path with a ':'.
|
171
|
+
Both ':' and '-' can be combined as ':-'.
|
172
|
+
|
173
|
+
$ kronk http://host.com -- :data/path2/1/child
|
174
|
+
|
175
|
+
{
|
176
|
+
"data" => {
|
177
|
+
"path2" => [
|
178
|
+
nil,
|
179
|
+
{
|
180
|
+
"first_child" => "first value",
|
181
|
+
"child" => "child value",
|
182
|
+
"last_child" => "last value"
|
183
|
+
},
|
184
|
+
nil,
|
185
|
+
nil
|
186
|
+
]
|
187
|
+
}
|
188
|
+
}
|
189
|
+
|
190
|
+
There are additionally a variety of wildcard and special characters that
|
191
|
+
are supported:
|
192
|
+
|
193
|
+
* \* matches /.*/, meaning zero or more characters
|
194
|
+
|
195
|
+
* \*\*/ matches any key recursively down the data structure
|
196
|
+
|
197
|
+
* ? matches zero or one character
|
198
|
+
|
199
|
+
* | effectively works as an "OR" character, matches /^val1|val2$/
|
200
|
+
|
201
|
+
* = is used to match values and may be used in conjuction with a key or not.
|
202
|
+
|
203
|
+
* Parentheses are ok to use if in conjunction with other special characters
|
204
|
+
for a given path item, such as: /path(1|2)
|
205
|
+
|
206
|
+
Check out Kronk::DataSet for more details on data traversing.
|
207
|
+
|
208
|
+
Note: Bash may try to parse your data paths, especially if they start with
|
209
|
+
wildcards or if they contain the pipe "|" character, so you may need to put
|
210
|
+
single quotes around some of your paths.
|
211
|
+
|
212
|
+
== REQUIREMENTS:
|
213
|
+
|
214
|
+
* activesupport gem
|
215
|
+
|
216
|
+
* nokogiri gem
|
217
|
+
|
218
|
+
* plist gem
|
219
|
+
|
220
|
+
* json gem
|
221
|
+
|
222
|
+
== INSTALL:
|
223
|
+
|
224
|
+
$ sudo gem install kronk
|
225
|
+
|
226
|
+
== DEVELOPERS:
|
227
|
+
|
228
|
+
After checking out the source, run:
|
229
|
+
|
230
|
+
$ rake newb
|
231
|
+
|
232
|
+
This task will install any missing dependencies, run the tests/specs,
|
233
|
+
and generate the RDoc.
|
234
|
+
|
235
|
+
== LICENSE:
|
236
|
+
|
237
|
+
(The MIT License)
|
238
|
+
|
239
|
+
Copyright (c) 2010 Jeremie Castagna
|
240
|
+
|
241
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
242
|
+
a copy of this software and associated documentation files (the
|
243
|
+
'Software'), to deal in the Software without restriction, including
|
244
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
245
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
246
|
+
permit persons to whom the Software is furnished to do so, subject to
|
247
|
+
the following conditions:
|
248
|
+
|
249
|
+
The above copyright notice and this permission notice shall be
|
250
|
+
included in all copies or substantial portions of the Software.
|
251
|
+
|
252
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
253
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
254
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
255
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
256
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
257
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
258
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
CHANGED
@@ -7,12 +7,16 @@ Hoe.plugin :isolate
|
|
7
7
|
|
8
8
|
Hoe.spec 'kronk' do
|
9
9
|
developer('Jeremie Castagna', 'yaksnrainbows@gmail.com')
|
10
|
+
self.readme_file = "README.rdoc"
|
11
|
+
self.history_file = "History.rdoc"
|
12
|
+
self.extra_rdoc_files = FileList['*.rdoc']
|
10
13
|
|
11
14
|
self.extra_deps << ['plist', '~>3.1.0']
|
12
15
|
self.extra_deps << ['json', '~>1.2']
|
13
16
|
self.extra_deps << ['nokogiri', '~>1.3']
|
14
17
|
self.extra_deps << ['i18n', '~>0.5']
|
15
18
|
self.extra_deps << ['activesupport', '>=2.0.0']
|
19
|
+
self.extra_deps << ['cookiejar', '~>0.3.0']
|
16
20
|
|
17
21
|
self.extra_dev_deps << ['mocha', '~>0.9.10']
|
18
22
|
end
|
data/lib/kronk.rb
CHANGED
@@ -2,22 +2,24 @@ require 'rubygems'
|
|
2
2
|
require 'plist'
|
3
3
|
require 'json'
|
4
4
|
require 'nokogiri'
|
5
|
+
require 'cookiejar'
|
5
6
|
|
6
7
|
# Support for new and old versions of ActiveSupport
|
7
8
|
begin
|
8
9
|
require 'active_support/inflector'
|
9
|
-
rescue LoadError
|
10
|
+
rescue LoadError => e
|
11
|
+
raise unless e.message =~ /-- active_support/
|
10
12
|
require 'activesupport'
|
11
13
|
end
|
12
14
|
|
13
|
-
require 'net/
|
15
|
+
require 'net/https'
|
14
16
|
require 'optparse'
|
15
17
|
require 'yaml'
|
16
18
|
|
17
19
|
class Kronk
|
18
20
|
|
19
21
|
# This gem's version.
|
20
|
-
VERSION = '1.0
|
22
|
+
VERSION = '1.1.0'
|
21
23
|
|
22
24
|
|
23
25
|
require 'kronk/data_set'
|
@@ -36,6 +38,10 @@ class Kronk
|
|
36
38
|
DEFAULT_CACHE_FILE = File.expand_path "~/.kronk_cache"
|
37
39
|
|
38
40
|
|
41
|
+
# Default cookies file.
|
42
|
+
DEFAULT_COOKIES_FILE = File.expand_path "~/.kronk_cookies"
|
43
|
+
|
44
|
+
|
39
45
|
# Default Content-Type header to parser mapping.
|
40
46
|
DEFAULT_CONTENT_TYPES = {
|
41
47
|
'js' => 'JSON',
|
@@ -45,14 +51,44 @@ class Kronk
|
|
45
51
|
}
|
46
52
|
|
47
53
|
|
54
|
+
# Aliases for various user-agents. Thanks Mechanize! :)
|
55
|
+
USER_AGENTS = {
|
56
|
+
'kronk' =>
|
57
|
+
"Kronk/#{VERSION} (http://github.com/yaksnrainbows/kronk)",
|
58
|
+
'iphone' =>
|
59
|
+
"Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1C28 Safari/419.3",
|
60
|
+
'linux_firefox' =>
|
61
|
+
"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.1) Gecko/20100122 firefox/3.6.1",
|
62
|
+
'linux_mozilla' =>
|
63
|
+
"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030624",
|
64
|
+
'mac_mozilla' =>
|
65
|
+
"Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.4a) Gecko/20030401",
|
66
|
+
'linux_konqueror' =>
|
67
|
+
"Mozilla/5.0 (compatible; Konqueror/3; Linux)",
|
68
|
+
'mac_firefox' =>
|
69
|
+
"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6",
|
70
|
+
'mac_safari' =>
|
71
|
+
"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_2; de-at) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10",
|
72
|
+
'win_ie6' =>
|
73
|
+
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
|
74
|
+
'win_ie7' =>
|
75
|
+
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
|
76
|
+
'win_mozilla' =>
|
77
|
+
"Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4b) Gecko/20030516 Mozilla Firebird/0.6"
|
78
|
+
}
|
79
|
+
|
80
|
+
|
48
81
|
# Default config to use.
|
49
82
|
DEFAULT_CONFIG = {
|
50
83
|
:content_types => DEFAULT_CONTENT_TYPES.dup,
|
51
84
|
:diff_format => :ascii_diff,
|
52
85
|
:show_lines => false,
|
53
86
|
:cache_file => DEFAULT_CACHE_FILE,
|
87
|
+
:cookies_file => DEFAULT_COOKIES_FILE,
|
88
|
+
:use_cookies => true,
|
54
89
|
:requires => [],
|
55
|
-
:uri_options => {}
|
90
|
+
:uri_options => {},
|
91
|
+
:user_agents => USER_AGENTS.dup
|
56
92
|
}
|
57
93
|
|
58
94
|
|
@@ -71,6 +107,7 @@ class Kronk
|
|
71
107
|
conf = YAML.load_file DEFAULT_CONFIG_FILE
|
72
108
|
content_types = conf.delete :content_types
|
73
109
|
uri_options = conf.delete :uri_options
|
110
|
+
user_agents = conf.delete :user_agents
|
74
111
|
|
75
112
|
if conf[:requires]
|
76
113
|
requires = [*conf.delete(:requires)]
|
@@ -78,9 +115,10 @@ class Kronk
|
|
78
115
|
self.config[:requires].concat requires
|
79
116
|
end
|
80
117
|
|
81
|
-
self.config[:uri_options].merge! uri_options
|
118
|
+
self.config[:uri_options].merge! uri_options if uri_options
|
119
|
+
self.config[:content_types].merge! content_types if content_types
|
120
|
+
self.config[:user_agents].merge! user_agents if user_agents
|
82
121
|
|
83
|
-
self.config[:content_types].merge!(content_types) if content_types
|
84
122
|
self.config.merge! conf
|
85
123
|
end
|
86
124
|
|
@@ -88,9 +126,9 @@ class Kronk
|
|
88
126
|
##
|
89
127
|
# Load the config-based requires.
|
90
128
|
|
91
|
-
def self.load_requires
|
92
|
-
return unless config[:requires]
|
93
|
-
config[:requires].each{|lib| require lib }
|
129
|
+
def self.load_requires more_requires=nil
|
130
|
+
return unless config[:requires] || more_requires
|
131
|
+
(config[:requires] | more_requires.to_a).each{|lib| require lib }
|
94
132
|
end
|
95
133
|
|
96
134
|
|
@@ -149,16 +187,73 @@ class Kronk
|
|
149
187
|
end
|
150
188
|
|
151
189
|
|
190
|
+
##
|
191
|
+
# Ask the user for a password from stdinthe command line.
|
192
|
+
|
193
|
+
def self.query_password str=nil
|
194
|
+
$stderr << "#{(str || "Password:")} "
|
195
|
+
system "stty -echo"
|
196
|
+
password = $stdin.gets.chomp
|
197
|
+
ensure
|
198
|
+
system "stty echo"
|
199
|
+
$stderr << "\n"
|
200
|
+
password
|
201
|
+
end
|
202
|
+
|
203
|
+
|
204
|
+
##
|
205
|
+
# Load the saved cookies file.
|
206
|
+
|
207
|
+
def self.load_cookie_jar file=nil
|
208
|
+
file ||= config[:cookies_file]
|
209
|
+
@cookie_jar = YAML.load_file file if File.file? file
|
210
|
+
@cookie_jar ||= CookieJar::Jar.new
|
211
|
+
@cookie_jar.expire_cookies
|
212
|
+
@cookie_jar
|
213
|
+
end
|
214
|
+
|
215
|
+
|
216
|
+
##
|
217
|
+
# Save the cookie jar to file.
|
218
|
+
|
219
|
+
def self.save_cookie_jar file=nil
|
220
|
+
file ||= config[:cookies_file]
|
221
|
+
File.open(file, "w") do |file|
|
222
|
+
file.write @cookie_jar.to_yaml
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
|
227
|
+
##
|
228
|
+
# Deletes all cookies from the runtime.
|
229
|
+
# If Kronk.run is in use, will write the change to the cookies file as well.
|
230
|
+
|
231
|
+
def self.clear_cookies!
|
232
|
+
@cookie_jar = CookieJar::Jar.new
|
233
|
+
end
|
234
|
+
|
235
|
+
|
236
|
+
##
|
237
|
+
# Returns the kronk cookie jar.
|
238
|
+
|
239
|
+
def self.cookie_jar
|
240
|
+
@cookie_jar ||= load_cookie_jar
|
241
|
+
end
|
242
|
+
|
243
|
+
|
152
244
|
##
|
153
245
|
# Make requests, parse the responses and compare the data.
|
154
|
-
#
|
155
|
-
#
|
156
|
-
# request will compare against nil.
|
246
|
+
# Query arguments may be set to the special value :cache to use the
|
247
|
+
# last live http response retrieved.
|
157
248
|
#
|
158
249
|
# Supports the following options:
|
159
250
|
# :data:: Hash/String - the data to pass to the http request
|
251
|
+
# :query:: Hash/String - the data to append to the http request path
|
160
252
|
# :headers:: Hash - extra headers to pass to the request
|
161
253
|
# :http_method:: Symbol - the http method to use; defaults to :get
|
254
|
+
# :user_agent:: String - user agent string or alias; defaults to 'kronk'
|
255
|
+
# :auth:: Hash - must contain :username and :password; defaults to nil
|
256
|
+
# :proxy:: Hash/String - http proxy to use; defaults to nil
|
162
257
|
# :only_data:: String/Array - extracts the data from given data paths
|
163
258
|
# :ignore_data:: String/Array - defines which data points to exclude
|
164
259
|
# :with_headers:: Bool/String/Array - defines which headers to include
|
@@ -167,45 +262,34 @@ class Kronk
|
|
167
262
|
#
|
168
263
|
# Returns a diff object.
|
169
264
|
|
170
|
-
def self.compare query1, query2
|
171
|
-
|
172
|
-
|
173
|
-
raw_diff query1, query2, options
|
174
|
-
else
|
175
|
-
data_diff query1, query2, options
|
176
|
-
end
|
265
|
+
def self.compare query1, query2, options={}
|
266
|
+
str1 = retrieve_data_string query1, options
|
267
|
+
str2 = retrieve_data_string query2, options
|
177
268
|
|
178
|
-
|
269
|
+
Diff.new str1, str2
|
179
270
|
end
|
180
271
|
|
181
272
|
|
182
273
|
##
|
183
|
-
# Return a
|
184
|
-
|
185
|
-
def self.raw_diff query1, query2, options={}
|
186
|
-
opts1 = options.merge options_for_uri(query1)
|
187
|
-
opts2 = options.merge options_for_uri(query2)
|
274
|
+
# Return a data string, parsed or raw.
|
275
|
+
# See Kronk.compare for supported options.
|
188
276
|
|
189
|
-
|
190
|
-
|
277
|
+
def self.retrieve_data_string query, options={}
|
278
|
+
options = options.merge options_for_uri(query)
|
191
279
|
|
192
|
-
|
193
|
-
end
|
280
|
+
resp = Request.retrieve query, options
|
194
281
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
Diff.new_from_data resp1.selective_data(opts1),
|
207
|
-
resp2.selective_data(opts2),
|
208
|
-
options
|
282
|
+
if options[:raw]
|
283
|
+
resp.selective_string options
|
284
|
+
else
|
285
|
+
begin
|
286
|
+
data = resp.selective_data options
|
287
|
+
Diff.ordered_data_string data, options[:struct]
|
288
|
+
rescue Response::MissingParser
|
289
|
+
verbose "Warning: No parser for #{resp['Content-Type']} [#{query}]"
|
290
|
+
resp.selective_string options
|
291
|
+
end
|
292
|
+
end
|
209
293
|
end
|
210
294
|
|
211
295
|
|
@@ -225,10 +309,15 @@ class Kronk
|
|
225
309
|
exit 1
|
226
310
|
end
|
227
311
|
|
312
|
+
load_cookie_jar
|
313
|
+
|
228
314
|
options = parse_args argv
|
229
315
|
|
230
|
-
|
231
|
-
|
316
|
+
load_requires options[:requires]
|
317
|
+
|
318
|
+
at_exit do
|
319
|
+
save_cookie_jar
|
320
|
+
end
|
232
321
|
|
233
322
|
options[:cache_response] = config[:cache_file] if config[:cache_file]
|
234
323
|
|
@@ -239,19 +328,9 @@ class Kronk
|
|
239
328
|
puts diff.formatted
|
240
329
|
verbose "\n\nFound #{diff.count} diff(s).\n"
|
241
330
|
|
242
|
-
elsif options[:raw]
|
243
|
-
options = options.merge options_for_uri(uri1)
|
244
|
-
|
245
|
-
out = Request.retrieve(uri1, options).selective_string options
|
246
|
-
out = Diff.insert_line_nums out if config[:show_lines]
|
247
|
-
puts out
|
248
|
-
|
249
331
|
else
|
250
|
-
|
251
|
-
|
252
|
-
data = Request.retrieve(uri1, options).selective_data options
|
253
|
-
out = Diff.ordered_data_string data, options[:struct]
|
254
|
-
out = Diff.insert_line_nums out if config[:show_lines]
|
332
|
+
out = retrieve_data_string uri1, options
|
333
|
+
out = Diff.insert_line_nums out if config[:show_lines]
|
255
334
|
puts out
|
256
335
|
end
|
257
336
|
|
@@ -274,9 +353,11 @@ class Kronk
|
|
274
353
|
|
275
354
|
def self.parse_args argv
|
276
355
|
options = {
|
277
|
-
:
|
278
|
-
:no_body
|
279
|
-
:
|
356
|
+
:auth => {},
|
357
|
+
:no_body => false,
|
358
|
+
:proxy => {},
|
359
|
+
:uris => [],
|
360
|
+
:with_headers => false
|
280
361
|
}
|
281
362
|
|
282
363
|
options = parse_data_path_args options, argv
|
@@ -308,30 +389,19 @@ Kronk runs diffs against data from live and cached http responses.
|
|
308
389
|
Options:
|
309
390
|
STR
|
310
391
|
|
311
|
-
opt.on('
|
312
|
-
|
313
|
-
options[:data] = value
|
314
|
-
options[:http_method] ||= 'POST'
|
315
|
-
end
|
316
|
-
|
317
|
-
|
318
|
-
opt.on('--prev', 'Use last response to diff against') do
|
319
|
-
options[:uris] << :cache
|
392
|
+
opt.on('--ascii', 'Return ascii formatted diff') do
|
393
|
+
config[:diff_format] = :ascii_diff
|
320
394
|
end
|
321
395
|
|
322
396
|
|
323
|
-
opt.on('--
|
324
|
-
|
325
|
-
options[:uri_suffix] = value
|
397
|
+
opt.on('--color', 'Return color formatted diff') do
|
398
|
+
config[:diff_format] = :color_diff
|
326
399
|
end
|
327
400
|
|
328
401
|
|
329
|
-
opt.on('
|
330
|
-
'
|
331
|
-
|
332
|
-
|
333
|
-
key, value = value.split ": ", 2
|
334
|
-
options[:headers][key] = value
|
402
|
+
opt.on('--format STR', String,
|
403
|
+
'Use a custom diff formatter') do |value|
|
404
|
+
config[:diff_format] = value
|
335
405
|
end
|
336
406
|
|
337
407
|
|
@@ -363,22 +433,19 @@ Kronk runs diffs against data from live and cached http responses.
|
|
363
433
|
end
|
364
434
|
|
365
435
|
|
366
|
-
opt.on('
|
367
|
-
|
368
|
-
options[:follow_redirects] = value || true
|
436
|
+
opt.on('--lines', 'Show line numbers') do
|
437
|
+
config[:show_lines] = true
|
369
438
|
end
|
370
439
|
|
371
440
|
|
372
|
-
opt.on('
|
373
|
-
'
|
374
|
-
options[:
|
441
|
+
opt.on('--parser STR', String,
|
442
|
+
'Override default parser') do |value|
|
443
|
+
options[:parser] = value
|
375
444
|
end
|
376
445
|
|
377
446
|
|
378
|
-
opt.on('
|
379
|
-
|
380
|
-
options[:requires] ||= []
|
381
|
-
options[:requires].concat value
|
447
|
+
opt.on('--prev', 'Use last response to diff against') do
|
448
|
+
options[:uris].unshift :cache
|
382
449
|
end
|
383
450
|
|
384
451
|
|
@@ -387,40 +454,105 @@ Kronk runs diffs against data from live and cached http responses.
|
|
387
454
|
end
|
388
455
|
|
389
456
|
|
457
|
+
opt.on('-r', '--require lib1,lib2', Array,
|
458
|
+
'Require a library or gem') do |value|
|
459
|
+
options[:requires] ||= []
|
460
|
+
options[:requires].concat value
|
461
|
+
end
|
462
|
+
|
463
|
+
|
390
464
|
opt.on('--struct', 'Run diff on the data structure') do
|
391
465
|
options[:struct] = true
|
392
466
|
end
|
393
467
|
|
394
468
|
|
395
|
-
opt.on('--
|
396
|
-
config[:
|
469
|
+
opt.on('-V', '--verbose', 'Make the operation more talkative') do
|
470
|
+
config[:verbose] = true
|
397
471
|
end
|
398
472
|
|
399
473
|
|
400
|
-
opt.
|
401
|
-
|
474
|
+
opt.separator <<-STR
|
475
|
+
|
476
|
+
HTTP Options:
|
477
|
+
STR
|
478
|
+
|
479
|
+
opt.on('--clear-cookies', 'Delete all saved cookies') do
|
480
|
+
clear_cookies!
|
402
481
|
end
|
403
482
|
|
404
483
|
|
405
|
-
opt.on('--
|
406
|
-
'
|
407
|
-
|
484
|
+
opt.on('-d', '--data STR', String,
|
485
|
+
'Post data with the request') do |value|
|
486
|
+
options[:data] = value
|
487
|
+
options[:http_method] ||= 'POST'
|
408
488
|
end
|
409
489
|
|
410
490
|
|
411
|
-
opt.on('
|
412
|
-
|
491
|
+
opt.on('-H', '--header STR', String,
|
492
|
+
'Header to pass to the server request') do |value|
|
493
|
+
options[:headers] ||= {}
|
494
|
+
|
495
|
+
key, value = value.split ": ", 2
|
496
|
+
options[:headers][key] = value.strip
|
413
497
|
end
|
414
498
|
|
415
499
|
|
416
|
-
opt.on('--
|
417
|
-
'
|
418
|
-
options[:
|
500
|
+
opt.on('-A', '--user-agent STR', String,
|
501
|
+
'User-Agent to send to server or a valid alias') do |value|
|
502
|
+
options[:user_agent] = value
|
419
503
|
end
|
420
504
|
|
421
505
|
|
422
|
-
opt.on('-
|
423
|
-
|
506
|
+
opt.on('-L', '--location [NUM]', Integer,
|
507
|
+
'Follow the location header always or num times') do |value|
|
508
|
+
options[:follow_redirects] = value || true
|
509
|
+
end
|
510
|
+
|
511
|
+
|
512
|
+
opt.on('--no-cookies', 'Don\'t use cookies for this session') do
|
513
|
+
options[:no_cookies] = true
|
514
|
+
end
|
515
|
+
|
516
|
+
|
517
|
+
opt.on('-?', '--query STR', String,
|
518
|
+
'Append query to URLs') do |value|
|
519
|
+
options[:query] = value
|
520
|
+
end
|
521
|
+
|
522
|
+
|
523
|
+
opt.on('--suff STR', String,
|
524
|
+
'Add common path items to the end of each URL') do |value|
|
525
|
+
options[:uri_suffix] = value
|
526
|
+
end
|
527
|
+
|
528
|
+
|
529
|
+
opt.on('-U', '--proxy-user STR', String,
|
530
|
+
'Set proxy user and/or password: usr[:pass]') do |value|
|
531
|
+
options[:proxy][:username], options[:proxy][:password] =
|
532
|
+
value.split ":", 2
|
533
|
+
|
534
|
+
options[:proxy][:password] ||= query_password "Proxy password:"
|
535
|
+
end
|
536
|
+
|
537
|
+
|
538
|
+
opt.on('-u', '--user STR', String,
|
539
|
+
'Set server auth user and/or password: usr[:pass]') do |value|
|
540
|
+
options[:auth][:username], options[:auth][:password] =
|
541
|
+
value.split ":", 2
|
542
|
+
|
543
|
+
options[:auth][:password] ||= query_password "Server password:"
|
544
|
+
end
|
545
|
+
|
546
|
+
|
547
|
+
opt.on('-X', '--request STR', String,
|
548
|
+
'The request method to use') do |value|
|
549
|
+
options[:http_method] = value
|
550
|
+
end
|
551
|
+
|
552
|
+
|
553
|
+
opt.on('-x', '--proxy STR', String,
|
554
|
+
'Use HTTP proxy on given port: host[:port]') do |value|
|
555
|
+
options[:proxy][:address], options[:proxy][:port] = value.split ":", 2
|
424
556
|
end
|
425
557
|
|
426
558
|
opt.separator nil
|
@@ -428,6 +560,11 @@ Kronk runs diffs against data from live and cached http responses.
|
|
428
560
|
|
429
561
|
opts.parse! argv
|
430
562
|
|
563
|
+
unless $stdin.tty?
|
564
|
+
io = StringIO.new $stdin.read
|
565
|
+
options[:uris] << io
|
566
|
+
end
|
567
|
+
|
431
568
|
options[:uris].concat argv
|
432
569
|
options[:uris].slice!(2..-1)
|
433
570
|
|