diff --git a/lib/httparty.rb b/lib/httparty.rb index c62c967..fbd0d71 100644 --- a/lib/httparty.rb +++ b/lib/httparty.rb @@ -49,6 +49,7 @@ module HTTParty # * :+maintain_method_across_redirects+: see HTTParty::ClassMethods.maintain_method_across_redirects. # * :+no_follow+: see HTTParty::ClassMethods.no_follow. # * :+parser+: see HTTParty::ClassMethods.parser. + # * :+uri_adapter+: see HTTParty::ClassMethods.uri_adapter # * :+connection_adapter+: see HTTParty::ClassMethods.connection_adapter. # * :+pem+: see HTTParty::ClassMethods.pem. # * :+query_string_normalizer+: see HTTParty::ClassMethods.query_string_normalizer @@ -419,6 +420,17 @@ module HTTParty end end + # Allows setting a custom URI adapter. + # + # class Foo + # include HTTParty + # uri_adapter Addressable::URI + # end + def uri_adapter(uri_adapter) + raise ArgumentError, 'The URI adapter should respond to #parse' unless uri_adapter.respond_to?(:parse) + default_options[:uri_adapter] = uri_adapter + end + # Allows setting a custom connection_adapter for the http connections # # @example diff --git a/lib/httparty/connection_adapter.rb b/lib/httparty/connection_adapter.rb index 635799c..7a4d467 100644 --- a/lib/httparty/connection_adapter.rb +++ b/lib/httparty/connection_adapter.rb @@ -61,7 +61,8 @@ module HTTParty attr_reader :uri, :options def initialize(uri, options = {}) - raise ArgumentError, "uri must be a URI, not a #{uri.class}" unless uri.is_a? URI + uri_adapter = options[:uri_adapter] || URI + raise ArgumentError, "uri must be a #{uri_adapter}, not a #{uri.class}" unless uri.is_a? uri_adapter @uri = uri @options = options diff --git a/lib/httparty/request.rb b/lib/httparty/request.rb index f8d2b9e..8f7b323 100644 --- a/lib/httparty/request.rb +++ b/lib/httparty/request.rb @@ -37,6 +37,7 @@ module HTTParty default_params: {}, follow_redirects: true, parser: Parser, + uri_adapter: URI, connection_adapter: ConnectionAdapter }.merge(o) self.path = path @@ -90,13 +91,15 @@ module HTTParty end def URI uri - if uri.is_a?(URI) + uri_adapter = options[:uri_adapter] + + if uri.is_a?(uri_adapter) uri elsif uri = String.try_convert(uri) - URI.parse uri + uri_adapter.parse uri else raise ArgumentError, - "bad argument (expected URI object or URI string)" + "bad argument (expected #{uri_adapter} object or URI string)" end end diff --git a/spec/httparty_spec.rb b/spec/httparty_spec.rb index 914202e..139c102 100644 --- a/spec/httparty_spec.rb +++ b/spec/httparty_spec.rb @@ -351,6 +351,45 @@ RSpec.describe HTTParty do end end + describe "uri_adapter" do + + require 'forwardable' + class CustomURIAdaptor + extend Forwardable + def_delegators :@uri, :userinfo, :relative?, :query, :query=, :scheme, :path, :host, :port + + def initialize uri + @uri = uri + end + + def self.parse uri + new URI.parse uri + end + end + + let(:uri_adapter) { CustomURIAdaptor } + + it "should set the uri_adapter" do + @klass.uri_adapter uri_adapter + expect(@klass.default_options[:uri_adapter]).to be uri_adapter + end + + it "should raise an ArgumentError if uri_adapter doesn't implement parse method" do + expect do + @klass.uri_adapter double() + end.to raise_error(ArgumentError) + end + + + it "should process a request with a uri instance parsed from the uri_adapter" do + uri = 'http://foo.com/bar' + FakeWeb.register_uri(:get, uri, body: 'stuff') + @klass.uri_adapter uri_adapter + expect(@klass.get(uri).parsed_response).to eq('stuff') + end + + end + describe "connection_adapter" do let(:uri) { 'http://google.com/api.json' } let(:connection_adapter) { double('CustomConnectionAdapter') }