htty 1.0.0 → 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.
Files changed (92) hide show
  1. data/History.markdown +21 -0
  2. data/MIT-LICENSE.markdown +10 -0
  3. data/README.markdown +238 -0
  4. data/VERSION +1 -1
  5. data/bin/htty +1 -1
  6. data/{app → lib}/htty.rb +0 -2
  7. data/{app → lib}/htty/cli.rb +11 -4
  8. data/{app → lib}/htty/cli/command.rb +25 -3
  9. data/{app → lib}/htty/cli/commands.rb +0 -2
  10. data/{app → lib}/htty/cli/commands/address.rb +15 -9
  11. data/{app → lib}/htty/cli/commands/body_clear.rb +0 -2
  12. data/{app → lib}/htty/cli/commands/body_request.rb +1 -3
  13. data/{app → lib}/htty/cli/commands/body_response.rb +1 -3
  14. data/{app → lib}/htty/cli/commands/body_set.rb +9 -4
  15. data/{app → lib}/htty/cli/commands/body_unset.rb +1 -3
  16. data/{app → lib}/htty/cli/commands/cd.rb +0 -2
  17. data/{app → lib}/htty/cli/commands/cookie_add.rb +0 -2
  18. data/{app → lib}/htty/cli/commands/cookie_remove.rb +0 -2
  19. data/{app → lib}/htty/cli/commands/cookies.rb +9 -5
  20. data/{app → lib}/htty/cli/commands/cookies_add.rb +1 -3
  21. data/{app → lib}/htty/cli/commands/cookies_clear.rb +0 -2
  22. data/{app → lib}/htty/cli/commands/cookies_remove.rb +1 -3
  23. data/{app → lib}/htty/cli/commands/cookies_remove_all.rb +1 -3
  24. data/{app → lib}/htty/cli/commands/cookies_use.rb +11 -4
  25. data/{app → lib}/htty/cli/commands/delete.rb +0 -2
  26. data/{app → lib}/htty/cli/commands/exit.rb +0 -2
  27. data/{app → lib}/htty/cli/commands/follow.rb +6 -9
  28. data/{app → lib}/htty/cli/commands/form.rb +0 -2
  29. data/{app → lib}/htty/cli/commands/form_add.rb +0 -2
  30. data/{app → lib}/htty/cli/commands/form_clear.rb +0 -2
  31. data/{app → lib}/htty/cli/commands/form_remove.rb +0 -2
  32. data/{app → lib}/htty/cli/commands/form_remove_all.rb +0 -2
  33. data/{app → lib}/htty/cli/commands/fragment_clear.rb +0 -2
  34. data/{app → lib}/htty/cli/commands/fragment_set.rb +6 -4
  35. data/{app → lib}/htty/cli/commands/fragment_unset.rb +4 -4
  36. data/{app → lib}/htty/cli/commands/get.rb +0 -2
  37. data/{app → lib}/htty/cli/commands/header_set.rb +0 -2
  38. data/{app → lib}/htty/cli/commands/header_unset.rb +0 -2
  39. data/{app → lib}/htty/cli/commands/headers_clear.rb +0 -2
  40. data/{app → lib}/htty/cli/commands/headers_request.rb +13 -8
  41. data/{app → lib}/htty/cli/commands/headers_response.rb +6 -4
  42. data/{app → lib}/htty/cli/commands/headers_set.rb +1 -3
  43. data/{app → lib}/htty/cli/commands/headers_unset.rb +1 -4
  44. data/{app → lib}/htty/cli/commands/headers_unset_all.rb +1 -3
  45. data/{app → lib}/htty/cli/commands/help.rb +8 -4
  46. data/{app → lib}/htty/cli/commands/history.rb +5 -7
  47. data/{app → lib}/htty/cli/commands/history_verbose.rb +6 -5
  48. data/{app → lib}/htty/cli/commands/host_set.rb +2 -7
  49. data/{app → lib}/htty/cli/commands/http_delete.rb +0 -2
  50. data/{app → lib}/htty/cli/commands/http_get.rb +0 -2
  51. data/{app → lib}/htty/cli/commands/http_head.rb +0 -2
  52. data/{app → lib}/htty/cli/commands/http_options.rb +0 -2
  53. data/{app → lib}/htty/cli/commands/http_post.rb +0 -2
  54. data/{app → lib}/htty/cli/commands/http_put.rb +0 -2
  55. data/{app → lib}/htty/cli/commands/http_trace.rb +0 -2
  56. data/{app → lib}/htty/cli/commands/path_set.rb +6 -4
  57. data/{app → lib}/htty/cli/commands/port_set.rb +4 -4
  58. data/{app → lib}/htty/cli/commands/post.rb +0 -2
  59. data/{app → lib}/htty/cli/commands/put.rb +0 -2
  60. data/{app → lib}/htty/cli/commands/query_clear.rb +0 -2
  61. data/{app → lib}/htty/cli/commands/query_set.rb +10 -7
  62. data/{app → lib}/htty/cli/commands/query_unset.rb +12 -6
  63. data/{app → lib}/htty/cli/commands/query_unset_all.rb +4 -4
  64. data/{app → lib}/htty/cli/commands/quit.rb +0 -2
  65. data/{app → lib}/htty/cli/commands/reuse.rb +4 -3
  66. data/{app → lib}/htty/cli/commands/scheme_set.rb +4 -4
  67. data/{app → lib}/htty/cli/commands/status.rb +8 -5
  68. data/{app → lib}/htty/cli/commands/undo.rb +0 -2
  69. data/{app → lib}/htty/cli/commands/userinfo_clear.rb +0 -2
  70. data/{app → lib}/htty/cli/commands/userinfo_set.rb +30 -8
  71. data/{app → lib}/htty/cli/commands/userinfo_unset.rb +4 -4
  72. data/{app → lib}/htty/cli/display.rb +40 -19
  73. data/{app → lib}/htty/cli/http_method_command.rb +4 -8
  74. data/{app → lib}/htty/cli/url_escaping.rb +0 -2
  75. data/{app → lib}/htty/cookies_util.rb +0 -2
  76. data/{app → lib}/htty/no_location_header_error.rb +3 -2
  77. data/{app → lib}/htty/no_response_error.rb +0 -2
  78. data/{app → lib}/htty/no_set_cookie_header_error.rb +3 -2
  79. data/{app → lib}/htty/ordered_hash.rb +2 -3
  80. data/{app → lib}/htty/payload.rb +2 -3
  81. data/{app → lib}/htty/request.rb +25 -15
  82. data/{app → lib}/htty/requests_util.rb +2 -3
  83. data/{app → lib}/htty/response.rb +2 -3
  84. data/{app → lib}/htty/session.rb +0 -2
  85. data/spec/unit/htty/cli_spec.rb +9 -14
  86. data/spec/unit/htty/ordered_hash_spec.rb +13 -17
  87. data/spec/unit/htty/request_spec.rb +281 -127
  88. data/spec/unit/htty/session_spec.rb +4 -7
  89. metadata +152 -99
  90. data/MIT-LICENSE.rdoc +0 -9
  91. data/README.rdoc +0 -199
  92. data/app/htty/cli/cookie_clearing_command.rb +0 -26
@@ -1,5 +1,4 @@
1
- # Defines HTTY::CLI::Commands::Status.
2
-
1
+ require File.expand_path("#{File.dirname __FILE__}/../../response")
3
2
  require File.expand_path("#{File.dirname __FILE__}/../command")
4
3
  require File.expand_path("#{File.dirname __FILE__}/../display")
5
4
  require File.expand_path("#{File.dirname __FILE__}/body_response")
@@ -29,9 +28,13 @@ class HTTY::CLI::Commands::Status < HTTY::CLI::Command
29
28
 
30
29
  # Returns the extended help text for the _status_ command.
31
30
  def self.help_extended
32
- 'Displays the status signal received in the response. Does not ' +
33
- "communicate with the endpoint.\n" +
34
- "\n" +
31
+ 'Displays the status signal, the number of headers, and size of the body ' +
32
+ "received in the response. Does not communicate with the host.\n" +
33
+ "\n" +
34
+ "If a '#{HTTY::Response::COOKIES_HEADER_NAME}' request header is " +
35
+ 'present, a bold asterisk (it looks like a cookie) appears next to the ' +
36
+ "headers summary.\n" +
37
+ "\n" +
35
38
  'Status is displayed automatically when a response is received.'
36
39
  end
37
40
 
@@ -1,5 +1,3 @@
1
- # Defines HTTY::CLI::Commands::Undo.
2
-
3
1
  require File.expand_path("#{File.dirname __FILE__}/../command")
4
2
 
5
3
  module HTTY; end
@@ -1,5 +1,3 @@
1
- # Defines HTTY::CLI::Commands::UserinfoClear.
2
-
3
1
  require File.expand_path("#{File.dirname __FILE__}/../command")
4
2
  require File.expand_path("#{File.dirname __FILE__}/userinfo_unset")
5
3
 
@@ -1,5 +1,4 @@
1
- # Defines HTTY::CLI::Commands::UserinfoSet.
2
-
1
+ require File.expand_path("#{File.dirname __FILE__}/../../request")
3
2
  require File.expand_path("#{File.dirname __FILE__}/../command")
4
3
  require File.expand_path("#{File.dirname __FILE__}/../url_escaping")
5
4
  require File.expand_path("#{File.dirname __FILE__}/address")
@@ -25,7 +24,7 @@ class HTTY::CLI::Commands::UserinfoSet < HTTY::CLI::Command
25
24
  # Returns the arguments for the command-line usage of the _userinfo-set_
26
25
  # command.
27
26
  def self.command_line_arguments
28
- 'userinfo'
27
+ 'username [password]'
29
28
  end
30
29
 
31
30
  # Returns the help text for the _userinfo-set_ command.
@@ -35,10 +34,18 @@ class HTTY::CLI::Commands::UserinfoSet < HTTY::CLI::Command
35
34
 
36
35
  # Returns the extended help text for the _userinfo-set_ command.
37
36
  def self.help_extended
38
- 'Sets the userinfo used for the request. Does not communicate with the ' +
39
- "endpoint.\n" +
40
- "\n" +
41
- 'The console prompt shows the address for the current request.'
37
+ 'Sets the userinfo used for the request. Does not communicate with the ' +
38
+ "host.\n" +
39
+ "\n" +
40
+ "Userinfo will be URL-encoded if necessary.\n" +
41
+ "\n" +
42
+ 'When userinfo is set, a corresponding ' +
43
+ "'#{HTTY::Request::AUTHORIZATION_HEADER_NAME}' header is set " +
44
+ "automatically.\n" +
45
+ "\n" +
46
+ 'The console prompt shows the address for the current request. Userinfo ' +
47
+ 'appears in normal type while the rest of the address appears in bold to ' +
48
+ 'indicate that userinfo is sent to the host in the form of a header.'
42
49
  end
43
50
 
44
51
  # Returns related command classes for the _userinfo-set_ command.
@@ -49,7 +56,22 @@ class HTTY::CLI::Commands::UserinfoSet < HTTY::CLI::Command
49
56
  # Performs the _userinfo-set_ command.
50
57
  def perform
51
58
  add_request_if_has_response do |request|
52
- request.userinfo_set(*escape_or_warn_of_escape_sequences(arguments))
59
+ arguments = self.arguments
60
+ if (arguments.length == 1) && (arguments.first.scan(':').length == 1)
61
+ arguments = arguments.first.split(':')
62
+ end
63
+ arguments = escape_mercantile(escape_or_warn_of_escape_sequences(arguments))
64
+ self.class.notify_if_cookies_cleared request do
65
+ request.userinfo_set(*arguments)
66
+ end
67
+ end
68
+ end
69
+
70
+ private
71
+
72
+ def escape_mercantile(arguments)
73
+ arguments.collect do |a|
74
+ a.gsub '@', '%40'
53
75
  end
54
76
  end
55
77
 
@@ -1,5 +1,3 @@
1
- # Defines HTTY::CLI::Commands::UserinfoUnset.
2
-
3
1
  require File.expand_path("#{File.dirname __FILE__}/../command")
4
2
  require File.expand_path("#{File.dirname __FILE__}/address")
5
3
  require File.expand_path("#{File.dirname __FILE__}/userinfo_set")
@@ -27,7 +25,7 @@ class HTTY::CLI::Commands::UserinfoUnset < HTTY::CLI::Command
27
25
  # Returns the extended help text for the _userinfo-unset_ command.
28
26
  def self.help_extended
29
27
  'Removes the userinfo used for the request. Does not communicate with ' +
30
- "the endpoint.\n" +
28
+ "the host.\n" +
31
29
  "\n" +
32
30
  'The console prompt shows the address for the current request.'
33
31
  end
@@ -40,7 +38,9 @@ class HTTY::CLI::Commands::UserinfoUnset < HTTY::CLI::Command
40
38
  # Performs the _userinfo-unset_ command.
41
39
  def perform
42
40
  add_request_if_has_response do |request|
43
- request.userinfo_unset(*arguments)
41
+ self.class.notify_if_cookies_cleared request do
42
+ request.userinfo_unset(*arguments)
43
+ end
44
44
  end
45
45
  end
46
46
 
@@ -1,5 +1,3 @@
1
- # Defines HTTY::CLI::Display.
2
-
3
1
  module HTTY; end
4
2
 
5
3
  class HTTY::CLI; end
@@ -74,6 +72,21 @@ module HTTY::CLI::Display
74
72
  # format string, :foreground_dark_default
75
73
  end
76
74
 
75
+ def pluralize(word, number)
76
+ case number
77
+ when 0
78
+ "no #{word}s"
79
+ when 1
80
+ "1 #{word}"
81
+ else
82
+ "#{number} #{word}s"
83
+ end
84
+ end
85
+
86
+ def prompt(request)
87
+ format_request_uri(request.uri) + normal('> ')
88
+ end
89
+
77
90
  def say(message, style=:normal)
78
91
  puts send(style, notice(message))
79
92
  end
@@ -91,18 +104,26 @@ module HTTY::CLI::Display
91
104
  strong('HTTP TTY') + normal('. Heck To The Yeah!')
92
105
  end
93
106
 
94
- def show_headers(headers, show_asterisk_next_to=nil)
95
- asterisk_symbol = nil
107
+ def show_headers(headers, options={})
108
+ show_asterisk_next_to = options[:show_asterisk_next_to]
109
+ show_mercantile_next_to = options[:show_mercantile_next_to]
110
+
111
+ asterisk_symbol, mercantile_symbol = nil, nil
96
112
  margin = headers.inject 0 do |result, header|
97
113
  header_name = header.first
98
- asterisk_symbol ||= (header_name == show_asterisk_next_to) ? '*' : nil
99
- asterisk = (header_name == show_asterisk_next_to) ? asterisk_symbol : ''
100
- [(header_name.length + asterisk.length), result].max
114
+ asterisk_symbol ||= (header_name == show_asterisk_next_to) ? '*' : nil
115
+ mercantile_symbol ||= (header_name == show_mercantile_next_to) ? '@' : nil
116
+ asterisk = (header_name == show_asterisk_next_to) ? asterisk_symbol : ''
117
+ mercantile = (header_name == show_mercantile_next_to) ? mercantile_symbol : ''
118
+ [(header_name.length + [asterisk.length, mercantile.length].max),
119
+ result].max
101
120
  end
102
121
  headers.each do |name, value|
103
- asterisk = (name == show_asterisk_next_to) ? asterisk_symbol : nil
104
- puts "#{name.rjust margin - asterisk.to_s.length}:#{strong asterisk} " +
105
- value
122
+ asterisk = (name == show_asterisk_next_to) ? asterisk_symbol : nil
123
+ mercantile = (name == show_mercantile_next_to) ? mercantile_symbol : nil
124
+ justified_name = name.rjust margin -
125
+ [asterisk.to_s.length, mercantile.to_s.length].max
126
+ puts "#{justified_name}:#{strong(asterisk || mercantile)} " + value
106
127
  end
107
128
  end
108
129
 
@@ -112,7 +133,7 @@ module HTTY::CLI::Display
112
133
  cookies_asterisk = request.cookies.empty? ? '' : strong('*')
113
134
  body_length = request.body.to_s.length
114
135
  body_size = body_length.zero? ? 'empty' : "#{body_length}-character"
115
- puts [request.uri,
136
+ puts [format_request_uri(request.uri),
116
137
  pluralize('header', request.headers.length) + cookies_asterisk,
117
138
  "#{body_size} body"].join(' -- ')
118
139
  end
@@ -162,15 +183,15 @@ module HTTY::CLI::Display
162
183
 
163
184
  private
164
185
 
165
- def pluralize(word, number)
166
- case number
167
- when 0
168
- "no #{word}s"
169
- when 1
170
- "1 #{word}"
171
- else
172
- "#{number} #{word}s"
186
+ def format_request_uri(uri)
187
+ if uri.userinfo
188
+ userinfo_with_at = "#{uri.userinfo}@"
189
+ before_userinfo, after_userinfo = uri.to_s.split(userinfo_with_at, 2)
190
+ return strong(before_userinfo) +
191
+ normal(userinfo_with_at) +
192
+ strong(after_userinfo)
173
193
  end
194
+ return strong(uri)
174
195
  end
175
196
 
176
197
  def sentence_case(text)
@@ -1,10 +1,6 @@
1
- # Defines HTTY::CLI::HTTPMethodCommand.
2
-
3
1
  require File.expand_path("#{File.dirname __FILE__}/../request")
4
2
  require File.expand_path("#{File.dirname __FILE__}/display")
5
3
  require File.expand_path("#{File.dirname __FILE__}/commands/cookies_use")
6
- # This 'require' statement leads to an unresolvable circular dependency.
7
- # require File.expand_path("#{File.dirname __FILE__}/commands/follow")
8
4
 
9
5
  module HTTY; end
10
6
 
@@ -16,8 +12,8 @@ module HTTY::CLI::HTTPMethodCommand
16
12
 
17
13
  include HTTY::CLI::Display
18
14
 
19
- # Returns the name of a category under which help for the _http-get_ command
20
- # should appear.
15
+ # Returns the name of a category under which help for the command should
16
+ # appear.
21
17
  def self.category
22
18
  'Issuing Requests'
23
19
  end
@@ -27,8 +23,8 @@ module HTTY::CLI::HTTPMethodCommand
27
23
  add_request_if_has_response do |request|
28
24
  request = request.send("#{method}!", *arguments)
29
25
  unless body? || request.body.to_s.empty?
30
- puts notice("The body of your #{method.upcase} request is not being " +
31
- 'sent')
26
+ puts notice("The body of your #{method.to_s.upcase} request is not " +
27
+ 'being sent')
32
28
  end
33
29
  notify_if_cookies
34
30
  notify_if_follow
@@ -1,5 +1,3 @@
1
- # Defines HTTY::CLI::UrlEscaping.
2
-
3
1
  require 'uri'
4
2
  require File.expand_path("#{File.dirname __FILE__}/display")
5
3
 
@@ -1,5 +1,3 @@
1
- # Defines HTTY::CookiesUtil.
2
-
3
1
  module HTTY; end
4
2
 
5
3
  # Provides support for marshaling HTTP cookies to and from strings.
@@ -1,4 +1,4 @@
1
- # Defines HTTY::NoLocationHeaderError.
1
+ require File.expand_path("#{File.dirname __FILE__}/response")
2
2
 
3
3
  module HTTY; end
4
4
 
@@ -6,7 +6,8 @@ module HTTY; end
6
6
  class HTTY::NoLocationHeaderError < StandardError
7
7
 
8
8
  def initialize
9
- super "response does not have a 'Location' header"
9
+ super 'response does not have a ' +
10
+ "'#{HTTY::Response::LOCATION_HEADER_NAME}' header"
10
11
  end
11
12
 
12
13
  end
@@ -1,5 +1,3 @@
1
- # Defines HTTY::NoResponseError.
2
-
3
1
  module HTTY; end
4
2
 
5
3
  # Indicates that HTTY::Request#response was missing.
@@ -1,4 +1,4 @@
1
- # Defines HTTY::NoSetCookieHeaderError.
1
+ require File.expand_path("#{File.dirname __FILE__}/response")
2
2
 
3
3
  module HTTY; end
4
4
 
@@ -7,7 +7,8 @@ module HTTY; end
7
7
  class HTTY::NoSetCookieHeaderError < StandardError
8
8
 
9
9
  def initialize
10
- super "response does not have a 'Set-Cookie' header"
10
+ super "response does not have a '#{HTTY::Response::COOKIES_HEADER_NAME}' " +
11
+ 'header'
11
12
  end
12
13
 
13
14
  end
@@ -1,5 +1,3 @@
1
- # Defines HTTY::OrderedHash.
2
-
3
1
  module HTTY; end
4
2
 
5
3
  # Represents a Hash that preserves the insertion order of values. This class
@@ -17,7 +15,8 @@ class HTTY::OrderedHash
17
15
  end
18
16
  end
19
17
 
20
- def initialize_copy(source) #:nodoc:
18
+ # @private
19
+ def initialize_copy(source)
21
20
  super
22
21
  @inner_hash = @inner_hash.dup
23
22
  @inner_keys = @inner_keys.dup
@@ -1,5 +1,3 @@
1
- # Defines HTTY::Payload.
2
-
3
1
  require File.expand_path("#{File.dirname __FILE__}/ordered_hash")
4
2
 
5
3
  module HTTY; end
@@ -39,7 +37,8 @@ protected
39
37
  end
40
38
  end
41
39
 
42
- def initialize_copy(source) #:nodoc:
40
+ # @private
41
+ def initialize_copy(source)
43
42
  super
44
43
  @body = @body.dup if @body
45
44
  @headers = @headers.dup
@@ -1,5 +1,4 @@
1
- # Defines HTTY::Request.
2
-
1
+ require 'base64'
3
2
  require 'pathname'
4
3
  require 'uri'
5
4
  require File.expand_path("#{File.dirname __FILE__}/../htty")
@@ -16,7 +15,8 @@ module HTTY; end
16
15
  # Encapsulates an HTTP(S) request.
17
16
  class HTTY::Request < HTTY::Payload
18
17
 
19
- COOKIES_HEADER_NAME = 'Cookie'
18
+ AUTHORIZATION_HEADER_NAME = 'Authorization'
19
+ COOKIES_HEADER_NAME = 'Cookie'
20
20
 
21
21
  METHODS_SENDING_BODY = [:post, :put]
22
22
 
@@ -65,9 +65,6 @@ class HTTY::Request < HTTY::Payload
65
65
  authority = build_authority(components)
66
66
  path_query_and_fragment = build_path_query_and_fragment(components)
67
67
  path_query_and_fragment ||= '/' if authority
68
- unless scheme == 'http://'
69
- raise ArgumentError, "#{scheme.inspect} is not yet supported"
70
- end
71
68
  URI.parse([scheme, authority, path_query_and_fragment].join)
72
69
  end
73
70
 
@@ -110,10 +107,13 @@ class HTTY::Request < HTTY::Payload
110
107
 
111
108
  protected
112
109
 
113
- def self.clear_cookies_if_host_changes(request)
110
+ def self.set_up_cookies_and_authentication(request)
114
111
  previous_host = request.uri.host
115
112
  yield
116
113
  request.cookies_remove_all unless request.uri.host == previous_host
114
+
115
+ request.send :establish_basic_authentication
116
+
117
117
  request
118
118
  end
119
119
 
@@ -133,10 +133,12 @@ public
133
133
  def initialize(address)
134
134
  super({:headers => [['User-Agent', "htty/#{HTTY::VERSION}"]]})
135
135
  @uri = self.class.parse_uri(address)
136
+ establish_basic_authentication
136
137
  establish_content_length
137
138
  end
138
139
 
139
- def initialize_copy(source) #:nodoc:
140
+ # @private
141
+ def initialize_copy(source)
140
142
  super
141
143
  @response = @response.dup if @response
142
144
  @uri = @uri.dup
@@ -157,12 +159,12 @@ public
157
159
  uri = self.class.parse_uri(address)
158
160
  if response
159
161
  dup = dup_without_response
160
- return self.class.clear_cookies_if_host_changes(dup) do
162
+ return self.class.send(:set_up_cookies_and_authentication, dup) do
161
163
  dup.uri = uri
162
164
  end
163
165
  end
164
166
 
165
- self.class.clear_cookies_if_host_changes self do
167
+ self.class.send(:set_up_cookies_and_authentication, self) do
166
168
  @uri = uri
167
169
  end
168
170
  end
@@ -263,7 +265,7 @@ public
263
265
  raise HTTY::NoResponseError unless response
264
266
 
265
267
  location_header = response.headers.detect do |name, value|
266
- name == 'Location'
268
+ name == HTTY::Response::LOCATION_HEADER_NAME
267
269
  end
268
270
  unless location_header && location_header.last
269
271
  raise HTTY::NoLocationHeaderError
@@ -411,7 +413,8 @@ public
411
413
  end
412
414
 
413
415
  # Establishes a new #uri with the specified _userinfo_.
414
- def userinfo_set(userinfo)
416
+ def userinfo_set(username, password=nil)
417
+ userinfo = [username, password].compact.join(':')
415
418
  rebuild_uri :userinfo => userinfo
416
419
  end
417
420
 
@@ -429,8 +432,11 @@ protected
429
432
  request
430
433
  end
431
434
 
432
- def establish_content_length
433
- header_set 'Content-Length', body.to_s.length
435
+ def establish_basic_authentication
436
+ value = uri.userinfo ?
437
+ "Basic #{Base64.encode64(URI.unescape(uri.userinfo)).chomp}" :
438
+ nil
439
+ header_set AUTHORIZATION_HEADER_NAME, value
434
440
  end
435
441
 
436
442
  def path_query_and_fragment
@@ -445,7 +451,7 @@ protected
445
451
  components = URI::HTTP::COMPONENT.inject({}) do |result, c|
446
452
  result.merge c => uri.send(c)
447
453
  end
448
- self.class.clear_cookies_if_host_changes self do
454
+ self.class.send(:set_up_cookies_and_authentication, self) do
449
455
  @uri = self.class.build_uri(components.merge(changed_components))
450
456
  end
451
457
  end
@@ -462,6 +468,10 @@ private
462
468
  :port => uri.port
463
469
  end
464
470
 
471
+ def establish_content_length
472
+ header_set 'Content-Length', body.to_s.length
473
+ end
474
+
465
475
  def request!(method)
466
476
  request = response ? dup_without_response : self
467
477
  request.instance_variable_set '@request_method', method