Skip to content

Commit

Permalink
starting excon branch
Browse files Browse the repository at this point in the history
  • Loading branch information
maxdemarzi committed Apr 27, 2014
1 parent 449fc12 commit 4fa441f
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 70 deletions.
2 changes: 1 addition & 1 deletion lib/neography.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
require 'cgi'
require 'httpclient'
require 'excon'
require 'json'
require 'multi_json'
require 'logger'
Expand Down
34 changes: 21 additions & 13 deletions lib/neography/connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class Connection
USER_AGENT = "Neography/#{Neography::VERSION}"
ACTIONS = ["get", "post", "put", "delete"]

attr_accessor :protocol, :server, :port, :directory,
attr_reader :protocol, :server, :port, :directory,
:cypher_path, :gremlin_path,
:log_file, :log_enabled, :logger, :slow_log_threshold,
:max_threads,
Expand All @@ -16,10 +16,13 @@ class Connection
def initialize(options = ENV['NEO4J_URL'] || {})
config = merge_configuration(options)
save_local_configuration(config)
@client ||= HTTPClient.new(config[:proxy])
@client.send_timeout = config[:http_send_timeout]
@client.receive_timeout = config[:http_receive_timeout]
authenticate
@client ||= Excon.new(config[:proxy] || "#{@protocol}#{@server}:#{@port}",
:read_timeout => config[:http_receive_timeout],
:write_timeout => config[:http_send_timeout],
:persistent => true,
:user => config[:username],
:password => config[:password])
#authenticate
end

def configure(protocol, server, port, directory)
Expand Down Expand Up @@ -47,13 +50,18 @@ def merge_options(options)
define_method(action) do |path, options = {}|
# This ugly hack is required because internal Batch paths do not start with "/db/data"
# if somebody has a cleaner solution... pull request please!
path = "/db/data" + path if ["node", "relationship", "transaction", "cypher", "propertykeys", "schema", "label", "labels", "batch", "index", "ext"].include?(path.split("/")[1].split("?").first)
query_path = configuration + path
query_body = merge_options(options)[:body]
partial_path = path.split("/")
if partial_path.size > 0
partial_path = partial_path[1].split("?").first
end
reserved = ["node", "relationship", "transaction", "cypher", "propertykeys", "schema", "label", "labels", "batch", "index", "ext"]
path = "/db/data" + path if reserved.include?(partial_path)
is_batch = (partial_path == "batch")
query_body = options[:body]
log path, query_body do
headers = merge_options(options)[:headers]
evaluate_response(@client.send(action.to_sym, query_path, query_body, headers),
path, query_body, headers && (headers['X-Stream'] == true))
evaluate_response(@client.request(:method => action.to_sym, :path => path, :body => query_body, :headers => headers),
path, query_body, headers && (headers['X-Stream'] == true), is_batch)
end
end
end
Expand Down Expand Up @@ -131,11 +139,11 @@ def evaluate_chunk_response(response, result)
return_result(code, result)
end

def evaluate_response(response, path, query_body, streaming)
if streaming && response.http_header.request_uri.request_uri == "/db/data/batch"
def evaluate_response(response, path, query_body, streaming, batching)
if streaming && batching
code, body, parsed = handle_batch(response)
else
code = response.code
code = response.status
body = response.body.force_encoding("UTF-8")
parsed = false
end
Expand Down
1 change: 0 additions & 1 deletion lib/neography/tasks.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# borrowed from architect4r
require 'os'
require 'httpclient'
require 'zip'
require 'net/http'

Expand Down
2 changes: 1 addition & 1 deletion neography.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Gem::Specification.new do |s|
s.add_development_dependency "rspec", ">= 2.11"
s.add_development_dependency "net-http-spy", "0.2.1"
s.add_development_dependency "coveralls"
s.add_dependency "httpclient", ">= 2.3.3"
s.add_dependency "excon", "~> 0.33.0"
s.add_dependency "json", ">= 1.7.7"
s.add_dependency "os", ">= 0.9.6"
s.add_dependency "rubyzip", ">= 1.0.0"
Expand Down
3 changes: 1 addition & 2 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,11 @@ def error_response(attributes)

double(
http_header: http_header,
code: attributes[:code],
status: attributes[:code],
body: {
message: attributes[:message],
exception: attributes[:exception],
stacktrace: attributes[:stacktrace]
}.reject { |k,v| v.nil? }.to_json
)
end

108 changes: 56 additions & 52 deletions spec/unit/connection_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,17 @@ module Neography
let(:options) do
{
:http_send_timeout => 120,
:http_receive_timeout => 120
:http_receive_timeout => 100
}
end

it 'configures send/receive timeout' do
HTTPClient.should_receive(:new).and_return(httpclient)
httpclient.should_receive(:send_timeout=).with(120)
httpclient.should_receive(:receive_timeout=).with(120)
Excon.should_receive(:new).with("http://localhost:7474",
:read_timeout => 100,
:write_timeout => 120,
:persistent=>true,
:user=>nil,
:password=>nil).and_return(httpclient)
connection
end
end
Expand All @@ -99,22 +102,22 @@ module Neography
context "requests" do

it "does a GET request" do
connection.client.should_receive(:get).with("http://localhost:7474/db/data/node/bar", nil, nil) { double.as_null_object }
connection.client.should_receive(:request).with(:method => :get, :path => "/db/data/node/bar", :body => nil, :headers => nil) { double.as_null_object }
connection.get("/node/bar")
end

it "does a POST request" do
connection.client.should_receive(:post).with("http://localhost:7474/db/data/node/bar", nil, nil) { double.as_null_object }
connection.client.should_receive(:request).with(:method => :post, :path => "/db/data/node/bar", :body => nil, :headers => nil) { double.as_null_object }
connection.post("/node/bar")
end

it "does a PUT request" do
connection.client.should_receive(:put).with("http://localhost:7474/db/data/node/bar", nil, nil) { double.as_null_object }
connection.client.should_receive(:request).with(:method => :put, :path => "/db/data/node/bar", :body => nil, :headers => nil) { double.as_null_object }
connection.put("/node/bar")
end

it "does a DELETE request" do
connection.client.should_receive(:delete).with("http://localhost:7474/db/data/node/bar", nil, nil) { double.as_null_object }
connection.client.should_receive(:request).with(:method => :delete, :path => "/db/data/node/bar", :body => nil, :headers => nil) { double.as_null_object }
connection.delete("/node/bar")
end

Expand All @@ -133,18 +136,17 @@ module Neography
"foo",
"bar") { double.as_null_object }

connection.client.should_receive(:get).with(
"http://localhost:7474/db/data/node/bar", nil, nil
) { double.as_null_object }
connection.client.should_receive(:request).with(
:method => :get, :path => "/db/data/node/bar", :body => nil, :headers => nil) { double.as_null_object }

connection.get("/node/bar")
end
end

it "adds the User-Agent to the headers" do
connection.client.should_receive(:get).with(
"http://localhost:7474/db/data/node/bar",
nil, { "User-Agent" => "Neography/#{Neography::VERSION}", "X-Stream"=>true, "max-execution-time"=>6000}
connection.client.should_receive(:request).with(
:method => :get, :path => "/db/data/node/bar", :body => nil,
:headers => { "User-Agent" => "Neography/#{Neography::VERSION}", "X-Stream"=>true, "max-execution-time" => 6000}
) { double.as_null_object }

connection.get("/node/bar", :headers => {})
Expand All @@ -154,71 +156,71 @@ module Neography

it "raises NodeNotFoundException" do
response = error_response(code: 404, message: "a message", exception: "NodeNotFoundException")
connection.client.stub(:get).and_return(response)
connection.client.stub(:request).and_return(response)
expect {
connection.get("/node/bar")
}.to raise_error NodeNotFoundException
end

it "raises OperationFailureException" do
response = error_response(code: 409, message: "a message", exception: "OperationFailureException")
connection.client.stub(:get).and_return(response)
connection.client.stub(:request).and_return(response)
expect {
connection.get("/node/bar")
}.to raise_error OperationFailureException
end

it "raises PropertyValueException" do
response = error_response(code: 400, message: "a message", exception: "PropertyValueException")
connection.client.stub(:get).and_return(response)
connection.client.stub(:request).and_return(response)
expect {
connection.get("/node/bar")
}.to raise_error PropertyValueException
end

it "raises NoSuchPropertyException" do
response = error_response(code: 404, message: "a message", exception: "NoSuchPropertyException")
connection.client.stub(:get).and_return(response)
connection.client.stub(:request).and_return(response)
expect {
connection.get("/node/bar")
}.to raise_error NoSuchPropertyException
end

it "raises RelationshipNotFoundException" do
response = error_response(code: 404, message: "a message", exception: "RelationshipNotFoundException")
connection.client.stub(:get).and_return(response)
connection.client.stub(:request).and_return(response)
expect {
connection.get("/node/bar")
}.to raise_error RelationshipNotFoundException
end

it "raises BadInputException" do
response = error_response(code: 400, message: "a message", exception: "BadInputException")
connection.client.stub(:get).and_return(response)
connection.client.stub(:request).and_return(response)
expect {
connection.get("/node/bar")
}.to raise_error BadInputException
end

it "raises UnauthorizedError" do
response = error_response(code: 401)
connection.client.stub(:get).and_return(response)
connection.client.stub(:request).and_return(response)
expect {
connection.get("/node/bar")
}.to raise_error UnauthorizedError
end

it "raises NeographyError in all other cases" do
response = error_response(code: 418, message: "I'm a teapot.")
connection.client.stub(:get).and_return(response)
connection.client.stub(:request).and_return(response)
expect {
connection.get("/node/bar")
}.to raise_error NeographyError
end

it "raises BadInputException" do
response = error_response(code: 500, message: "a message", exception: "JsonParseException")
connection.client.stub(:get).and_return(response)
connection.client.stub(:request).and_return(response)
expect {
connection.get("/node/bar")
}.to raise_error NeographyError
Expand All @@ -227,49 +229,51 @@ module Neography
end

context "query logging" do
before do
@logger = Logger.new(nil)
connection.logger = @logger
connection.log_enabled = true
end

let(:expected_response) {"expected_response"}
subject(:connection) do

let(:request_body) { {key1: :val1} }
Connection.new({
:logger => Logger.new(nil),
:log_enabled => true
})

let(:expected_response) {"expected_response"}

it "should log query" do
connection.should_receive(:log).with("/db/data/node/bar", request_body).once
connection.get("/node/bar", {body: request_body})
end
let(:request_body) { {key1: :val1} }

it "should return original response" do
connection.stub(:evaluate_response).and_return expected_response
connection.get("/node/bar").should eq expected_response
end
it "should log query" do
connection.should_receive(:log).with("/db/data/node/bar", request_body).once
connection.get("/node/bar", {body: request_body})
end

describe "slow_log_threshold" do
before do
it "should return original response" do
connection.stub(:evaluate_response).and_return expected_response
connection.get("/node/bar").should eq expected_response
end

context "default value" do
it "should have output" do
@logger.should_receive(:info).once
describe "slow_log_threshold" do
before do
connection.stub(:evaluate_response).and_return expected_response
end
end

context "high value" do
before { connection.slow_log_threshold = 100_000 }
it "should not have output" do
@logger.should_not_receive(:info)
context "default value" do
it "should have output" do
@logger.should_receive(:info).once
end
end
end

after do
connection.get("/node/bar", {body: request_body})
context "high value" do
before { connection.slow_log_threshold = 100_000 }
it "should not have output" do
@logger.should_not_receive(:info)
end
end

after do
connection.get("/node/bar", {body: request_body})
end
end
end

end
end
end
Expand Down

0 comments on commit 4fa441f

Please sign in to comment.