mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Digest auth option for ActiveResource.
Signed-off-by: Michael Koziarski <michael@koziarski.com>
This commit is contained in:
parent
1d01bad3ce
commit
945d999aad
5 changed files with 258 additions and 35 deletions
|
@ -326,6 +326,17 @@ module ActiveResource
|
|||
@password = password
|
||||
end
|
||||
|
||||
def auth_type
|
||||
if defined?(@auth_type)
|
||||
@auth_type
|
||||
end
|
||||
end
|
||||
|
||||
def auth_type=(auth_type)
|
||||
@connection = nil
|
||||
@auth_type = auth_type
|
||||
end
|
||||
|
||||
# Sets the format that attributes are sent and received in from a mime type reference:
|
||||
#
|
||||
# Person.format = :json
|
||||
|
@ -397,6 +408,7 @@ module ActiveResource
|
|||
@connection.proxy = proxy if proxy
|
||||
@connection.user = user if user
|
||||
@connection.password = password if password
|
||||
@connection.auth_type = auth_type if auth_type
|
||||
@connection.timeout = timeout if timeout
|
||||
@connection.ssl_options = ssl_options if ssl_options
|
||||
@connection
|
||||
|
|
|
@ -17,7 +17,7 @@ module ActiveResource
|
|||
:head => 'Accept'
|
||||
}
|
||||
|
||||
attr_reader :site, :user, :password, :timeout, :proxy, :ssl_options
|
||||
attr_reader :site, :user, :password, :auth_type, :timeout, :proxy, :ssl_options
|
||||
attr_accessor :format
|
||||
|
||||
class << self
|
||||
|
@ -57,6 +57,11 @@ module ActiveResource
|
|||
@password = password
|
||||
end
|
||||
|
||||
# Sets the auth type for remote service.
|
||||
def auth_type=(auth_type)
|
||||
@auth_type = legitimize_auth_type(auth_type)
|
||||
end
|
||||
|
||||
# Sets the number of seconds after which HTTP requests to the remote service should time out.
|
||||
def timeout=(timeout)
|
||||
@timeout = timeout
|
||||
|
@ -70,31 +75,31 @@ module ActiveResource
|
|||
# Executes a GET request.
|
||||
# Used to get (find) resources.
|
||||
def get(path, headers = {})
|
||||
format.decode(request(:get, path, build_request_headers(headers, :get)).body)
|
||||
with_auth { format.decode(request(:get, path, build_request_headers(headers, :get, self.site.merge(path))).body) }
|
||||
end
|
||||
|
||||
# Executes a DELETE request (see HTTP protocol documentation if unfamiliar).
|
||||
# Used to delete resources.
|
||||
def delete(path, headers = {})
|
||||
request(:delete, path, build_request_headers(headers, :delete))
|
||||
with_auth { request(:delete, path, build_request_headers(headers, :delete, self.site.merge(path))) }
|
||||
end
|
||||
|
||||
# Executes a PUT request (see HTTP protocol documentation if unfamiliar).
|
||||
# Used to update resources.
|
||||
def put(path, body = '', headers = {})
|
||||
request(:put, path, body.to_s, build_request_headers(headers, :put))
|
||||
with_auth { request(:put, path, body.to_s, build_request_headers(headers, :put, self.site.merge(path))) }
|
||||
end
|
||||
|
||||
# Executes a POST request.
|
||||
# Used to create new resources.
|
||||
def post(path, body = '', headers = {})
|
||||
request(:post, path, body.to_s, build_request_headers(headers, :post))
|
||||
with_auth { request(:post, path, body.to_s, build_request_headers(headers, :post, self.site.merge(path))) }
|
||||
end
|
||||
|
||||
# Executes a HEAD request.
|
||||
# Used to obtain meta-information about resources, such as whether they exist and their size (via response headers).
|
||||
def head(path, headers = {})
|
||||
request(:head, path, build_request_headers(headers, :head))
|
||||
with_auth { request(:head, path, build_request_headers(headers, :head, self.site.merge(path))) }
|
||||
end
|
||||
|
||||
|
||||
|
@ -198,13 +203,70 @@ module ActiveResource
|
|||
end
|
||||
|
||||
# Builds headers for request to remote service.
|
||||
def build_request_headers(headers, http_method=nil)
|
||||
authorization_header.update(default_header).update(http_format_header(http_method)).update(headers)
|
||||
def build_request_headers(headers, http_method, uri)
|
||||
authorization_header(http_method, uri).update(default_header).update(http_format_header(http_method)).update(headers)
|
||||
end
|
||||
|
||||
# Sets authorization header
|
||||
def authorization_header
|
||||
(@user || @password ? { 'Authorization' => 'Basic ' + ["#{@user}:#{ @password}"].pack('m').delete("\r\n") } : {})
|
||||
def response_auth_header
|
||||
@response_auth_header ||= ""
|
||||
end
|
||||
|
||||
def with_auth
|
||||
retried ||= false
|
||||
yield
|
||||
rescue UnauthorizedAccess => e
|
||||
raise if retried || auth_type != :digest
|
||||
@response_auth_header = e.response['WWW-Authenticate']
|
||||
retried = true
|
||||
retry
|
||||
end
|
||||
|
||||
def authorization_header(http_method, uri)
|
||||
if @user || @password
|
||||
if auth_type == :digest
|
||||
{ 'Authorization' => digest_auth_header(http_method, uri) }
|
||||
else
|
||||
{ 'Authorization' => 'Basic ' + ["#{@user}:#{@password}"].pack('m').delete("\r\n") }
|
||||
end
|
||||
else
|
||||
{}
|
||||
end
|
||||
end
|
||||
|
||||
def digest_auth_header(http_method, uri)
|
||||
params = extract_params_from_response
|
||||
|
||||
ha1 = Digest::MD5.hexdigest("#{@user}:#{params['realm']}:#{@password}")
|
||||
ha2 = Digest::MD5.hexdigest("#{http_method.to_s.upcase}:#{uri.path}")
|
||||
|
||||
params.merge!('cnonce' => client_nonce)
|
||||
request_digest = Digest::MD5.hexdigest([ha1, params['nonce'], "0", params['cnonce'], params['qop'], ha2].join(":"))
|
||||
"Digest #{auth_attributes_for(uri, request_digest, params)}"
|
||||
end
|
||||
|
||||
def client_nonce
|
||||
Digest::MD5.hexdigest("%x" % (Time.now.to_i + rand(65535)))
|
||||
end
|
||||
|
||||
def extract_params_from_response
|
||||
params = {}
|
||||
if response_auth_header =~ /^(\w+) (.*)/
|
||||
$2.gsub(/(\w+)="(.*?)"/) { params[$1] = $2 }
|
||||
end
|
||||
params
|
||||
end
|
||||
|
||||
def auth_attributes_for(uri, request_digest, params)
|
||||
[
|
||||
%Q(username="#{@user}"),
|
||||
%Q(realm="#{params['realm']}"),
|
||||
%Q(qop="#{params['qop']}"),
|
||||
%Q(uri="#{uri.path}"),
|
||||
%Q(nonce="#{params['nonce']}"),
|
||||
%Q(nc="0"),
|
||||
%Q(cnonce="#{params['cnonce']}"),
|
||||
%Q(opaque="#{params['opaque']}"),
|
||||
%Q(response="#{request_digest}")].join(", ")
|
||||
end
|
||||
|
||||
def http_format_header(http_method)
|
||||
|
@ -214,5 +276,11 @@ module ActiveResource
|
|||
def logger #:nodoc:
|
||||
Base.logger
|
||||
end
|
||||
|
||||
def legitimize_auth_type(auth_type)
|
||||
return :basic if auth_type.nil?
|
||||
auth_type = auth_type.to_sym
|
||||
[:basic, :digest].include?(auth_type) ? auth_type : :basic
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,46 +8,75 @@ class AuthorizationTest < Test::Unit::TestCase
|
|||
@matz = { :id => 1, :name => 'Matz' }.to_xml(:root => 'person')
|
||||
@david = { :id => 2, :name => 'David' }.to_xml(:root => 'person')
|
||||
@authenticated_conn = ActiveResource::Connection.new("http://david:test123@localhost")
|
||||
@authorization_request_header = { 'Authorization' => 'Basic ZGF2aWQ6dGVzdDEyMw==' }
|
||||
@basic_authorization_request_header = { 'Authorization' => 'Basic ZGF2aWQ6dGVzdDEyMw==' }
|
||||
|
||||
@nonce = "MTI0OTUxMzc4NzpjYWI3NDM3NDNmY2JmODU4ZjQ2ZjcwNGZkMTJiMjE0NA=="
|
||||
|
||||
ActiveResource::HttpMock.respond_to do |mock|
|
||||
mock.get "/people/2.xml", @authorization_request_header, @david
|
||||
mock.put "/people/2.xml", @authorization_request_header, nil, 204
|
||||
mock.delete "/people/2.xml", @authorization_request_header, nil, 200
|
||||
mock.post "/people/2/addresses.xml", @authorization_request_header, nil, 201, 'Location' => '/people/1/addresses/5'
|
||||
mock.get "/people/2.xml", @basic_authorization_request_header, @david
|
||||
mock.get "/people/1.xml", @basic_authorization_request_header, nil, 401, { 'WWW-Authenticate' => 'i_should_be_ignored' }
|
||||
mock.put "/people/2.xml", @basic_authorization_request_header, nil, 204
|
||||
mock.delete "/people/2.xml", @basic_authorization_request_header, nil, 200
|
||||
mock.post "/people/2/addresses.xml", @basic_authorization_request_header, nil, 201, 'Location' => '/people/1/addresses/5'
|
||||
mock.head "/people/2.xml", @basic_authorization_request_header, nil, 200
|
||||
|
||||
mock.get "/people/2.xml", { 'Authorization' => blank_digest_auth_header("/people/2.xml", "a10c9bd131c9d4d7755b8f4706fd04af") }, nil, 401, { 'WWW-Authenticate' => response_digest_auth_header }
|
||||
mock.get "/people/2.xml", { 'Authorization' => request_digest_auth_header("/people/2.xml", "912c7a643f18cda562b8d9662c47b6f5") }, @david, 200
|
||||
mock.get "/people/1.xml", { 'Authorization' => request_digest_auth_header("/people/1.xml", "d76e675c0ecfa2bb1abe01491b068a06") }, @matz, 200
|
||||
|
||||
mock.put "/people/2.xml", { 'Authorization' => blank_digest_auth_header("/people/2.xml", "7de8a265a5be3c4c2d3a246562ecd6bd") }, nil, 401, { 'WWW-Authenticate' => response_digest_auth_header }
|
||||
mock.put "/people/2.xml", { 'Authorization' => request_digest_auth_header("/people/2.xml", "3fb3b33d9d0b869cc75815aa11faacd9") }, nil, 204
|
||||
|
||||
mock.delete "/people/2.xml", { 'Authorization' => blank_digest_auth_header("/people/2.xml", "07dfc32769a34ea3510d3a77d64ca495") }, nil, 401, { 'WWW-Authenticate' => response_digest_auth_header }
|
||||
mock.delete "/people/2.xml", { 'Authorization' => request_digest_auth_header("/people/2.xml", "5d438610de7ec163b29096c9afcbb254") }, nil, 200
|
||||
|
||||
mock.post "/people/2/addresses.xml", { 'Authorization' => blank_digest_auth_header("/people/2/addresses.xml", "966dab13620421f928d051f2b9d7b9af") }, nil, 401, { 'WWW-Authenticate' => response_digest_auth_header }
|
||||
mock.post "/people/2/addresses.xml", { 'Authorization' => request_digest_auth_header("/people/2/addresses.xml", "ed540d032c63f8ee34959116c090ec45") }, nil, 201, 'Location' => '/people/1/addresses/5'
|
||||
|
||||
mock.head "/people/2.xml", { 'Authorization' => blank_digest_auth_header("/people/2.xml", "2854eeb92cce2aed29350ea0ce7ba1e2") }, nil, 401, { 'WWW-Authenticate' => response_digest_auth_header }
|
||||
mock.head "/people/2.xml", { 'Authorization' => request_digest_auth_header("/people/2.xml", "07cd4d247e9c130f92ba2501a080b328") }, nil, 200
|
||||
end
|
||||
|
||||
# Make client nonce deterministic
|
||||
class << @authenticated_conn
|
||||
private
|
||||
|
||||
def client_nonce
|
||||
'i-am-a-client-nonce'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_authorization_header
|
||||
authorization_header = @authenticated_conn.__send__(:authorization_header)
|
||||
assert_equal @authorization_request_header['Authorization'], authorization_header['Authorization']
|
||||
authorization_header = @authenticated_conn.__send__(:authorization_header, :get, URI.parse('/people/2.xml'))
|
||||
assert_equal @basic_authorization_request_header['Authorization'], authorization_header['Authorization']
|
||||
authorization = authorization_header["Authorization"].to_s.split
|
||||
|
||||
|
||||
assert_equal "Basic", authorization[0]
|
||||
assert_equal ["david", "test123"], ActiveSupport::Base64.decode64(authorization[1]).split(":")[0..1]
|
||||
end
|
||||
|
||||
|
||||
def test_authorization_header_with_username_but_no_password
|
||||
@conn = ActiveResource::Connection.new("http://david:@localhost")
|
||||
authorization_header = @conn.__send__(:authorization_header)
|
||||
authorization_header = @conn.__send__(:authorization_header, :get, URI.parse('/people/2.xml'))
|
||||
authorization = authorization_header["Authorization"].to_s.split
|
||||
|
||||
|
||||
assert_equal "Basic", authorization[0]
|
||||
assert_equal ["david"], ActiveSupport::Base64.decode64(authorization[1]).split(":")[0..1]
|
||||
end
|
||||
|
||||
|
||||
def test_authorization_header_with_password_but_no_username
|
||||
@conn = ActiveResource::Connection.new("http://:test123@localhost")
|
||||
authorization_header = @conn.__send__(:authorization_header)
|
||||
authorization_header = @conn.__send__(:authorization_header, :get, URI.parse('/people/2.xml'))
|
||||
authorization = authorization_header["Authorization"].to_s.split
|
||||
|
||||
|
||||
assert_equal "Basic", authorization[0]
|
||||
assert_equal ["", "test123"], ActiveSupport::Base64.decode64(authorization[1]).split(":")[0..1]
|
||||
end
|
||||
|
||||
|
||||
def test_authorization_header_with_decoded_credentials_from_url
|
||||
@conn = ActiveResource::Connection.new("http://my%40email.com:%31%32%33@localhost")
|
||||
authorization_header = @conn.__send__(:authorization_header)
|
||||
authorization_header = @conn.__send__(:authorization_header, :get, URI.parse('/people/2.xml'))
|
||||
authorization = authorization_header["Authorization"].to_s.split
|
||||
|
||||
assert_equal "Basic", authorization[0]
|
||||
|
@ -58,8 +87,8 @@ class AuthorizationTest < Test::Unit::TestCase
|
|||
@authenticated_conn = ActiveResource::Connection.new("http://@localhost")
|
||||
@authenticated_conn.user = 'david'
|
||||
@authenticated_conn.password = 'test123'
|
||||
authorization_header = @authenticated_conn.__send__(:authorization_header)
|
||||
assert_equal @authorization_request_header['Authorization'], authorization_header['Authorization']
|
||||
authorization_header = @authenticated_conn.__send__(:authorization_header, :get, URI.parse('/people/2.xml'))
|
||||
assert_equal @basic_authorization_request_header['Authorization'], authorization_header['Authorization']
|
||||
authorization = authorization_header["Authorization"].to_s.split
|
||||
|
||||
assert_equal "Basic", authorization[0]
|
||||
|
@ -69,7 +98,7 @@ class AuthorizationTest < Test::Unit::TestCase
|
|||
def test_authorization_header_explicitly_setting_username_but_no_password
|
||||
@conn = ActiveResource::Connection.new("http://@localhost")
|
||||
@conn.user = "david"
|
||||
authorization_header = @conn.__send__(:authorization_header)
|
||||
authorization_header = @conn.__send__(:authorization_header, :get, URI.parse('/people/2.xml'))
|
||||
authorization = authorization_header["Authorization"].to_s.split
|
||||
|
||||
assert_equal "Basic", authorization[0]
|
||||
|
@ -79,38 +108,119 @@ class AuthorizationTest < Test::Unit::TestCase
|
|||
def test_authorization_header_explicitly_setting_password_but_no_username
|
||||
@conn = ActiveResource::Connection.new("http://@localhost")
|
||||
@conn.password = "test123"
|
||||
authorization_header = @conn.__send__(:authorization_header)
|
||||
authorization_header = @conn.__send__(:authorization_header, :get, URI.parse('/people/2.xml'))
|
||||
authorization = authorization_header["Authorization"].to_s.split
|
||||
|
||||
assert_equal "Basic", authorization[0]
|
||||
assert_equal ["", "test123"], ActiveSupport::Base64.decode64(authorization[1]).split(":")[0..1]
|
||||
end
|
||||
|
||||
def test_authorization_header_if_credentials_supplied_and_auth_type_is_basic
|
||||
@authenticated_conn.auth_type = :basic
|
||||
authorization_header = @authenticated_conn.__send__(:authorization_header, :get, URI.parse('/people/2.xml'))
|
||||
assert_equal @basic_authorization_request_header['Authorization'], authorization_header['Authorization']
|
||||
authorization = authorization_header["Authorization"].to_s.split
|
||||
|
||||
assert_equal "Basic", authorization[0]
|
||||
assert_equal ["david", "test123"], ActiveSupport::Base64.decode64(authorization[1]).split(":")[0..1]
|
||||
end
|
||||
|
||||
def test_authorization_header_if_credentials_supplied_and_auth_type_is_digest
|
||||
@authenticated_conn.auth_type = :digest
|
||||
authorization_header = @authenticated_conn.__send__(:authorization_header, :get, URI.parse('/people/2.xml'))
|
||||
assert_equal blank_digest_auth_header("/people/2.xml", "a10c9bd131c9d4d7755b8f4706fd04af"), authorization_header['Authorization']
|
||||
end
|
||||
|
||||
def test_get
|
||||
david = @authenticated_conn.get("/people/2.xml")
|
||||
assert_equal "David", david["name"]
|
||||
end
|
||||
|
||||
|
||||
def test_post
|
||||
response = @authenticated_conn.post("/people/2/addresses.xml")
|
||||
assert_equal "/people/1/addresses/5", response["Location"]
|
||||
end
|
||||
|
||||
|
||||
def test_put
|
||||
response = @authenticated_conn.put("/people/2.xml")
|
||||
assert_equal 204, response.code
|
||||
end
|
||||
|
||||
|
||||
def test_delete
|
||||
response = @authenticated_conn.delete("/people/2.xml")
|
||||
assert_equal 200, response.code
|
||||
end
|
||||
|
||||
def test_head
|
||||
response = @authenticated_conn.head("/people/2.xml")
|
||||
assert_equal 200, response.code
|
||||
end
|
||||
|
||||
def test_get_with_digest_auth_handles_initial_401_response_and_retries
|
||||
@authenticated_conn.auth_type = :digest
|
||||
response = @authenticated_conn.get("/people/2.xml")
|
||||
assert_equal "David", response["name"]
|
||||
end
|
||||
|
||||
def test_post_with_digest_auth_handles_initial_401_response_and_retries
|
||||
@authenticated_conn.auth_type = :digest
|
||||
response = @authenticated_conn.post("/people/2/addresses.xml")
|
||||
assert_equal "/people/1/addresses/5", response["Location"]
|
||||
assert_equal 201, response.code
|
||||
end
|
||||
|
||||
def test_put_with_digest_auth_handles_initial_401_response_and_retries
|
||||
@authenticated_conn.auth_type = :digest
|
||||
response = @authenticated_conn.put("/people/2.xml")
|
||||
assert_equal 204, response.code
|
||||
end
|
||||
|
||||
def test_delete_with_digest_auth_handles_initial_401_response_and_retries
|
||||
@authenticated_conn.auth_type = :digest
|
||||
response = @authenticated_conn.delete("/people/2.xml")
|
||||
assert_equal 200, response.code
|
||||
end
|
||||
|
||||
def test_head_with_digest_auth_handles_initial_401_response_and_retries
|
||||
@authenticated_conn.auth_type = :digest
|
||||
response = @authenticated_conn.head("/people/2.xml")
|
||||
assert_equal 200, response.code
|
||||
end
|
||||
|
||||
def test_get_with_digest_auth_caches_nonce
|
||||
@authenticated_conn.auth_type = :digest
|
||||
response = @authenticated_conn.get("/people/2.xml")
|
||||
assert_equal "David", response["name"]
|
||||
|
||||
# There is no mock for this request with a non-cached nonce.
|
||||
response = @authenticated_conn.get("/people/1.xml")
|
||||
assert_equal "Matz", response["name"]
|
||||
end
|
||||
|
||||
def test_retry_on_401_only_happens_with_digest_auth
|
||||
assert_raise(ActiveResource::UnauthorizedAccess) { @authenticated_conn.get("/people/1.xml") }
|
||||
assert_equal "", @authenticated_conn.send(:response_auth_header)
|
||||
end
|
||||
|
||||
def test_raises_invalid_request_on_unauthorized_requests
|
||||
assert_raise(ActiveResource::InvalidRequestError) { @conn.post("/people/2.xml") }
|
||||
assert_raise(ActiveResource::InvalidRequestError) { @conn.get("/people/2.xml") }
|
||||
assert_raise(ActiveResource::InvalidRequestError) { @conn.post("/people/2/addresses.xml") }
|
||||
assert_raise(ActiveResource::InvalidRequestError) { @conn.put("/people/2.xml") }
|
||||
assert_raise(ActiveResource::InvalidRequestError) { @conn.delete("/people/2.xml") }
|
||||
assert_raise(ActiveResource::InvalidRequestError) { @conn.head("/people/2.xml") }
|
||||
end
|
||||
|
||||
def test_raises_invalid_request_on_unauthorized_requests_with_digest_auth
|
||||
@conn.auth_type = :digest
|
||||
assert_raise(ActiveResource::InvalidRequestError) { @conn.get("/people/2.xml") }
|
||||
assert_raise(ActiveResource::InvalidRequestError) { @conn.post("/people/2/addresses.xml") }
|
||||
assert_raise(ActiveResource::InvalidRequestError) { @conn.put("/people/2.xml") }
|
||||
assert_raise(ActiveResource::InvalidRequestError) { @conn.delete("/people/2.xml") }
|
||||
assert_raise(ActiveResource::InvalidRequestError) { @conn.head("/people/2.xml") }
|
||||
end
|
||||
|
||||
def test_client_nonce_is_not_nil
|
||||
assert_not_nil ActiveResource::Connection.new("http://david:test123@localhost").send(:client_nonce)
|
||||
end
|
||||
|
||||
protected
|
||||
|
@ -119,4 +229,16 @@ class AuthorizationTest < Test::Unit::TestCase
|
|||
@conn.__send__(:handle_response, Response.new(code))
|
||||
end
|
||||
end
|
||||
|
||||
def blank_digest_auth_header(uri, response)
|
||||
%Q(Digest username="david", realm="", qop="", uri="#{uri}", nonce="", nc="0", cnonce="i-am-a-client-nonce", opaque="", response="#{response}")
|
||||
end
|
||||
|
||||
def request_digest_auth_header(uri, response)
|
||||
%Q(Digest username="david", realm="RailsTestApp", qop="auth", uri="#{uri}", nonce="#{@nonce}", nc="0", cnonce="i-am-a-client-nonce", opaque="ef6dfb078ba22298d366f99567814ffb", response="#{response}")
|
||||
end
|
||||
|
||||
def response_digest_auth_header
|
||||
%Q(Digest realm="RailsTestApp", qop="auth", algorithm=MD5, nonce="#{@nonce}", opaque="ef6dfb078ba22298d366f99567814ffb")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -163,6 +163,12 @@ class BaseTest < Test::Unit::TestCase
|
|||
assert_equal('test123', Forum.connection.password)
|
||||
end
|
||||
|
||||
def test_should_accept_setting_auth_type
|
||||
Forum.auth_type = :digest
|
||||
assert_equal(:digest, Forum.auth_type)
|
||||
assert_equal(:digest, Forum.connection.auth_type)
|
||||
end
|
||||
|
||||
def test_should_accept_setting_timeout
|
||||
Forum.timeout = 5
|
||||
assert_equal(5, Forum.timeout)
|
||||
|
|
|
@ -225,6 +225,21 @@ class ConnectionTest < Test::Unit::TestCase
|
|||
assert_raise(ActiveResource::SSLError) { @conn.get('/people/1.xml') }
|
||||
end
|
||||
|
||||
def test_auth_type_can_be_string
|
||||
@conn.auth_type = 'digest'
|
||||
assert_equal(:digest, @conn.auth_type)
|
||||
end
|
||||
|
||||
def test_auth_type_defaults_to_basic
|
||||
@conn.auth_type = nil
|
||||
assert_equal(:basic, @conn.auth_type)
|
||||
end
|
||||
|
||||
def test_auth_type_ignores_nonsensical_values
|
||||
@conn.auth_type = :wibble
|
||||
assert_equal(:basic, @conn.auth_type)
|
||||
end
|
||||
|
||||
protected
|
||||
def assert_response_raises(klass, code)
|
||||
assert_raise(klass, "Expected response code #{code} to raise #{klass}") do
|
||||
|
|
Loading…
Reference in a new issue