kronk 1.0.3 → 1.1.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.
@@ -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.txt
2
+ History.rdoc
3
3
  Manifest.txt
4
- README.txt
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/http'
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.3'
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 if 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
- # If the second argument is omitted or is passed :cache, will
155
- # attempt to compare with the last made request. If there was no last
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=:cache, options={}
171
- diff =
172
- if options[:raw]
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
- diff
269
+ Diff.new str1, str2
179
270
  end
180
271
 
181
272
 
182
273
  ##
183
- # Return a diff object from two responses' raw data.
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
- resp1 = Request.retrieve query1, opts1
190
- resp2 = Request.retrieve query2, opts2
277
+ def self.retrieve_data_string query, options={}
278
+ options = options.merge options_for_uri(query)
191
279
 
192
- Diff.new resp1.selective_string(opts1), resp2.selective_string(opts2)
193
- end
280
+ resp = Request.retrieve query, options
194
281
 
195
-
196
- ##
197
- # Return a diff object from two parsed responses.
198
-
199
- def self.data_diff query1, query2, options={}
200
- opts1 = options.merge options_for_uri(query1)
201
- opts2 = options.merge options_for_uri(query2)
202
-
203
- resp1 = Request.retrieve query1, opts1
204
- resp2 = Request.retrieve query2, opts2
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
- config[:requires].concat options[:requires] if options[:requires]
231
- load_requires
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
- options = options.merge options_for_uri(uri1)
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
- :with_headers => false,
278
- :no_body => false,
279
- :uris => []
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('-d', '--data STR', String,
312
- 'Post data with the request') do |value|
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('--suff STR', String,
324
- 'Add common path items to the end of each URI') do |value|
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('-H', '--header STR', String,
330
- 'Header to pass to the server request') do |value|
331
- options[:headers] ||= {}
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('-L', '--location [NUM]', Integer,
367
- 'Follow the location header always or num times') do |value|
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('-X', '--request STR', String,
373
- 'The request method to use') do |value|
374
- options[:http_method] = value
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('-r', '--require lib1,lib2', Array,
379
- 'Require a library or gem') do |value|
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('--ascii', 'Return ascii formatted diff') do
396
- config[:diff_format] = :ascii_diff
469
+ opt.on('-V', '--verbose', 'Make the operation more talkative') do
470
+ config[:verbose] = true
397
471
  end
398
472
 
399
473
 
400
- opt.on('--color', 'Return color formatted diff') do
401
- config[:diff_format] = :color_diff
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('--format STR', String,
406
- 'Use a custom diff formatter') do |value|
407
- config[:diff_format] = value
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('--lines', 'Show line numbers') do
412
- config[:show_lines] = true
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('--parser STR', String,
417
- 'Override default parser') do |value|
418
- options[:parser] = value
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('-V', '--verbose', 'Make the operation more talkative') do
423
- config[:verbose] = true
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