From 685628bd6107c058678e4f172e11c4baad740dea Mon Sep 17 00:00:00 2001 From: Bruce Krysiak Date: Thu, 17 Nov 2016 17:34:35 -0800 Subject: [PATCH 01/19] Allow :http_adapter creation option for http CypherSession --- Gemfile | 7 +++++++ README.md | 8 ++++++++ lib/neo4j-server/cypher_session.rb | 2 +- .../core/cypher_session/adaptors/http.rb | 11 ++++++----- .../core/cypher_session/adaptors/http_spec.rb | 19 +++++++++++++++++++ spec/neo4j/core/shared_examples/http.rb | 6 ++++++ 6 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 spec/neo4j/core/shared_examples/http.rb diff --git a/Gemfile b/Gemfile index cb5bc98f..37c65c28 100644 --- a/Gemfile +++ b/Gemfile @@ -24,4 +24,11 @@ group 'test' do gem 'rspec-its' gem 'dotenv' gem 'activesupport', '~> 4.0' + + gem 'em-http-request', '>= 1.1', require: 'em-http' + gem 'em-synchrony', '>= 1.0.3', require: ['em-synchrony', 'em-synchrony/em-http'] + gem 'excon', '>= 0.27.4' + gem 'patron', '>= 0.4.2', platforms: :ruby + gem 'rack-test', '>= 0.6', require: 'rack/test' + gem 'typhoeus', '>= 0.3.3', platforms: [:ruby_18, :ruby_19, :ruby_20, :ruby_21, :ruby_22, :ruby_23] end diff --git a/README.md b/README.md index ac54d9c9..4b1a1596 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,14 @@ To make a basic connection to Neo4j to execute Cypher queries, first choose an a neo4j_adaptor = Neo4j::Core::CypherSession::Adaptors::Embedded.new('/file/path/to/graph.db') +The `http_adapter` can also take an `:http_adapter` option for `Faraday` (defaulting to `:net_http_persistent`): + + http_adaptor = Neo4j::Core::CypherSession::Adaptors::HTTP.new('http://neo4j:pass@localhost:7474', http_adapter: :typhoeus) + +Note you **must** install any required http adapter gems yourself as per [Faraday](https://github.com/lostisland/faraday). Ex for `:typhoeus`, add to your Gemfile: + + gem 'typhoeus' + Once you have an adaptor you can create a session like so: neo4j_session = Neo4j::Core::CypherSession.new(http_adaptor) diff --git a/lib/neo4j-server/cypher_session.rb b/lib/neo4j-server/cypher_session.rb index d49aee5d..14e470ef 100644 --- a/lib/neo4j-server/cypher_session.rb +++ b/lib/neo4j-server/cypher_session.rb @@ -31,7 +31,7 @@ def self.create_connection(params, url = nil) b.response :multi_json, symbolize_keys: true, content_type: 'application/json' # b.use Faraday::Response::RaiseError - b.use Faraday::Adapter::NetHttpPersistent + b.adapter :net_http_persistent # b.adapter Faraday.default_adapter end conn.headers = {'Content-Type' => 'application/json', 'User-Agent' => ::Neo4j::Session.user_agent_string} diff --git a/lib/neo4j/core/cypher_session/adaptors/http.rb b/lib/neo4j/core/cypher_session/adaptors/http.rb index c1019a3e..dc4e11fa 100644 --- a/lib/neo4j/core/cypher_session/adaptors/http.rb +++ b/lib/neo4j/core/cypher_session/adaptors/http.rb @@ -16,7 +16,7 @@ def initialize(url, options = {}) end def connect - @requestor = Requestor.new(@url, USER_AGENT_STRING, self.class.method(:instrument_request)) + @requestor = Requestor.new(@url, USER_AGENT_STRING, self.class.method(:instrument_request), @options[:http_adapter]) rescue Faraday::ConnectionFailed => e raise CypherSession::ConnectionFailedError, "#{e.class}: #{e.message}" end @@ -94,12 +94,12 @@ class Requestor default_url('http://neo4:neo4j@localhost:7474') validate_uri { |uri| uri.is_a?(URI::HTTP) } - def initialize(url, user_agent_string, instrument_proc) + def initialize(url, user_agent_string, instrument_proc, adapter) self.url = url @user = user @password = password @user_agent_string = user_agent_string - @faraday = faraday_connection + @faraday = faraday_connection(adapter) @instrument_proc = instrument_proc end @@ -134,16 +134,17 @@ def get(path, body = '', options = {}) private - def faraday_connection + def faraday_connection(adapter) require 'faraday' require 'faraday_middleware/multi_json' + require 'typhoeus/adapters/faraday' if adapter == :typhoeus Faraday.new(url) do |c| c.request :basic_auth, user, password c.request :multi_json c.response :multi_json, symbolize_keys: true, content_type: 'application/json' - c.use Faraday::Adapter::NetHttpPersistent + c.adapter(adapter || :net_http_persistent) # c.response :logger, ::Logger.new(STDOUT), bodies: true diff --git a/spec/neo4j/core/cypher_session/adaptors/http_spec.rb b/spec/neo4j/core/cypher_session/adaptors/http_spec.rb index f3d61a03..c17bd7f1 100644 --- a/spec/neo4j/core/cypher_session/adaptors/http_spec.rb +++ b/spec/neo4j/core/cypher_session/adaptors/http_spec.rb @@ -1,6 +1,7 @@ require 'spec_helper' require 'neo4j/core/cypher_session/adaptors/http' require './spec/neo4j/core/shared_examples/adaptor' +require './spec/neo4j/core/shared_examples/http' describe Neo4j::Core::CypherSession::Adaptors::HTTP do before(:all) { setup_http_request_subscription } @@ -22,6 +23,24 @@ expect { adaptor_class.new('bolt://localhost:7474').connect }.to raise_error ArgumentError, /Invalid URL/ expect { adaptor_class.new('foo://localhost:7474').connect }.to raise_error ArgumentError, /Invalid URL/ end + + it 'uses net_http_persistent by default' do + expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:net_http_persistent) + conn = adaptor_class.new(url).connect + end + + it 'passes the :http_adapter option to Faraday' do + expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:something) + conn = adaptor_class.new(url, http_adapter: :something).connect + end + + (Faraday::Adapter.instance_variable_get(:@registered_middleware).keys - [:test, :rack]).each do |adapter_name| + describe "the :#{adapter_name} adapter" do + let(:http_adapter) { adapter_name } + it_behaves_like 'Neo4j::Core::CypherSession::Adaptors::Http' + end + end + end let(:session_double) { double('session', adaptor: subject) } diff --git a/spec/neo4j/core/shared_examples/http.rb b/spec/neo4j/core/shared_examples/http.rb new file mode 100644 index 00000000..0c52f961 --- /dev/null +++ b/spec/neo4j/core/shared_examples/http.rb @@ -0,0 +1,6 @@ +# Requires that an `http_adaptor` let variable exist with the Faraday adaptor name +RSpec.shared_examples 'Neo4j::Core::CypherSession::Adaptors::Http' do + it "should connect properly" do + subject.class.new(url, http_adapter: http_adapter).connect.get('/') + end +end \ No newline at end of file From b011c46c4fee73c96e2b4c5ab80b8ceb8c2eb3e2 Mon Sep 17 00:00:00 2001 From: Bruce Krysiak Date: Thu, 17 Nov 2016 18:48:43 -0800 Subject: [PATCH 02/19] Harmonizing adaptor spelling --- README.md | 6 +++--- lib/neo4j/core/cypher_session/adaptors/http.rb | 12 ++++++------ spec/neo4j/core/cypher_session/adaptors/http_spec.rb | 10 +++++----- spec/neo4j/core/shared_examples/http.rb | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 4b1a1596..810cce7e 100644 --- a/README.md +++ b/README.md @@ -15,11 +15,11 @@ To make a basic connection to Neo4j to execute Cypher queries, first choose an a neo4j_adaptor = Neo4j::Core::CypherSession::Adaptors::Embedded.new('/file/path/to/graph.db') -The `http_adapter` can also take an `:http_adapter` option for `Faraday` (defaulting to `:net_http_persistent`): +The `http_adaptor` can also take an `:http_adaptor` option for `Faraday` (defaulting to `:net_http_persistent`): - http_adaptor = Neo4j::Core::CypherSession::Adaptors::HTTP.new('http://neo4j:pass@localhost:7474', http_adapter: :typhoeus) + http_adaptor = Neo4j::Core::CypherSession::Adaptors::HTTP.new('http://neo4j:pass@localhost:7474', http_adaptor: :typhoeus) -Note you **must** install any required http adapter gems yourself as per [Faraday](https://github.com/lostisland/faraday). Ex for `:typhoeus`, add to your Gemfile: +Note you **must** install any required http adaptor gems yourself as per [Faraday](https://github.com/lostisland/faraday). Ex for `:typhoeus`, add to your Gemfile: gem 'typhoeus' diff --git a/lib/neo4j/core/cypher_session/adaptors/http.rb b/lib/neo4j/core/cypher_session/adaptors/http.rb index dc4e11fa..86b11009 100644 --- a/lib/neo4j/core/cypher_session/adaptors/http.rb +++ b/lib/neo4j/core/cypher_session/adaptors/http.rb @@ -16,7 +16,7 @@ def initialize(url, options = {}) end def connect - @requestor = Requestor.new(@url, USER_AGENT_STRING, self.class.method(:instrument_request), @options[:http_adapter]) + @requestor = Requestor.new(@url, USER_AGENT_STRING, self.class.method(:instrument_request), @options[:http_adaptor]) rescue Faraday::ConnectionFailed => e raise CypherSession::ConnectionFailedError, "#{e.class}: #{e.message}" end @@ -94,12 +94,12 @@ class Requestor default_url('http://neo4:neo4j@localhost:7474') validate_uri { |uri| uri.is_a?(URI::HTTP) } - def initialize(url, user_agent_string, instrument_proc, adapter) + def initialize(url, user_agent_string, instrument_proc, adaptor) self.url = url @user = user @password = password @user_agent_string = user_agent_string - @faraday = faraday_connection(adapter) + @faraday = faraday_connection(adaptor) @instrument_proc = instrument_proc end @@ -134,17 +134,17 @@ def get(path, body = '', options = {}) private - def faraday_connection(adapter) + def faraday_connection(adaptor) require 'faraday' require 'faraday_middleware/multi_json' - require 'typhoeus/adapters/faraday' if adapter == :typhoeus + require 'typhoeus/adapters/faraday' if adaptor == :typhoeus Faraday.new(url) do |c| c.request :basic_auth, user, password c.request :multi_json c.response :multi_json, symbolize_keys: true, content_type: 'application/json' - c.adapter(adapter || :net_http_persistent) + c.adapter(adaptor || :net_http_persistent) # c.response :logger, ::Logger.new(STDOUT), bodies: true diff --git a/spec/neo4j/core/cypher_session/adaptors/http_spec.rb b/spec/neo4j/core/cypher_session/adaptors/http_spec.rb index c17bd7f1..170080ea 100644 --- a/spec/neo4j/core/cypher_session/adaptors/http_spec.rb +++ b/spec/neo4j/core/cypher_session/adaptors/http_spec.rb @@ -29,14 +29,14 @@ conn = adaptor_class.new(url).connect end - it 'passes the :http_adapter option to Faraday' do + it 'passes the :http_adaptor option to Faraday' do expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:something) - conn = adaptor_class.new(url, http_adapter: :something).connect + conn = adaptor_class.new(url, http_adaptor: :something).connect end - (Faraday::Adapter.instance_variable_get(:@registered_middleware).keys - [:test, :rack]).each do |adapter_name| - describe "the :#{adapter_name} adapter" do - let(:http_adapter) { adapter_name } + (Faraday::Adapter.instance_variable_get(:@registered_middleware).keys - [:test, :rack]).each do |adaptor_name| + describe "the :#{adaptor_name} adaptor" do + let(:http_adaptor) { adaptor_name } it_behaves_like 'Neo4j::Core::CypherSession::Adaptors::Http' end end diff --git a/spec/neo4j/core/shared_examples/http.rb b/spec/neo4j/core/shared_examples/http.rb index 0c52f961..c15672f4 100644 --- a/spec/neo4j/core/shared_examples/http.rb +++ b/spec/neo4j/core/shared_examples/http.rb @@ -1,6 +1,6 @@ # Requires that an `http_adaptor` let variable exist with the Faraday adaptor name RSpec.shared_examples 'Neo4j::Core::CypherSession::Adaptors::Http' do it "should connect properly" do - subject.class.new(url, http_adapter: http_adapter).connect.get('/') + subject.class.new(url, http_adaptor: http_adaptor).connect.get('/') end end \ No newline at end of file From 662fed4d3386d6d1f703ec842950162e577cf45b Mon Sep 17 00:00:00 2001 From: Bruce Krysiak Date: Thu, 17 Nov 2016 19:12:46 -0800 Subject: [PATCH 03/19] Fixing rubocop --- spec/neo4j/core/cypher_session/adaptors/http_spec.rb | 4 ++-- spec/neo4j/core/shared_examples/http.rb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/neo4j/core/cypher_session/adaptors/http_spec.rb b/spec/neo4j/core/cypher_session/adaptors/http_spec.rb index 170080ea..79019b1f 100644 --- a/spec/neo4j/core/cypher_session/adaptors/http_spec.rb +++ b/spec/neo4j/core/cypher_session/adaptors/http_spec.rb @@ -26,12 +26,12 @@ it 'uses net_http_persistent by default' do expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:net_http_persistent) - conn = adaptor_class.new(url).connect + adaptor_class.new(url).connect end it 'passes the :http_adaptor option to Faraday' do expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:something) - conn = adaptor_class.new(url, http_adaptor: :something).connect + adaptor_class.new(url, http_adaptor: :something).connect end (Faraday::Adapter.instance_variable_get(:@registered_middleware).keys - [:test, :rack]).each do |adaptor_name| diff --git a/spec/neo4j/core/shared_examples/http.rb b/spec/neo4j/core/shared_examples/http.rb index c15672f4..75af56a9 100644 --- a/spec/neo4j/core/shared_examples/http.rb +++ b/spec/neo4j/core/shared_examples/http.rb @@ -1,6 +1,6 @@ # Requires that an `http_adaptor` let variable exist with the Faraday adaptor name RSpec.shared_examples 'Neo4j::Core::CypherSession::Adaptors::Http' do - it "should connect properly" do + it 'should connect properly' do subject.class.new(url, http_adaptor: http_adaptor).connect.get('/') end -end \ No newline at end of file +end From f270f530d3cbcbaf9c34fd991361386de8b95c3a Mon Sep 17 00:00:00 2001 From: Bruce Krysiak Date: Thu, 17 Nov 2016 19:26:14 -0800 Subject: [PATCH 04/19] Fixing rubocop --- spec/neo4j/core/cypher_session/adaptors/http_spec.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/neo4j/core/cypher_session/adaptors/http_spec.rb b/spec/neo4j/core/cypher_session/adaptors/http_spec.rb index 79019b1f..ebc2ff01 100644 --- a/spec/neo4j/core/cypher_session/adaptors/http_spec.rb +++ b/spec/neo4j/core/cypher_session/adaptors/http_spec.rb @@ -40,7 +40,6 @@ it_behaves_like 'Neo4j::Core::CypherSession::Adaptors::Http' end end - end let(:session_double) { double('session', adaptor: subject) } From 7dbcf0a326262835be3f0af1c5ebe51b6e3e2b4e Mon Sep 17 00:00:00 2001 From: Bruce Krysiak Date: Thu, 17 Nov 2016 20:43:38 -0800 Subject: [PATCH 05/19] Trying to fix JRuby --- Gemfile | 7 +++---- spec/neo4j/core/cypher_session/adaptors/http_spec.rb | 4 +++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Gemfile b/Gemfile index 37c65c28..08d4209c 100644 --- a/Gemfile +++ b/Gemfile @@ -25,10 +25,9 @@ group 'test' do gem 'dotenv' gem 'activesupport', '~> 4.0' - gem 'em-http-request', '>= 1.1', require: 'em-http' - gem 'em-synchrony', '>= 1.0.3', require: ['em-synchrony', 'em-synchrony/em-http'] + gem 'em-http-request', '>= 1.1', require: 'em-http', platforms: :ruby + gem 'em-synchrony', '>= 1.0.3', require: ['em-synchrony', 'em-synchrony/em-http'], platforms: :ruby gem 'excon', '>= 0.27.4' gem 'patron', '>= 0.4.2', platforms: :ruby - gem 'rack-test', '>= 0.6', require: 'rack/test' - gem 'typhoeus', '>= 0.3.3', platforms: [:ruby_18, :ruby_19, :ruby_20, :ruby_21, :ruby_22, :ruby_23] + gem 'typhoeus', '>= 0.3.3' end diff --git a/spec/neo4j/core/cypher_session/adaptors/http_spec.rb b/spec/neo4j/core/cypher_session/adaptors/http_spec.rb index ebc2ff01..8efc544a 100644 --- a/spec/neo4j/core/cypher_session/adaptors/http_spec.rb +++ b/spec/neo4j/core/cypher_session/adaptors/http_spec.rb @@ -34,7 +34,9 @@ adaptor_class.new(url, http_adaptor: :something).connect end - (Faraday::Adapter.instance_variable_get(:@registered_middleware).keys - [:test, :rack]).each do |adaptor_name| + adaptors = Faraday::Adapter.instance_variable_get(:@registered_middleware).keys - [:test, :rack] + adaptors -= [:patron, :em_synchrony, :em_http] if RUBY_PLATFORM == 'java' + adaptors.each do |adaptor_name| describe "the :#{adaptor_name} adaptor" do let(:http_adaptor) { adaptor_name } it_behaves_like 'Neo4j::Core::CypherSession::Adaptors::Http' From f9c2f31ee12befd60f6ee8053ddecd2e9ea5e935 Mon Sep 17 00:00:00 2001 From: Bruce Krysiak Date: Thu, 17 Nov 2016 22:36:06 -0800 Subject: [PATCH 06/19] Fixing Gemfile dependency --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 08d4209c..09e2ffad 100644 --- a/Gemfile +++ b/Gemfile @@ -23,7 +23,7 @@ group 'test' do gem 'rspec', '~> 3.0' gem 'rspec-its' gem 'dotenv' - gem 'activesupport', '~> 4.0' + gem 'activesupport', '>= 4.0' gem 'em-http-request', '>= 1.1', require: 'em-http', platforms: :ruby gem 'em-synchrony', '>= 1.0.3', require: ['em-synchrony', 'em-synchrony/em-http'], platforms: :ruby From f376dc9c73e74112ebae75ca39e3db6d0d3e9815 Mon Sep 17 00:00:00 2001 From: Bruce Krysiak Date: Thu, 17 Nov 2016 23:16:44 -0800 Subject: [PATCH 07/19] Hopefully actually fixing the Gemfile dependency issue --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 09e2ffad..1cd08ee4 100644 --- a/Gemfile +++ b/Gemfile @@ -23,7 +23,7 @@ group 'test' do gem 'rspec', '~> 3.0' gem 'rspec-its' gem 'dotenv' - gem 'activesupport', '>= 4.0' + gem 'activesupport', RUBY_VERSION.to_f >= 2.2 ? '>= 4.0' : '~> 4' gem 'em-http-request', '>= 1.1', require: 'em-http', platforms: :ruby gem 'em-synchrony', '>= 1.0.3', require: ['em-synchrony', 'em-synchrony/em-http'], platforms: :ruby From eee66ccce3ee1318102f38bd3ebc3fa66e7bbe48 Mon Sep 17 00:00:00 2001 From: Bruce Krysiak Date: Fri, 18 Nov 2016 01:24:08 -0800 Subject: [PATCH 08/19] Allow string http_adaptor keys --- lib/neo4j-server/cypher_session.rb | 6 ++-- .../core/cypher_session/adaptors/http.rb | 3 +- spec/neo4j-server/e2e/cypher_session_spec.rb | 14 ++++++++ .../core/cypher_session/adaptors/http_spec.rb | 35 +++++++++++-------- 4 files changed, 41 insertions(+), 17 deletions(-) diff --git a/lib/neo4j-server/cypher_session.rb b/lib/neo4j-server/cypher_session.rb index 14e470ef..5b394c7c 100644 --- a/lib/neo4j-server/cypher_session.rb +++ b/lib/neo4j-server/cypher_session.rb @@ -23,6 +23,9 @@ def initialize(data_url, connection) # @return [Faraday] # @see https://github.com/lostisland/faraday def self.create_connection(params, url = nil) + http_adaptor = (params.delete(:http_adaptor) || params.delete('http_adaptor') || :net_http_persistent).to_sym + require 'typhoeus/adapters/faraday' if http_adaptor == :typhoeus + init_params = params[:initialize] && params.delete(:initialize) conn = Faraday.new(url, init_params) do |b| b.request :basic_auth, params[:basic_auth][:username], params[:basic_auth][:password] if params[:basic_auth] @@ -31,8 +34,7 @@ def self.create_connection(params, url = nil) b.response :multi_json, symbolize_keys: true, content_type: 'application/json' # b.use Faraday::Response::RaiseError - b.adapter :net_http_persistent - # b.adapter Faraday.default_adapter + b.adapter http_adaptor end conn.headers = {'Content-Type' => 'application/json', 'User-Agent' => ::Neo4j::Session.user_agent_string} conn diff --git a/lib/neo4j/core/cypher_session/adaptors/http.rb b/lib/neo4j/core/cypher_session/adaptors/http.rb index 86b11009..92da5297 100644 --- a/lib/neo4j/core/cypher_session/adaptors/http.rb +++ b/lib/neo4j/core/cypher_session/adaptors/http.rb @@ -16,7 +16,8 @@ def initialize(url, options = {}) end def connect - @requestor = Requestor.new(@url, USER_AGENT_STRING, self.class.method(:instrument_request), @options[:http_adaptor]) + @requestor = Requestor.new(@url, USER_AGENT_STRING, self.class.method(:instrument_request), + @options[:http_adaptor] || @options['http_adaptor']) rescue Faraday::ConnectionFailed => e raise CypherSession::ConnectionFailedError, "#{e.class}: #{e.message}" end diff --git a/spec/neo4j-server/e2e/cypher_session_spec.rb b/spec/neo4j-server/e2e/cypher_session_spec.rb index 163f5a47..1c93e98b 100644 --- a/spec/neo4j-server/e2e/cypher_session_spec.rb +++ b/spec/neo4j-server/e2e/cypher_session_spec.rb @@ -37,6 +37,20 @@ def open_session expect(connection.port).to eq ENV['NEO4J_URL'] ? URI(ENV['NEO4J_URL']).port : 7474 expect(connection.host).to eq 'localhost' end + + describe 'a faraday connection type http_adaptor param' do + it 'will pass through a symbol key' do + # expect(Neo4j::Server::CypherSession).to receive(:open).with(anything, hash_including(http_adaptor: :something)) + expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:typhoeus).and_call_original + create_server_session(http_adaptor: :typhoeus) + end + + it "will pass through a string key" do + # expect(Neo4j::Server::CypherSession).to receive(:open).with(anything, hash_including('http_adaptor' => :something)) + expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:typhoeus).and_call_original + create_server_session('http_adaptor' => :typhoeus) + end + end end diff --git a/spec/neo4j/core/cypher_session/adaptors/http_spec.rb b/spec/neo4j/core/cypher_session/adaptors/http_spec.rb index 8efc544a..9db13d52 100644 --- a/spec/neo4j/core/cypher_session/adaptors/http_spec.rb +++ b/spec/neo4j/core/cypher_session/adaptors/http_spec.rb @@ -24,22 +24,29 @@ expect { adaptor_class.new('foo://localhost:7474').connect }.to raise_error ArgumentError, /Invalid URL/ end - it 'uses net_http_persistent by default' do - expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:net_http_persistent) - adaptor_class.new(url).connect - end + describe 'the http_adaptor option for Faraday' do + it 'uses net_http_persistent by default' do + expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:net_http_persistent) + adaptor_class.new(url).connect + end - it 'passes the :http_adaptor option to Faraday' do - expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:something) - adaptor_class.new(url, http_adaptor: :something).connect - end + it 'will pass through a symbol key' do + expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:something) + adaptor_class.new(url, http_adaptor: :something).connect + end - adaptors = Faraday::Adapter.instance_variable_get(:@registered_middleware).keys - [:test, :rack] - adaptors -= [:patron, :em_synchrony, :em_http] if RUBY_PLATFORM == 'java' - adaptors.each do |adaptor_name| - describe "the :#{adaptor_name} adaptor" do - let(:http_adaptor) { adaptor_name } - it_behaves_like 'Neo4j::Core::CypherSession::Adaptors::Http' + it 'will pass through a string key' do + expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:something) + adaptor_class.new(url, 'http_adaptor' => :something).connect + end + + adaptors = Faraday::Adapter.instance_variable_get(:@registered_middleware).keys - [:test, :rack] + adaptors -= [:patron, :em_synchrony, :em_http] if RUBY_PLATFORM == 'java' + adaptors.each do |adaptor_name| + describe "the :#{adaptor_name} adaptor" do + let(:http_adaptor) { adaptor_name } + it_behaves_like 'Neo4j::Core::CypherSession::Adaptors::Http' + end end end end From ca48b3482bc1e0595ccb07e3e67017d5b519b486 Mon Sep 17 00:00:00 2001 From: Bruce Krysiak Date: Fri, 18 Nov 2016 02:27:35 -0800 Subject: [PATCH 09/19] Rubocop --- .rubocop_todo.yml | 27 ++++++++------------ spec/neo4j-server/e2e/cypher_session_spec.rb | 2 +- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 7b1d23ba..5ea50368 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2016-03-28 20:14:45 +0900 using RuboCop version 0.39.0. +# on 2016-11-18 02:25:11 -0800 using RuboCop version 0.39.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -31,22 +31,22 @@ Lint/UnusedMethodArgument: - 'lib/neo4j/relationship.rb' - 'lib/neo4j/session.rb' -# Offense count: 16 +# Offense count: 23 Metrics/AbcSize: - Max: 17 + Max: 20 -# Offense count: 9 +# Offense count: 12 # Configuration parameters: CountComments. Metrics/ClassLength: - Max: 191 + Max: 193 -# Offense count: 508 +# Offense count: 650 # Configuration parameters: AllowHeredoc, AllowURI, URISchemes. # URISchemes: http, https Metrics/LineLength: Max: 180 -# Offense count: 20 +# Offense count: 27 # Configuration parameters: CountComments. Metrics/MethodLength: Max: 14 @@ -54,7 +54,7 @@ Metrics/MethodLength: # Offense count: 1 # Configuration parameters: CountComments. Metrics/ModuleLength: - Max: 113 + Max: 123 # Offense count: 8 Style/AccessorMethodName: @@ -72,7 +72,7 @@ Style/ClassVars: Exclude: - 'lib/neo4j/session.rb' -# Offense count: 72 +# Offense count: 84 Style/Documentation: Enabled: false @@ -82,7 +82,7 @@ Style/GuardClause: Exclude: - 'lib/neo4j-core/query_clauses.rb' -# Offense count: 56 +# Offense count: 65 # Cop supports --auto-correct. Style/MutableConstant: Enabled: false @@ -92,10 +92,3 @@ Style/MutableConstant: Style/RedundantSelf: Exclude: - 'lib/neo4j-core/query_clauses.rb' - -# Offense count: 1 -# Cop supports --auto-correct. -Style/RescueEnsureAlignment: - Exclude: - - 'spec/shared_examples/node_with_tx.rb' - diff --git a/spec/neo4j-server/e2e/cypher_session_spec.rb b/spec/neo4j-server/e2e/cypher_session_spec.rb index 1c93e98b..60df7a46 100644 --- a/spec/neo4j-server/e2e/cypher_session_spec.rb +++ b/spec/neo4j-server/e2e/cypher_session_spec.rb @@ -45,7 +45,7 @@ def open_session create_server_session(http_adaptor: :typhoeus) end - it "will pass through a string key" do + it 'will pass through a string key' do # expect(Neo4j::Server::CypherSession).to receive(:open).with(anything, hash_including('http_adaptor' => :something)) expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:typhoeus).and_call_original create_server_session('http_adaptor' => :typhoeus) From 074ca27c4315ebe96d802d1531925181287d0289 Mon Sep 17 00:00:00 2001 From: Bruce Krysiak Date: Mon, 21 Nov 2016 15:44:32 -0800 Subject: [PATCH 10/19] Changing http_adaptor initialization to faraday_options --- README.md | 4 +- lib/neo4j-server/cypher_session.rb | 7 ++-- .../core/cypher_session/adaptors/http.rb | 13 +++--- spec/neo4j-server/e2e/cypher_session_spec.rb | 22 +++++----- .../core/cypher_session/adaptors/http_spec.rb | 40 ++++++++++--------- spec/neo4j/core/shared_examples/http.rb | 2 +- 6 files changed, 47 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 810cce7e..c536fcb9 100644 --- a/README.md +++ b/README.md @@ -15,9 +15,9 @@ To make a basic connection to Neo4j to execute Cypher queries, first choose an a neo4j_adaptor = Neo4j::Core::CypherSession::Adaptors::Embedded.new('/file/path/to/graph.db') -The `http_adaptor` can also take an `:http_adaptor` option for `Faraday` (defaulting to `:net_http_persistent`): +The `http_adaptor` can also take `:faraday_options`. Currently, only :adapter is supported (defaulting to `:net_http_persistent`): - http_adaptor = Neo4j::Core::CypherSession::Adaptors::HTTP.new('http://neo4j:pass@localhost:7474', http_adaptor: :typhoeus) + http_adaptor = Neo4j::Core::CypherSession::Adaptors::HTTP.new('http://neo4j:pass@localhost:7474', faraday_options: { adaptor: :typhoeus }) Note you **must** install any required http adaptor gems yourself as per [Faraday](https://github.com/lostisland/faraday). Ex for `:typhoeus`, add to your Gemfile: diff --git a/lib/neo4j-server/cypher_session.rb b/lib/neo4j-server/cypher_session.rb index 5b394c7c..20bc043b 100644 --- a/lib/neo4j-server/cypher_session.rb +++ b/lib/neo4j-server/cypher_session.rb @@ -23,8 +23,9 @@ def initialize(data_url, connection) # @return [Faraday] # @see https://github.com/lostisland/faraday def self.create_connection(params, url = nil) - http_adaptor = (params.delete(:http_adaptor) || params.delete('http_adaptor') || :net_http_persistent).to_sym - require 'typhoeus/adapters/faraday' if http_adaptor == :typhoeus + faraday_options = params.delete(:faraday_options) || params.delete('faraday_options') || {} + adapter = (faraday_options[:adapter] || faraday_options['adapter'] || :net_http_persistent).to_sym + require 'typhoeus/adapters/faraday' if adapter == :typhoeus init_params = params[:initialize] && params.delete(:initialize) conn = Faraday.new(url, init_params) do |b| @@ -34,7 +35,7 @@ def self.create_connection(params, url = nil) b.response :multi_json, symbolize_keys: true, content_type: 'application/json' # b.use Faraday::Response::RaiseError - b.adapter http_adaptor + b.adapter adapter end conn.headers = {'Content-Type' => 'application/json', 'User-Agent' => ::Neo4j::Session.user_agent_string} conn diff --git a/lib/neo4j/core/cypher_session/adaptors/http.rb b/lib/neo4j/core/cypher_session/adaptors/http.rb index 92da5297..e367dfcb 100644 --- a/lib/neo4j/core/cypher_session/adaptors/http.rb +++ b/lib/neo4j/core/cypher_session/adaptors/http.rb @@ -17,7 +17,7 @@ def initialize(url, options = {}) def connect @requestor = Requestor.new(@url, USER_AGENT_STRING, self.class.method(:instrument_request), - @options[:http_adaptor] || @options['http_adaptor']) + @options[:faraday_options] || @options['faraday_options'] || {}) rescue Faraday::ConnectionFailed => e raise CypherSession::ConnectionFailedError, "#{e.class}: #{e.message}" end @@ -95,12 +95,12 @@ class Requestor default_url('http://neo4:neo4j@localhost:7474') validate_uri { |uri| uri.is_a?(URI::HTTP) } - def initialize(url, user_agent_string, instrument_proc, adaptor) + def initialize(url, user_agent_string, instrument_proc, faraday_options) self.url = url @user = user @password = password @user_agent_string = user_agent_string - @faraday = faraday_connection(adaptor) + @faraday = faraday_connection(faraday_options) @instrument_proc = instrument_proc end @@ -135,17 +135,18 @@ def get(path, body = '', options = {}) private - def faraday_connection(adaptor) + def faraday_connection(faraday_options={}) + adapter = (faraday_options[:adapter] || faraday_options['adapter'] || :net_http_persistent).to_sym require 'faraday' require 'faraday_middleware/multi_json' - require 'typhoeus/adapters/faraday' if adaptor == :typhoeus + require 'typhoeus/adapters/faraday' if adapter == :typhoeus Faraday.new(url) do |c| c.request :basic_auth, user, password c.request :multi_json c.response :multi_json, symbolize_keys: true, content_type: 'application/json' - c.adapter(adaptor || :net_http_persistent) + c.adapter(adapter || :net_http_persistent) # c.response :logger, ::Logger.new(STDOUT), bodies: true diff --git a/spec/neo4j-server/e2e/cypher_session_spec.rb b/spec/neo4j-server/e2e/cypher_session_spec.rb index 60df7a46..833ddb77 100644 --- a/spec/neo4j-server/e2e/cypher_session_spec.rb +++ b/spec/neo4j-server/e2e/cypher_session_spec.rb @@ -38,17 +38,19 @@ def open_session expect(connection.host).to eq 'localhost' end - describe 'a faraday connection type http_adaptor param' do - it 'will pass through a symbol key' do - # expect(Neo4j::Server::CypherSession).to receive(:open).with(anything, hash_including(http_adaptor: :something)) - expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:typhoeus).and_call_original - create_server_session(http_adaptor: :typhoeus) - end + describe 'faraday_options' do + describe 'a faraday connection type adapter option' do + it 'will pass through a symbol key' do + # expect(Neo4j::Server::CypherSession).to receive(:open).with(anything, hash_including(http_adaptor: :something)) + expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:typhoeus).and_call_original + create_server_session(faraday_options: { adapter: :typhoeus }) + end - it 'will pass through a string key' do - # expect(Neo4j::Server::CypherSession).to receive(:open).with(anything, hash_including('http_adaptor' => :something)) - expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:typhoeus).and_call_original - create_server_session('http_adaptor' => :typhoeus) + it 'will pass through a string key' do + # expect(Neo4j::Server::CypherSession).to receive(:open).with(anything, hash_including('http_adaptor' => :something)) + expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:typhoeus).and_call_original + create_server_session('faraday_options' => { 'adapter' => :typhoeus }) + end end end end diff --git a/spec/neo4j/core/cypher_session/adaptors/http_spec.rb b/spec/neo4j/core/cypher_session/adaptors/http_spec.rb index 9db13d52..7c287976 100644 --- a/spec/neo4j/core/cypher_session/adaptors/http_spec.rb +++ b/spec/neo4j/core/cypher_session/adaptors/http_spec.rb @@ -24,28 +24,30 @@ expect { adaptor_class.new('foo://localhost:7474').connect }.to raise_error ArgumentError, /Invalid URL/ end - describe 'the http_adaptor option for Faraday' do - it 'uses net_http_persistent by default' do - expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:net_http_persistent) - adaptor_class.new(url).connect - end + describe 'the faraday_options param' do + describe 'the adapter option' do + it 'uses net_http_persistent by default' do + expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:net_http_persistent) + adaptor_class.new(url).connect + end - it 'will pass through a symbol key' do - expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:something) - adaptor_class.new(url, http_adaptor: :something).connect - end + it 'will pass through a symbol key' do + expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:something) + adaptor_class.new(url, faraday_options: { adapter: :something }).connect + end - it 'will pass through a string key' do - expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:something) - adaptor_class.new(url, 'http_adaptor' => :something).connect - end + it 'will pass through a string key' do + expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:something) + adaptor_class.new(url, 'faraday_options' => { 'adapter' => :something }).connect + end - adaptors = Faraday::Adapter.instance_variable_get(:@registered_middleware).keys - [:test, :rack] - adaptors -= [:patron, :em_synchrony, :em_http] if RUBY_PLATFORM == 'java' - adaptors.each do |adaptor_name| - describe "the :#{adaptor_name} adaptor" do - let(:http_adaptor) { adaptor_name } - it_behaves_like 'Neo4j::Core::CypherSession::Adaptors::Http' + adaptors = Faraday::Adapter.instance_variable_get(:@registered_middleware).keys - [:test, :rack] + adaptors -= [:patron, :em_synchrony, :em_http] if RUBY_PLATFORM == 'java' + adaptors.each do |adapter_name| + describe "the :#{adapter_name} adapter" do + let(:http_adapter) { adapter_name } + it_behaves_like 'Neo4j::Core::CypherSession::Adaptors::Http' + end end end end diff --git a/spec/neo4j/core/shared_examples/http.rb b/spec/neo4j/core/shared_examples/http.rb index 75af56a9..dc0e9047 100644 --- a/spec/neo4j/core/shared_examples/http.rb +++ b/spec/neo4j/core/shared_examples/http.rb @@ -1,6 +1,6 @@ # Requires that an `http_adaptor` let variable exist with the Faraday adaptor name RSpec.shared_examples 'Neo4j::Core::CypherSession::Adaptors::Http' do it 'should connect properly' do - subject.class.new(url, http_adaptor: http_adaptor).connect.get('/') + subject.class.new(url, faraday_options: { adapter: http_adapter }).connect.get('/') end end From de0a304716cc119ed5501ced82157d356a8638fa Mon Sep 17 00:00:00 2001 From: Bruce Krysiak Date: Mon, 21 Nov 2016 15:50:18 -0800 Subject: [PATCH 11/19] Rubocop --- .rubocop_todo.yml | 20 +++++++++++++------ .../core/cypher_session/adaptors/http.rb | 2 +- spec/neo4j-server/e2e/cypher_session_spec.rb | 4 ++-- .../core/cypher_session/adaptors/http_spec.rb | 4 ++-- spec/neo4j/core/shared_examples/http.rb | 2 +- 5 files changed, 20 insertions(+), 12 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 5ea50368..4f4b3b4b 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2016-11-18 02:25:11 -0800 using RuboCop version 0.39.0. +# on 2016-11-21 15:47:20 -0800 using RuboCop version 0.39.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -31,16 +31,20 @@ Lint/UnusedMethodArgument: - 'lib/neo4j/relationship.rb' - 'lib/neo4j/session.rb' -# Offense count: 23 +# Offense count: 24 Metrics/AbcSize: - Max: 20 + Max: 22 # Offense count: 12 # Configuration parameters: CountComments. Metrics/ClassLength: - Max: 193 + Max: 194 -# Offense count: 650 +# Offense count: 1 +Metrics/CyclomaticComplexity: + Max: 8 + +# Offense count: 657 # Configuration parameters: AllowHeredoc, AllowURI, URISchemes. # URISchemes: http, https Metrics/LineLength: @@ -54,7 +58,11 @@ Metrics/MethodLength: # Offense count: 1 # Configuration parameters: CountComments. Metrics/ModuleLength: - Max: 123 + Max: 125 + +# Offense count: 1 +Metrics/PerceivedComplexity: + Max: 8 # Offense count: 8 Style/AccessorMethodName: diff --git a/lib/neo4j/core/cypher_session/adaptors/http.rb b/lib/neo4j/core/cypher_session/adaptors/http.rb index e367dfcb..7071716e 100644 --- a/lib/neo4j/core/cypher_session/adaptors/http.rb +++ b/lib/neo4j/core/cypher_session/adaptors/http.rb @@ -135,7 +135,7 @@ def get(path, body = '', options = {}) private - def faraday_connection(faraday_options={}) + def faraday_connection(faraday_options = {}) adapter = (faraday_options[:adapter] || faraday_options['adapter'] || :net_http_persistent).to_sym require 'faraday' require 'faraday_middleware/multi_json' diff --git a/spec/neo4j-server/e2e/cypher_session_spec.rb b/spec/neo4j-server/e2e/cypher_session_spec.rb index 833ddb77..480f3594 100644 --- a/spec/neo4j-server/e2e/cypher_session_spec.rb +++ b/spec/neo4j-server/e2e/cypher_session_spec.rb @@ -43,13 +43,13 @@ def open_session it 'will pass through a symbol key' do # expect(Neo4j::Server::CypherSession).to receive(:open).with(anything, hash_including(http_adaptor: :something)) expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:typhoeus).and_call_original - create_server_session(faraday_options: { adapter: :typhoeus }) + create_server_session(faraday_options: {adapter: :typhoeus}) end it 'will pass through a string key' do # expect(Neo4j::Server::CypherSession).to receive(:open).with(anything, hash_including('http_adaptor' => :something)) expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:typhoeus).and_call_original - create_server_session('faraday_options' => { 'adapter' => :typhoeus }) + create_server_session('faraday_options' => {'adapter' => :typhoeus}) end end end diff --git a/spec/neo4j/core/cypher_session/adaptors/http_spec.rb b/spec/neo4j/core/cypher_session/adaptors/http_spec.rb index 7c287976..cdecb4ca 100644 --- a/spec/neo4j/core/cypher_session/adaptors/http_spec.rb +++ b/spec/neo4j/core/cypher_session/adaptors/http_spec.rb @@ -33,12 +33,12 @@ it 'will pass through a symbol key' do expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:something) - adaptor_class.new(url, faraday_options: { adapter: :something }).connect + adaptor_class.new(url, faraday_options: {adapter: :something}).connect end it 'will pass through a string key' do expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:something) - adaptor_class.new(url, 'faraday_options' => { 'adapter' => :something }).connect + adaptor_class.new(url, 'faraday_options' => {'adapter' => :something}).connect end adaptors = Faraday::Adapter.instance_variable_get(:@registered_middleware).keys - [:test, :rack] diff --git a/spec/neo4j/core/shared_examples/http.rb b/spec/neo4j/core/shared_examples/http.rb index dc0e9047..e0d06bb6 100644 --- a/spec/neo4j/core/shared_examples/http.rb +++ b/spec/neo4j/core/shared_examples/http.rb @@ -1,6 +1,6 @@ # Requires that an `http_adaptor` let variable exist with the Faraday adaptor name RSpec.shared_examples 'Neo4j::Core::CypherSession::Adaptors::Http' do it 'should connect properly' do - subject.class.new(url, faraday_options: { adapter: http_adapter }).connect.get('/') + subject.class.new(url, faraday_options: {adapter: http_adapter}).connect.get('/') end end From b03503944fbd1dd4ce8d55f1a8c3e27448717088 Mon Sep 17 00:00:00 2001 From: Bruce Krysiak Date: Mon, 21 Nov 2016 16:12:17 -0800 Subject: [PATCH 12/19] Fixing docs --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c536fcb9..9af0b96c 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ To make a basic connection to Neo4j to execute Cypher queries, first choose an a The `http_adaptor` can also take `:faraday_options`. Currently, only :adapter is supported (defaulting to `:net_http_persistent`): - http_adaptor = Neo4j::Core::CypherSession::Adaptors::HTTP.new('http://neo4j:pass@localhost:7474', faraday_options: { adaptor: :typhoeus }) + http_adaptor = Neo4j::Core::CypherSession::Adaptors::HTTP.new('http://neo4j:pass@localhost:7474', faraday_options: { adapter: :typhoeus }) Note you **must** install any required http adaptor gems yourself as per [Faraday](https://github.com/lostisland/faraday). Ex for `:typhoeus`, add to your Gemfile: From d66d47ca86b81665e0bef015c01c78a50c4786d7 Mon Sep 17 00:00:00 2001 From: Bruce Krysiak Date: Thu, 1 Dec 2016 22:14:46 -0800 Subject: [PATCH 13/19] Reverting rubocop_todo.yml and fixing issues --- .rubocop_todo.yml | 6 ++-- Gemfile | 1 + lib/neo4j-server/cypher_session.rb | 27 ++++++++++------ .../adaptors/faraday_helpers.rb | 17 ++++++++++ .../core/cypher_session/adaptors/http.rb | 5 +-- .../cypher_session/shared_examples/adaptor.rb | 29 +++++++++++++++++ spec/neo4j-server/e2e/cypher_session_spec.rb | 32 ++----------------- spec/neo4j/core/shared_examples/http.rb | 2 +- 8 files changed, 73 insertions(+), 46 deletions(-) create mode 100644 lib/neo4j/core/cypher_session/adaptors/faraday_helpers.rb create mode 100644 spec/neo4j-server/cypher_session/shared_examples/adaptor.rb diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 4f4b3b4b..f5654dae 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -33,12 +33,12 @@ Lint/UnusedMethodArgument: # Offense count: 24 Metrics/AbcSize: - Max: 22 + Max: 17 # Offense count: 12 # Configuration parameters: CountComments. Metrics/ClassLength: - Max: 194 + Max: 191 # Offense count: 1 Metrics/CyclomaticComplexity: @@ -58,7 +58,7 @@ Metrics/MethodLength: # Offense count: 1 # Configuration parameters: CountComments. Metrics/ModuleLength: - Max: 125 + Max: 113 # Offense count: 1 Metrics/PerceivedComplexity: diff --git a/Gemfile b/Gemfile index 1cd08ee4..741c9c13 100644 --- a/Gemfile +++ b/Gemfile @@ -30,4 +30,5 @@ group 'test' do gem 'excon', '>= 0.27.4' gem 'patron', '>= 0.4.2', platforms: :ruby gem 'typhoeus', '>= 0.3.3' + gem 'byebug' end diff --git a/lib/neo4j-server/cypher_session.rb b/lib/neo4j-server/cypher_session.rb index 20bc043b..0e6e5439 100644 --- a/lib/neo4j-server/cypher_session.rb +++ b/lib/neo4j-server/cypher_session.rb @@ -1,4 +1,5 @@ require 'uri' +require 'neo4j/core/cypher_session/adaptors/faraday_helpers' module Neo4j module Server @@ -7,7 +8,22 @@ module Server end class CypherSession < Neo4j::Session + module PrivateMethods + private + + def extract_adapter_from_options(params) + extract_adapter(params.delete(:faraday_options) || params.delete('faraday_options') || {}) + end + + def extract_basic_auth(url, params) + return unless url && URI(url).userinfo + params[:basic_auth] = {username: URI(url).user, password: URI(url).password} + end + end + include Resource + extend Neo4j::Core::CypherSession::Adaptors::FaradayHelpers + extend Neo4j::Server::CypherSession::PrivateMethods alias super_query query attr_reader :connection @@ -23,9 +39,7 @@ def initialize(data_url, connection) # @return [Faraday] # @see https://github.com/lostisland/faraday def self.create_connection(params, url = nil) - faraday_options = params.delete(:faraday_options) || params.delete('faraday_options') || {} - adapter = (faraday_options[:adapter] || faraday_options['adapter'] || :net_http_persistent).to_sym - require 'typhoeus/adapters/faraday' if adapter == :typhoeus + adapter = extract_adapter_from_options(params) init_params = params[:initialize] && params.delete(:initialize) conn = Faraday.new(url, init_params) do |b| @@ -61,13 +75,6 @@ def self.establish_session(root_data, connection) CypherSession.new(data_url, connection) end - def self.extract_basic_auth(url, params) - return unless url && URI(url).userinfo - params[:basic_auth] = {username: URI(url).user, password: URI(url).password} - end - - private_class_method :extract_basic_auth - def db_type :server_db end diff --git a/lib/neo4j/core/cypher_session/adaptors/faraday_helpers.rb b/lib/neo4j/core/cypher_session/adaptors/faraday_helpers.rb new file mode 100644 index 00000000..4285744d --- /dev/null +++ b/lib/neo4j/core/cypher_session/adaptors/faraday_helpers.rb @@ -0,0 +1,17 @@ +module Neo4j + module Core + class CypherSession + module Adaptors + module FaradayHelpers + private + + def extract_adapter(faraday_options = {}) + (faraday_options[:adapter] || faraday_options['adapter'] || :net_http_persistent).to_sym.tap do |adapter| + require 'typhoeus/adapters/faraday' if adapter == :typhoeus + end + end + end + end + end + end +end diff --git a/lib/neo4j/core/cypher_session/adaptors/http.rb b/lib/neo4j/core/cypher_session/adaptors/http.rb index 7071716e..3f8cbd23 100644 --- a/lib/neo4j/core/cypher_session/adaptors/http.rb +++ b/lib/neo4j/core/cypher_session/adaptors/http.rb @@ -1,5 +1,6 @@ require 'neo4j/core/cypher_session/adaptors' require 'neo4j/core/cypher_session/adaptors/has_uri' +require 'neo4j/core/cypher_session/adaptors/faraday_helpers' require 'neo4j/core/cypher_session/responses/http' # TODO: Work with `Query` objects @@ -92,6 +93,7 @@ def connected? # - Sets headers, including user agent string class Requestor include Adaptors::HasUri + include FaradayHelpers default_url('http://neo4:neo4j@localhost:7474') validate_uri { |uri| uri.is_a?(URI::HTTP) } @@ -136,10 +138,9 @@ def get(path, body = '', options = {}) private def faraday_connection(faraday_options = {}) - adapter = (faraday_options[:adapter] || faraday_options['adapter'] || :net_http_persistent).to_sym + adapter = extract_adapter(faraday_options) require 'faraday' require 'faraday_middleware/multi_json' - require 'typhoeus/adapters/faraday' if adapter == :typhoeus Faraday.new(url) do |c| c.request :basic_auth, user, password diff --git a/spec/neo4j-server/cypher_session/shared_examples/adaptor.rb b/spec/neo4j-server/cypher_session/shared_examples/adaptor.rb new file mode 100644 index 00000000..598071c3 --- /dev/null +++ b/spec/neo4j-server/cypher_session/shared_examples/adaptor.rb @@ -0,0 +1,29 @@ +RSpec.shared_examples 'Neo4j::Server::CypherSession::Adaptor' do + describe 'faraday_options' do + describe 'a faraday connection type adapter option' do + it 'can use a user supplied faraday connection for a new session' do + connection = Faraday.new do |faraday| + faraday.request :basic_auth, basic_auth_hash[:username], basic_auth_hash[:password] + + faraday.request :multi_json + faraday.response :multi_json, symbolize_keys: true, content_type: 'application/json' + faraday.adapter Faraday.default_adapter + end + connection.headers = {'Content-Type' => 'application/json'} + + expect(connection).to receive(:get).at_least(:once).and_call_original + create_server_session(connection: connection) + end + + it 'will pass through a symbol key' do + expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:typhoeus).and_call_original + create_server_session(faraday_options: {adapter: :typhoeus}) + end + + it 'will pass through a string key' do + expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:typhoeus).and_call_original + create_server_session('faraday_options' => {'adapter' => :typhoeus}) + end + end + end +end diff --git a/spec/neo4j-server/e2e/cypher_session_spec.rb b/spec/neo4j-server/e2e/cypher_session_spec.rb index 480f3594..3fe26327 100644 --- a/spec/neo4j-server/e2e/cypher_session_spec.rb +++ b/spec/neo4j-server/e2e/cypher_session_spec.rb @@ -1,4 +1,5 @@ require 'spec_helper' +require './spec/neo4j-server/cypher_session/shared_examples/adaptor' module Neo4j module Server @@ -18,44 +19,15 @@ def open_session Neo4j::Session.set_current(@before_session) end - it 'can use a user supplied faraday connection for a new session' do - connection = Faraday.new do |faraday| - faraday.request :basic_auth, basic_auth_hash[:username], basic_auth_hash[:password] - - faraday.request :multi_json - faraday.response :multi_json, symbolize_keys: true, content_type: 'application/json' - faraday.adapter Faraday.default_adapter - end - connection.headers = {'Content-Type' => 'application/json'} - - expect(connection).to receive(:get).at_least(:once).and_call_original - create_server_session(connection: connection) - end - it 'adds host and port to the connection object' do connection = Neo4j::Session.current.connection expect(connection.port).to eq ENV['NEO4J_URL'] ? URI(ENV['NEO4J_URL']).port : 7474 expect(connection.host).to eq 'localhost' end - describe 'faraday_options' do - describe 'a faraday connection type adapter option' do - it 'will pass through a symbol key' do - # expect(Neo4j::Server::CypherSession).to receive(:open).with(anything, hash_including(http_adaptor: :something)) - expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:typhoeus).and_call_original - create_server_session(faraday_options: {adapter: :typhoeus}) - end - - it 'will pass through a string key' do - # expect(Neo4j::Server::CypherSession).to receive(:open).with(anything, hash_including('http_adaptor' => :something)) - expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:typhoeus).and_call_original - create_server_session('faraday_options' => {'adapter' => :typhoeus}) - end - end - end + it_behaves_like 'Neo4j::Server::CypherSession::Adaptor' end - describe 'named sessions' do before { Neo4j::Session.current && Neo4j::Session.current.close } after { Neo4j::Session.current && Neo4j::Session.current.close } diff --git a/spec/neo4j/core/shared_examples/http.rb b/spec/neo4j/core/shared_examples/http.rb index e0d06bb6..9803a1fd 100644 --- a/spec/neo4j/core/shared_examples/http.rb +++ b/spec/neo4j/core/shared_examples/http.rb @@ -1,4 +1,4 @@ -# Requires that an `http_adaptor` let variable exist with the Faraday adaptor name +# Requires that an `http_adapter` let variable exist with the Faraday adaptor name RSpec.shared_examples 'Neo4j::Core::CypherSession::Adaptors::Http' do it 'should connect properly' do subject.class.new(url, faraday_options: {adapter: http_adapter}).connect.get('/') From 99e3b3f268cf33e7fa761e2811fc082e97358500 Mon Sep 17 00:00:00 2001 From: Bruce Krysiak Date: Fri, 2 Dec 2016 00:35:01 -0800 Subject: [PATCH 14/19] Allow passing in all faraday_options --- lib/neo4j-server/cypher_session.rb | 18 ++++----- .../adaptors/faraday_helpers.rb | 38 +++++++++++++++++-- .../core/cypher_session/adaptors/http.rb | 22 +++++------ 3 files changed, 55 insertions(+), 23 deletions(-) diff --git a/lib/neo4j-server/cypher_session.rb b/lib/neo4j-server/cypher_session.rb index 0e6e5439..3ba66b34 100644 --- a/lib/neo4j-server/cypher_session.rb +++ b/lib/neo4j-server/cypher_session.rb @@ -11,8 +11,8 @@ class CypherSession < Neo4j::Session module PrivateMethods private - def extract_adapter_from_options(params) - extract_adapter(params.delete(:faraday_options) || params.delete('faraday_options') || {}) + def extract_faraday_options(params, defaults = {}) + verify_faraday_options(params.delete(:faraday_options) || params.delete('faraday_options') || {}, defaults) end def extract_basic_auth(url, params) @@ -39,17 +39,17 @@ def initialize(data_url, connection) # @return [Faraday] # @see https://github.com/lostisland/faraday def self.create_connection(params, url = nil) - adapter = extract_adapter_from_options(params) - init_params = params[:initialize] && params.delete(:initialize) + + request = [:multi_json] + request.unshift([:basic_auth, params[:basic_auth][:username], params[:basic_auth][:password]]) if params[:basic_auth] + + faraday_options = extract_faraday_options( + params, request: request, response: [:multi_json, symbolize_keys: true, content_type: 'application/json']) conn = Faraday.new(url, init_params) do |b| - b.request :basic_auth, params[:basic_auth][:username], params[:basic_auth][:password] if params[:basic_auth] - b.request :multi_json # b.response :logger, ::Logger.new(STDOUT), bodies: true - - b.response :multi_json, symbolize_keys: true, content_type: 'application/json' # b.use Faraday::Response::RaiseError - b.adapter adapter + set_faraday_middleware b, faraday_options end conn.headers = {'Content-Type' => 'application/json', 'User-Agent' => ::Neo4j::Session.user_agent_string} conn diff --git a/lib/neo4j/core/cypher_session/adaptors/faraday_helpers.rb b/lib/neo4j/core/cypher_session/adaptors/faraday_helpers.rb index 4285744d..66f1d655 100644 --- a/lib/neo4j/core/cypher_session/adaptors/faraday_helpers.rb +++ b/lib/neo4j/core/cypher_session/adaptors/faraday_helpers.rb @@ -5,9 +5,41 @@ module Adaptors module FaradayHelpers private - def extract_adapter(faraday_options = {}) - (faraday_options[:adapter] || faraday_options['adapter'] || :net_http_persistent).to_sym.tap do |adapter| - require 'typhoeus/adapters/faraday' if adapter == :typhoeus + def verify_faraday_options(faraday_options = {}, defaults = {}) + faraday_options.symbolize_keys!.reverse_merge!(defaults) + faraday_options[:adapter] ||= :net_http_persistent + require 'typhoeus/adapters/faraday' if faraday_options[:adapter].to_sym == :typhoeus + faraday_options + end + + def set_faraday_middleware(faraday, options = {adapter: :net_http_persistent}) + adapter = options.delete(:adapter) + send_all_faraday_options(faraday, options) + faraday.adapter adapter + end + + def send_all_faraday_options(faraday, options) + options.each do |key, value| + next unless faraday.respond_to? key + if value.is_a? Array + if value.none? { |arg| arg.is_a? Array } + faraday.send key, *value + else + value.each do |args| + arg_safe_send faraday, key, args + end + end + else + faraday.send key, value + end + end + end + + def arg_safe_send(object, msg, args) + if args.is_a? Array + object.send(msg, *args) + else + object.send(msg, args) end end end diff --git a/lib/neo4j/core/cypher_session/adaptors/http.rb b/lib/neo4j/core/cypher_session/adaptors/http.rb index 3f8cbd23..f4070884 100644 --- a/lib/neo4j/core/cypher_session/adaptors/http.rb +++ b/lib/neo4j/core/cypher_session/adaptors/http.rb @@ -138,22 +138,22 @@ def get(path, body = '', options = {}) private def faraday_connection(faraday_options = {}) - adapter = extract_adapter(faraday_options) + verify_faraday_options(faraday_options, + request: [ + [:basic_auth, user, password], + :multi_json + ], + response: [:multi_json, symbolize_keys: true, content_type: 'application/json'] + ) require 'faraday' require 'faraday_middleware/multi_json' - Faraday.new(url) do |c| - c.request :basic_auth, user, password - c.request :multi_json - - c.response :multi_json, symbolize_keys: true, content_type: 'application/json' - c.adapter(adapter || :net_http_persistent) - + conn = Faraday.new(url) do |c| # c.response :logger, ::Logger.new(STDOUT), bodies: true - - c.headers['Content-Type'] = 'application/json' - c.headers['User-Agent'] = @user_agent_string + set_faraday_middleware c, faraday_options end + conn.headers = {'Content-Type' => 'application/json', 'User-Agent' => @user_agent_string} + conn end def request_body(body) From 9db897ef7dfb126bf635abe573b7f867a2b6f7b3 Mon Sep 17 00:00:00 2001 From: Bruce Krysiak Date: Fri, 2 Dec 2016 00:39:08 -0800 Subject: [PATCH 15/19] Changing spec param to a valid value --- spec/neo4j/core/cypher_session/adaptors/http_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/neo4j/core/cypher_session/adaptors/http_spec.rb b/spec/neo4j/core/cypher_session/adaptors/http_spec.rb index cdecb4ca..27d0ddd7 100644 --- a/spec/neo4j/core/cypher_session/adaptors/http_spec.rb +++ b/spec/neo4j/core/cypher_session/adaptors/http_spec.rb @@ -32,13 +32,13 @@ end it 'will pass through a symbol key' do - expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:something) - adaptor_class.new(url, faraday_options: {adapter: :something}).connect + expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:typhoeus) + adaptor_class.new(url, faraday_options: {adapter: :typhoeus}).connect end it 'will pass through a string key' do - expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:something) - adaptor_class.new(url, 'faraday_options' => {'adapter' => :something}).connect + expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:typhoeus) + adaptor_class.new(url, 'faraday_options' => {'adapter' => :typhoeus}).connect end adaptors = Faraday::Adapter.instance_variable_get(:@registered_middleware).keys - [:test, :rack] From aea75e0a8e441f10d5053faeee720cf4b453abda Mon Sep 17 00:00:00 2001 From: Bruce Krysiak Date: Fri, 2 Dec 2016 01:04:16 -0800 Subject: [PATCH 16/19] Forgot to remove debugging gem which breaks CI --- Gemfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Gemfile b/Gemfile index 741c9c13..1cd08ee4 100644 --- a/Gemfile +++ b/Gemfile @@ -30,5 +30,4 @@ group 'test' do gem 'excon', '>= 0.27.4' gem 'patron', '>= 0.4.2', platforms: :ruby gem 'typhoeus', '>= 0.3.3' - gem 'byebug' end From bb32ab423240cea4c7d4501ef56fd9b73a7965cc Mon Sep 17 00:00:00 2001 From: Bruce Krysiak Date: Fri, 2 Dec 2016 01:12:43 -0800 Subject: [PATCH 17/19] Trying to fix CI timing issue --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d71d7cf2..1c6fb57f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ before_script: - "echo 'dbms.memory.heap.max_size=1000' >> ./db/neo4j/development/conf/neo4j-wrapper.conf" - "echo 'dbms.memory.heap.initial_size=1000' >> ./db/neo4j/development/conf/neo4j-wrapper.conf" - "bin/rake neo4j:start --trace" - - "sleep 10" + - "sleep 11" script: - "bundle exec rspec $RSPEC_OPTS" language: ruby From e6e1844078070f68acf59eba4cf755bf76b61eea Mon Sep 17 00:00:00 2001 From: Bruce Krysiak Date: Fri, 2 Dec 2016 02:43:42 -0800 Subject: [PATCH 18/19] Forgot to update the faraday_options docs --- README.md | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9af0b96c..fa070f64 100644 --- a/README.md +++ b/README.md @@ -15,9 +15,31 @@ To make a basic connection to Neo4j to execute Cypher queries, first choose an a neo4j_adaptor = Neo4j::Core::CypherSession::Adaptors::Embedded.new('/file/path/to/graph.db') -The `http_adaptor` can also take `:faraday_options`. Currently, only :adapter is supported (defaulting to `:net_http_persistent`): +The `http_adaptor` can also take `:faraday_options`. Multiple middlewares with the same key can be passed through using arrays: + + http_adaptor = Neo4j::Core::CypherSession::Adaptors::HTTP.new('http://neo4j:pass@localhost:7474', + faraday_options: { + adapter: :typhoeus, + # This will pass 2 items to Faraday. You must use multidimensional arrays to pass single args separately + request: [ + [:multipart], + [:url_encoded] + ], + # This will only pass a single item + response: [:multi_json, symbolize_keys: true, content_type: 'application/json'] + }) + +This will initialize Faraday like so: + + Faraday.new(url: 'http://neo4j:pass@localhost:7474') do |faraday| + faraday.request :multipart + faraday.request :url_encoded + + faraday.response :multi_json, symbolize_keys: true, content_type: 'application/json' + faraday.adapter: :typhoeus + end - http_adaptor = Neo4j::Core::CypherSession::Adaptors::HTTP.new('http://neo4j:pass@localhost:7474', faraday_options: { adapter: :typhoeus }) +The order that the keys are passed through to Faraday will remain hash ordered *except* that `adapter` is always last. Arrays within each key are passed in order. Note you **must** install any required http adaptor gems yourself as per [Faraday](https://github.com/lostisland/faraday). Ex for `:typhoeus`, add to your Gemfile: From cfa89738d02a6094edd3ba68cdfa17af4e87319b Mon Sep 17 00:00:00 2001 From: Bruce Krysiak Date: Fri, 2 Dec 2016 20:14:12 -0800 Subject: [PATCH 19/19] Refactoring --- lib/neo4j-server/cypher_session.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/neo4j-server/cypher_session.rb b/lib/neo4j-server/cypher_session.rb index 3ba66b34..08d3b854 100644 --- a/lib/neo4j-server/cypher_session.rb +++ b/lib/neo4j-server/cypher_session.rb @@ -16,8 +16,9 @@ def extract_faraday_options(params, defaults = {}) end def extract_basic_auth(url, params) - return unless url && URI(url).userinfo - params[:basic_auth] = {username: URI(url).user, password: URI(url).password} + uri = URI(url) if url + return unless url && uri.userinfo + params[:basic_auth] = {username: uri.user, password: uri.password} end end