htty 1.0.0 → 1.1.0

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