Object
Class to handle connections to remote web services. This class is used by ActiveResource::Base to interface with REST services.
The site parameter is required and will set the site attribute to the URI for the remote resource service.
# File lib/active_resource/connection.rb, line 31
31: def initialize(site, format = ActiveResource::Formats::XmlFormat)
32: raise ArgumentError, 'Missing site URI' unless site
33: @user = @password = nil
34: @uri_parser = URI.const_defined?(:Parser) ? URI::Parser.new : URI
35: self.site = site
36: self.format = format
37: end
Sets the auth type for remote service.
# File lib/active_resource/connection.rb, line 62
62: def auth_type=(auth_type)
63: @auth_type = legitimize_auth_type(auth_type)
64: end
Executes a DELETE request (see HTTP protocol documentation if unfamiliar). Used to delete resources.
# File lib/active_resource/connection.rb, line 84
84: def delete(path, headers = {})
85: with_auth { request(:delete, path, build_request_headers(headers, :delete, self.site.merge(path))) }
86: end
Executes a GET request. Used to get (find) resources.
# File lib/active_resource/connection.rb, line 78
78: def get(path, headers = {})
79: with_auth { format.decode(request(:get, path, build_request_headers(headers, :get, self.site.merge(path))).body) }
80: end
Executes a HEAD request. Used to obtain meta-information about resources, such as whether they exist and their size (via response headers).
# File lib/active_resource/connection.rb, line 102
102: def head(path, headers = {})
103: with_auth { request(:head, path, build_request_headers(headers, :head, self.site.merge(path))) }
104: end
Sets the password for remote service.
# File lib/active_resource/connection.rb, line 57
57: def password=(password)
58: @password = password
59: end
Executes a POST request. Used to create new resources.
# File lib/active_resource/connection.rb, line 96
96: def post(path, body = '', headers = {})
97: with_auth { request(:post, path, body.to_s, build_request_headers(headers, :post, self.site.merge(path))) }
98: end
Set the proxy for remote service.
# File lib/active_resource/connection.rb, line 47
47: def proxy=(proxy)
48: @proxy = proxy.is_a?(URI) ? proxy : @uri_parser.parse(proxy)
49: end
Executes a PUT request (see HTTP protocol documentation if unfamiliar). Used to update resources.
# File lib/active_resource/connection.rb, line 90
90: def put(path, body = '', headers = {})
91: with_auth { request(:put, path, body.to_s, build_request_headers(headers, :put, self.site.merge(path))) }
92: end
Set URI for remote service.
# File lib/active_resource/connection.rb, line 40
40: def site=(site)
41: @site = site.is_a?(URI) ? site : @uri_parser.parse(site)
42: @user = @uri_parser.unescape(@site.user) if @site.user
43: @password = @uri_parser.unescape(@site.password) if @site.password
44: end
Hash of options applied to Net::HTTP instance when site protocol is ‘https’.
# File lib/active_resource/connection.rb, line 72
72: def ssl_options=(opts={})
73: @ssl_options = opts
74: end
# File lib/active_resource/connection.rb, line 179
179: def apply_ssl_options(http)
180: return http unless @site.is_a?(URI::HTTPS)
181:
182: http.use_ssl = true
183: http.verify_mode = OpenSSL::SSL::VERIFY_NONE
184: return http unless defined?(@ssl_options)
185:
186: http.ca_path = @ssl_options[:ca_path] if @ssl_options[:ca_path]
187: http.ca_file = @ssl_options[:ca_file] if @ssl_options[:ca_file]
188:
189: http.cert = @ssl_options[:cert] if @ssl_options[:cert]
190: http.key = @ssl_options[:key] if @ssl_options[:key]
191:
192: http.cert_store = @ssl_options[:cert_store] if @ssl_options[:cert_store]
193: http.ssl_timeout = @ssl_options[:ssl_timeout] if @ssl_options[:ssl_timeout]
194:
195: http.verify_mode = @ssl_options[:verify_mode] if @ssl_options[:verify_mode]
196: http.verify_callback = @ssl_options[:verify_callback] if @ssl_options[:verify_callback]
197: http.verify_depth = @ssl_options[:verify_depth] if @ssl_options[:verify_depth]
198:
199: http
200: end
# File lib/active_resource/connection.rb, line 260
260: def auth_attributes_for(uri, request_digest, params)
261: [
262: %(username="#{@user}"),
263: %(realm="#{params['realm']}"),
264: %(qop="#{params['qop']}"),
265: %(uri="#{uri.path}"),
266: %(nonce="#{params['nonce']}"),
267: %(nc="0"),
268: %(cnonce="#{params['cnonce']}"),
269: %(opaque="#{params['opaque']}"),
270: %(response="#{request_digest}")].join(", ")
271: end
Builds headers for request to remote service.
# File lib/active_resource/connection.rb, line 207
207: def build_request_headers(headers, http_method, uri)
208: authorization_header(http_method, uri).update(default_header).update(http_format_header(http_method)).update(headers)
209: end
# File lib/active_resource/connection.rb, line 248
248: def client_nonce
249: Digest::MD5.hexdigest("%x" % (Time.now.to_i + rand(65535)))
250: end
# File lib/active_resource/connection.rb, line 167
167: def configure_http(http)
168: http = apply_ssl_options(http)
169:
170: # Net::HTTP timeouts default to 60 seconds.
171: if @timeout
172: http.open_timeout = @timeout
173: http.read_timeout = @timeout
174: end
175:
176: http
177: end
# File lib/active_resource/connection.rb, line 202
202: def default_header
203: @default_header ||= {}
204: end
# File lib/active_resource/connection.rb, line 237
237: def digest_auth_header(http_method, uri)
238: params = extract_params_from_response
239:
240: ha1 = Digest::MD5.hexdigest("#{@user}:#{params['realm']}:#{@password}")
241: ha2 = Digest::MD5.hexdigest("#{http_method.to_s.upcase}:#{uri.path}")
242:
243: params.merge!('cnonce' => client_nonce)
244: request_digest = Digest::MD5.hexdigest([ha1, params['nonce'], "0", params['cnonce'], params['qop'], ha2].join(":"))
245: "Digest #{auth_attributes_for(uri, request_digest, params)}"
246: end
# File lib/active_resource/connection.rb, line 252
252: def extract_params_from_response
253: params = {}
254: if response_auth_header =~ /^(\w+) (.*)/
255: $2.gsub(/(\w+)="(.*?)"/) { params[$1] = $2 }
256: end
257: params
258: end
Handles response and error codes from the remote service.
# File lib/active_resource/connection.rb, line 122
122: def handle_response(response)
123: case response.code.to_i
124: when 301,302
125: raise(Redirection.new(response))
126: when 200...400
127: response
128: when 400
129: raise(BadRequest.new(response))
130: when 401
131: raise(UnauthorizedAccess.new(response))
132: when 403
133: raise(ForbiddenAccess.new(response))
134: when 404
135: raise(ResourceNotFound.new(response))
136: when 405
137: raise(MethodNotAllowed.new(response))
138: when 409
139: raise(ResourceConflict.new(response))
140: when 410
141: raise(ResourceGone.new(response))
142: when 422
143: raise(ResourceInvalid.new(response))
144: when 401...500
145: raise(ClientError.new(response))
146: when 500...600
147: raise(ServerError.new(response))
148: else
149: raise(ConnectionError.new(response, "Unknown response code: #{response.code}"))
150: end
151: end
# File lib/active_resource/http_mock.rb, line 296
296: def http
297: @http ||= HttpMock.new(@site)
298: end
Creates new Net::HTTP instance for communication with the remote service and resources.
# File lib/active_resource/connection.rb, line 155
155: def http
156: configure_http(new_http)
157: end
# File lib/active_resource/connection.rb, line 273
273: def http_format_header(http_method)
274: {HTTP_FORMAT_HEADER_NAMES[http_method] => format.mime_type}
275: end
# File lib/active_resource/connection.rb, line 277
277: def legitimize_auth_type(auth_type)
278: return :basic if auth_type.nil?
279: auth_type = auth_type.to_sym
280: [:basic, :digest].include?(auth_type) ? auth_type : :basic
281: end
# File lib/active_resource/connection.rb, line 159
159: def new_http
160: if @proxy
161: Net::HTTP.new(@site.host, @site.port, @proxy.host, @proxy.port, @proxy.user, @proxy.password)
162: else
163: Net::HTTP.new(@site.host, @site.port)
164: end
165: end
Makes a request to the remote service.
# File lib/active_resource/connection.rb, line 108
108: def request(method, path, *arguments)
109: result = ActiveSupport::Notifications.instrument("request.active_resource") do |payload|
110: payload[:method] = method
111: payload[:request_uri] = "#{site.scheme}://#{site.host}:#{site.port}#{path}"
112: payload[:result] = http.send(method, path, *arguments)
113: end
114: handle_response(result)
115: rescue Timeout::Error => e
116: raise TimeoutError.new(e.message)
117: rescue OpenSSL::SSL::SSLError => e
118: raise SSLError.new(e.message)
119: end
# File lib/active_resource/connection.rb, line 211
211: def response_auth_header
212: @response_auth_header ||= ""
213: end
# File lib/active_resource/connection.rb, line 215
215: def with_auth
216: retried ||= false
217: yield
218: rescue UnauthorizedAccess => e
219: raise if retried || auth_type != :digest
220: @response_auth_header = e.response['WWW-Authenticate']
221: retried = true
222: retry
223: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.