started extracting the http layer

This commit is contained in:
Matt Aimonetti 2009-07-14 01:43:40 -07:00
parent bd1b114930
commit b2a29d9eb7
8 changed files with 158 additions and 81 deletions

View file

@ -45,6 +45,7 @@ module CouchRest
autoload :ExtendedDocument, 'couchrest/more/extended_document' autoload :ExtendedDocument, 'couchrest/more/extended_document'
autoload :CastedModel, 'couchrest/more/casted_model' autoload :CastedModel, 'couchrest/more/casted_model'
require File.join(File.dirname(__FILE__), 'couchrest', 'core', 'http_abstraction')
require File.join(File.dirname(__FILE__), 'couchrest', 'mixins') require File.join(File.dirname(__FILE__), 'couchrest', 'mixins')
# The CouchRest module methods handle the basic JSON serialization # The CouchRest module methods handle the basic JSON serialization
@ -118,9 +119,9 @@ module CouchRest
} }
end end
# set proxy for RestClient to use # set proxy to use
def proxy url def proxy url
RestClient.proxy = url HttpAbstraction.proxy = url
end end
# ensure that a database exists # ensure that a database exists
@ -141,7 +142,7 @@ module CouchRest
def put(uri, doc = nil) def put(uri, doc = nil)
payload = doc.to_json if doc payload = doc.to_json if doc
begin begin
JSON.parse(RestClient.put(uri, payload)) JSON.parse(HttpAbstraction.put(uri, payload))
rescue Exception => e rescue Exception => e
if $DEBUG if $DEBUG
raise "Error while sending a PUT request #{uri}\npayload: #{payload.inspect}\n#{e}" raise "Error while sending a PUT request #{uri}\npayload: #{payload.inspect}\n#{e}"
@ -153,7 +154,7 @@ module CouchRest
def get(uri) def get(uri)
begin begin
JSON.parse(RestClient.get(uri), :max_nesting => false) JSON.parse(HttpAbstraction.get(uri), :max_nesting => false)
rescue => e rescue => e
if $DEBUG if $DEBUG
raise "Error while sending a GET request #{uri}\n: #{e}" raise "Error while sending a GET request #{uri}\n: #{e}"
@ -166,7 +167,7 @@ module CouchRest
def post uri, doc = nil def post uri, doc = nil
payload = doc.to_json if doc payload = doc.to_json if doc
begin begin
JSON.parse(RestClient.post(uri, payload)) JSON.parse(HttpAbstraction.post(uri, payload))
rescue Exception => e rescue Exception => e
if $DEBUG if $DEBUG
raise "Error while sending a POST request #{uri}\npayload: #{payload.inspect}\n#{e}" raise "Error while sending a POST request #{uri}\npayload: #{payload.inspect}\n#{e}"
@ -177,11 +178,11 @@ module CouchRest
end end
def delete uri def delete uri
JSON.parse(RestClient.delete(uri)) JSON.parse(HttpAbstraction.delete(uri))
end end
def copy uri, destination def copy uri, destination
JSON.parse(RestClient.copy(uri, {'Destination' => destination})) JSON.parse(HttpAbstraction.copy(uri, {'Destination' => destination}))
end end
def paramify_url url, params = {} def paramify_url url, params = {}

View file

@ -0,0 +1,35 @@
module RestClientAdapter
module API
def proxy=(url)
RestClient.proxy = url
end
def proxy
RestClient.proxy
end
def get(uri, headers={})
RestClient.get(uri, headers)
end
def post(uri, payload, headers={})
RestClient.post(uri, payload, headers)
end
def put(uri, payload, headers={})
RestClient.put(uri, payload, headers)
end
def delete(uri, headers={})
RestClient.delete(uri, headers)
end
def copy(uri, headers)
RestClient::Request.execute( :method => :copy,
:url => uri,
:headers => headers)
end
end
end

View file

@ -58,7 +58,7 @@ module CouchRest
keys = params.delete(:keys) keys = params.delete(:keys)
funcs = funcs.merge({:keys => keys}) if keys funcs = funcs.merge({:keys => keys}) if keys
url = CouchRest.paramify_url "#{@root}/_temp_view", params url = CouchRest.paramify_url "#{@root}/_temp_view", params
JSON.parse(RestClient.post(url, funcs.to_json, {"Content-Type" => 'application/json'})) JSON.parse(HttpAbstraction.post(url, funcs.to_json, {"Content-Type" => 'application/json'}))
end end
# backwards compatibility is a plus # backwards compatibility is a plus
@ -100,11 +100,8 @@ module CouchRest
# GET an attachment directly from CouchDB # GET an attachment directly from CouchDB
def fetch_attachment(doc, name) def fetch_attachment(doc, name)
# slug = escape_docid(docid)
# name = CGI.escape(name)
uri = url_for_attachment(doc, name) uri = url_for_attachment(doc, name)
RestClient.get uri HttpAbstraction.get uri
# "#{@uri}/#{slug}/#{name}"
end end
# PUT an attachment directly to CouchDB # PUT an attachment directly to CouchDB
@ -112,14 +109,14 @@ module CouchRest
docid = escape_docid(doc['_id']) docid = escape_docid(doc['_id'])
name = CGI.escape(name) name = CGI.escape(name)
uri = url_for_attachment(doc, name) uri = url_for_attachment(doc, name)
JSON.parse(RestClient.put(uri, file, options)) JSON.parse(HttpAbstraction.put(uri, file, options))
end end
# DELETE an attachment directly from CouchDB # DELETE an attachment directly from CouchDB
def delete_attachment doc, name def delete_attachment doc, name
uri = url_for_attachment(doc, name) uri = url_for_attachment(doc, name)
# this needs a rev # this needs a rev
JSON.parse(RestClient.delete(uri)) JSON.parse(HttpAbstraction.delete(uri))
end end
# Save a document to CouchDB. This will use the <tt>_id</tt> field from # Save a document to CouchDB. This will use the <tt>_id</tt> field from
@ -146,7 +143,7 @@ module CouchRest
slug = escape_docid(doc['_id']) slug = escape_docid(doc['_id'])
begin begin
CouchRest.put "#{@root}/#{slug}", doc CouchRest.put "#{@root}/#{slug}", doc
rescue RestClient::ResourceNotFound rescue HttpAbstraction::ResourceNotFound
p "resource not found when saving even tho an id was passed" p "resource not found when saving even tho an id was passed"
slug = doc['_id'] = @server.next_uuid slug = doc['_id'] = @server.next_uuid
CouchRest.put "#{@root}/#{slug}", doc CouchRest.put "#{@root}/#{slug}", doc
@ -252,7 +249,7 @@ module CouchRest
def recreate! def recreate!
delete! delete!
create! create!
rescue RestClient::ResourceNotFound rescue HttpAbstraction::ResourceNotFound
ensure ensure
create! create!
end end

View file

@ -3,10 +3,6 @@ require 'delegate'
module CouchRest module CouchRest
class Document < Response class Document < Response
include CouchRest::Mixins::Attachments include CouchRest::Mixins::Attachments
# def self.inherited(subklass)
# subklass.send(:extlib_inheritable_accessor, :database)
# end
extlib_inheritable_accessor :database extlib_inheritable_accessor :database
attr_accessor :database attr_accessor :database

View file

@ -0,0 +1,48 @@
require 'couchrest/core/adapters/restclient'
# Abstraction layet for HTTP communications.
#
# By defining a basic API that CouchRest is relying on,
# it allows for easy experimentations and implementations of various libraries.
#
# Most of the API is based on the RestClient API that was used in the early version of CouchRest.
#
module HttpAbstraction
# here is the list of exception expected by CouchRest
# please convert the underlying errors in this set of known
# exceptions.
class ResourceNotFound < StandardError; end
class RequestFailed < StandardError; end
class RequestTimeout < StandardError; end
class ServerBrokeConnection < StandardError; end
class Conflict < StandardError; end
# # Here is the API you need to implement if you want to write a new adapter
# # See adapters/restclient.rb for more information.
#
# def self.proxy=(url)
# end
#
# def self.proxy
# end
#
# def self.get(uri, headers=nil)
# end
#
# def self.post(uri, payload, headers=nil)
# end
#
# def self.put(uri, payload, headers=nil)
# end
#
# def self.delete(uri, headers=nil)
# end
#
# def self.copy(uri, headers)
# end
end
HttpAbstraction.extend(RestClientAdapter::API)

View file

@ -162,7 +162,7 @@ module CouchRest
begin begin
design_doc.view_on(db, view_name, opts, &block) design_doc.view_on(db, view_name, opts, &block)
# the design doc may not have been saved yet on this database # the design doc may not have been saved yet on this database
rescue RestClient::ResourceNotFound => e rescue HttpAbstraction::ResourceNotFound => e
if retryable if retryable
save_design_doc_on(db) save_design_doc_on(db)
retryable = false retryable = false

View file

@ -51,63 +51,63 @@ if RUBY_VERSION.to_f < 1.9
end end
end end
module RestClient # module RestClient
def self.copy(url, headers={}) # # def self.copy(url, headers={})
Request.execute(:method => :copy, # # Request.execute(:method => :copy,
:url => url, # # :url => url,
:headers => headers) # # :headers => headers)
end # # end
# class Request
#
# def establish_connection(uri)
# Thread.current[:connection].finish if (Thread.current[:connection] && Thread.current[:connection].started?)
# p net_http_class
# net = net_http_class.new(uri.host, uri.port)
# net.use_ssl = uri.is_a?(URI::HTTPS)
# net.verify_mode = OpenSSL::SSL::VERIFY_NONE
# Thread.current[:connection] = net
# Thread.current[:connection].start
# Thread.current[:connection]
# end
#
# def transmit(uri, req, payload)
# setup_credentials(req)
#
# Thread.current[:host] ||= uri.host
# Thread.current[:port] ||= uri.port
#
# if (Thread.current[:connection].nil? || (Thread.current[:host] != uri.host))
# p "establishing a connection"
# establish_connection(uri)
# end
# #
# display_log request_log # # class Request
# http = Thread.current[:connection] # #
# http.read_timeout = @timeout if @timeout # # def establish_connection(uri)
# # # Thread.current[:connection].finish if (Thread.current[:connection] && Thread.current[:connection].started?)
# begin # # p net_http_class
# res = http.request(req, payload) # # net = net_http_class.new(uri.host, uri.port)
# rescue # # net.use_ssl = uri.is_a?(URI::HTTPS)
# p "Net::HTTP connection failed, reconnecting" # # net.verify_mode = OpenSSL::SSL::VERIFY_NONE
# establish_connection(uri) # # Thread.current[:connection] = net
# http = Thread.current[:connection] # # Thread.current[:connection].start
# require 'ruby-debug' # # Thread.current[:connection]
# req.body_stream = nil # # end
# # #
# res = http.request(req, payload) # # def transmit(uri, req, payload)
# display_log response_log(res) # # setup_credentials(req)
# result res # #
# else # # Thread.current[:host] ||= uri.host
# display_log response_log(res) # # Thread.current[:port] ||= uri.port
# process_result res # #
# end # # if (Thread.current[:connection].nil? || (Thread.current[:host] != uri.host))
# # # p "establishing a connection"
# rescue EOFError # # establish_connection(uri)
# raise RestClient::ServerBrokeConnection # # end
# rescue Timeout::Error # #
# raise RestClient::RequestTimeout # # display_log request_log
# end # # http = Thread.current[:connection]
# end # # http.read_timeout = @timeout if @timeout
# #
end # # begin
# # res = http.request(req, payload)
# # rescue
# # p "Net::HTTP connection failed, reconnecting"
# # establish_connection(uri)
# # http = Thread.current[:connection]
# # require 'ruby-debug'
# # req.body_stream = nil
# #
# # res = http.request(req, payload)
# # display_log response_log(res)
# # result res
# # else
# # display_log response_log(res)
# # process_result res
# # end
# #
# # rescue EOFError
# # raise RestClient::ServerBrokeConnection
# # rescue Timeout::Error
# # raise RestClient::RequestTimeout
# # end
# # end
#
# end

View file

@ -191,7 +191,7 @@ describe CouchRest do
describe "using a proxy for RestClient connections" do describe "using a proxy for RestClient connections" do
it "should set proxy url for RestClient" do it "should set proxy url for RestClient" do
CouchRest.proxy 'http://localhost:8888/' CouchRest.proxy 'http://localhost:8888/'
proxy_uri = URI.parse(RestClient.proxy) proxy_uri = URI.parse(HttpAbstraction.proxy)
proxy_uri.host.should eql( 'localhost' ) proxy_uri.host.should eql( 'localhost' )
proxy_uri.port.should eql( 8888 ) proxy_uri.port.should eql( 8888 )
CouchRest.proxy nil CouchRest.proxy nil