aboutsummaryrefslogtreecommitdiffstats
path: root/activeresource/lib
diff options
context:
space:
mode:
Diffstat (limited to 'activeresource/lib')
-rw-r--r--activeresource/lib/active_resource/base.rb77
-rw-r--r--activeresource/lib/active_resource/connection.rb19
2 files changed, 87 insertions, 9 deletions
diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb
index 97baa46682..d79198f49b 100644
--- a/activeresource/lib/active_resource/base.rb
+++ b/activeresource/lib/active_resource/base.rb
@@ -85,16 +85,26 @@ module ActiveResource
# == Authentication
#
# Many REST APIs will require authentication, usually in the form of basic
- # HTTP authentication. Authentication can be specified by putting the credentials
- # in the +site+ variable of the Active Resource class you need to authenticate.
+ # HTTP authentication. Authentication can be specified by:
+ # * putting the credentials in the URL for the +site+ variable.
#
- # class Person < ActiveResource::Base
- # self.site = "http://ryan:password@api.people.com:3000/"
- # end
+ # class Person < ActiveResource::Base
+ # self.site = "http://ryan:password@api.people.com:3000/"
+ # end
#
+ # * defining +user+ and/or +password+ variables
+ #
+ # class Person < ActiveResource::Base
+ # self.site = "http://api.people.com:3000/"
+ # self.user = "ryan"
+ # self.password = "password"
+ # end
+ #
# For obvious security reasons, it is probably best if such services are available
# over HTTPS.
#
+ # Note: Some values cannot be provided in the URL passed to site. e.g. email addresses
+ # as usernames. In those situations you should use the seperate user and password option.
# == Errors & Validation
#
# Error handling and validation is handled in much the same manner as you're used to seeing in
@@ -164,6 +174,21 @@ module ActiveResource
# Gets the URI of the REST resources to map for this class. The site variable is required
# ActiveResource's mapping to work.
def site
+ # Not using superclass_delegating_reader because don't want subclasses to modify superclass instance
+ #
+ # With superclass_delegating_reader
+ #
+ # Parent.site = 'http://anonymous@test.com'
+ # Subclass.site # => 'http://anonymous@test.com'
+ # Subclass.site.user = 'david'
+ # Parent.site # => 'http://david@test.com'
+ #
+ # Without superclass_delegating_reader (expected behaviour)
+ #
+ # Parent.site = 'http://anonymous@test.com'
+ # Subclass.site # => 'http://anonymous@test.com'
+ # Subclass.site.user = 'david' # => TypeError: can't modify frozen object
+ #
if defined?(@site)
@site
elsif superclass != Object && superclass.site
@@ -175,7 +200,45 @@ module ActiveResource
# The site variable is required ActiveResource's mapping to work.
def site=(site)
@connection = nil
- @site = site.nil? ? nil : create_site_uri_from(site)
+ if site.nil?
+ @site = nil
+ else
+ @site = create_site_uri_from(site)
+ @user = @site.user if @site.user
+ @password = @site.password if @site.password
+ end
+ end
+
+ # Gets the user for REST HTTP authentication
+ def user
+ # Not using superclass_delegating_reader. See +site+ for explanation
+ if defined?(@user)
+ @user
+ elsif superclass != Object && superclass.user
+ superclass.user.dup.freeze
+ end
+ end
+
+ # Sets the user for REST HTTP authentication
+ def user=(user)
+ @connection = nil
+ @user = user
+ end
+
+ # Gets the password for REST HTTP authentication
+ def password
+ # Not using superclass_delegating_reader. See +site+ for explanation
+ if defined?(@password)
+ @password
+ elsif superclass != Object && superclass.password
+ superclass.password.dup.freeze
+ end
+ end
+
+ # Sets the password for REST HTTP authentication
+ def password=(password)
+ @connection = nil
+ @password = password
end
# Sets the format that attributes are sent and received in from a mime type reference. Example:
@@ -206,6 +269,8 @@ module ActiveResource
def connection(refresh = false)
if defined?(@connection) || superclass == Object
@connection = Connection.new(site, format) if refresh || @connection.nil?
+ @connection.user = user if user
+ @connection.password = password if password
@connection
else
superclass.connection
diff --git a/activeresource/lib/active_resource/connection.rb b/activeresource/lib/active_resource/connection.rb
index e4e6da50c9..cf4681b25b 100644
--- a/activeresource/lib/active_resource/connection.rb
+++ b/activeresource/lib/active_resource/connection.rb
@@ -55,7 +55,7 @@ module ActiveResource
# This class is used by ActiveResource::Base to interface with REST
# services.
class Connection
- attr_reader :site
+ attr_reader :site, :user, :password
attr_accessor :format
class << self
@@ -68,6 +68,7 @@ module ActiveResource
# attribute to the URI for the remote resource service.
def initialize(site, format = ActiveResource::Formats[:xml])
raise ArgumentError, 'Missing site URI' unless site
+ @user = @password = nil
self.site = site
self.format = format
end
@@ -75,6 +76,18 @@ module ActiveResource
# Set URI for remote service.
def site=(site)
@site = site.is_a?(URI) ? site : URI.parse(site)
+ @user = @site.user if @site.user
+ @password = @site.password if @site.password
+ end
+
+ # Set user for remote service.
+ def user=(user)
+ @user = user
+ end
+
+ # Set password for remote service.
+ def password=(password)
+ @password = password
end
# Execute a GET request.
@@ -166,9 +179,9 @@ module ActiveResource
authorization_header.update(default_header).update(headers)
end
- # Sets authorization header; authentication information is pulled from credentials provided with site URI.
+ # Sets authorization header
def authorization_header
- (@site.user || @site.password ? { 'Authorization' => 'Basic ' + ["#{@site.user}:#{ @site.password}"].pack('m').delete("\r\n") } : {})
+ (@user || @password ? { 'Authorization' => 'Basic ' + ["#{@user}:#{ @password}"].pack('m').delete("\r\n") } : {})
end
def logger #:nodoc: