mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
55d4dbb8df
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@5714 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
137 lines
3.7 KiB
Ruby
137 lines
3.7 KiB
Ruby
require 'net/https'
|
|
require 'date'
|
|
require 'time'
|
|
require 'uri'
|
|
require 'benchmark'
|
|
|
|
module ActiveResource
|
|
class ConnectionError < StandardError
|
|
attr_reader :response
|
|
|
|
def initialize(response, message = nil)
|
|
@response = response
|
|
@message = message
|
|
end
|
|
|
|
def to_s
|
|
"Failed with #{response.code}"
|
|
end
|
|
end
|
|
|
|
class ClientError < ConnectionError; end # 4xx Client Error
|
|
class ResourceNotFound < ClientError; end # 404 Not Found
|
|
class ResourceConflict < ClientError; end # 409 Conflict
|
|
|
|
class ServerError < ConnectionError; end # 5xx Server Error
|
|
|
|
|
|
class Connection
|
|
attr_reader :site
|
|
|
|
class << self
|
|
def requests
|
|
@@requests ||= []
|
|
end
|
|
|
|
def default_header
|
|
class << self ; attr_reader :default_header end
|
|
@default_header = { 'Content-Type' => 'application/xml' }
|
|
end
|
|
end
|
|
|
|
def initialize(site)
|
|
raise ArgumentError, 'Missing site URI' unless site
|
|
self.site = site
|
|
end
|
|
|
|
def site=(site)
|
|
@site = site.is_a?(URI) ? site : URI.parse(site)
|
|
end
|
|
|
|
def get(path)
|
|
from_xml_data(Hash.from_xml(request(:get, path, build_request_headers).body).values.first)
|
|
end
|
|
|
|
def delete(path)
|
|
request(:delete, path, build_request_headers)
|
|
end
|
|
|
|
def put(path, body = '')
|
|
request(:put, path, body, build_request_headers)
|
|
end
|
|
|
|
def post(path, body = '')
|
|
request(:post, path, body, build_request_headers)
|
|
end
|
|
|
|
private
|
|
def request(method, path, *arguments)
|
|
logger.info "#{method.to_s.upcase} #{site.scheme}://#{site.host}:#{site.port}#{path}" if logger
|
|
result = nil
|
|
time = Benchmark.realtime { result = http.send(method, path, *arguments) }
|
|
logger.info "--> #{result.code} #{result.message} (#{result.body.length}b %.2fs)" % time if logger
|
|
handle_response(result)
|
|
end
|
|
|
|
def handle_response(response)
|
|
case response.code.to_i
|
|
when 200...400
|
|
response
|
|
when 404
|
|
raise(ResourceNotFound.new(response))
|
|
when 400
|
|
raise(ResourceInvalid.new(response))
|
|
when 409
|
|
raise(ResourceConflict.new(response))
|
|
when 401...500
|
|
raise(ClientError.new(response))
|
|
when 500...600
|
|
raise(ServerError.new(response))
|
|
else
|
|
raise(ConnectionError.new(response, "Unknown response code: #{response.code}"))
|
|
end
|
|
end
|
|
|
|
def http
|
|
unless @http
|
|
@http = Net::HTTP.new(@site.host, @site.port)
|
|
@http.use_ssl = @site.is_a?(URI::HTTPS)
|
|
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE if @http.use_ssl
|
|
end
|
|
|
|
@http
|
|
end
|
|
|
|
def build_request_headers
|
|
authorization_header.update(self.class.default_header)
|
|
end
|
|
|
|
def authorization_header
|
|
(@site.user || @site.password ? { 'Authorization' => 'Basic ' + ["#{@site.user}:#{ @site.password}"].pack('m').delete("\r\n") } : {})
|
|
end
|
|
|
|
def logger
|
|
ActiveResource::Base.logger
|
|
end
|
|
|
|
# Manipulate from_xml Hash, because xml_simple is not exactly what we
|
|
# want for ActiveResource.
|
|
def from_xml_data(data)
|
|
case data
|
|
when Hash
|
|
if data.keys.size == 1
|
|
case data.values.first
|
|
when Hash then [ from_xml_data(data.values.first) ]
|
|
when Array then from_xml_data(data.values.first)
|
|
else data
|
|
end
|
|
else
|
|
data.each_key { |key| data[key] = from_xml_data(data[key]) }
|
|
data
|
|
end
|
|
when Array then data.collect { |val| from_xml_data(val) }
|
|
else data
|
|
end
|
|
end
|
|
end
|
|
end
|