kronk 1.0.3 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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