rsolr 1.1.2 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +1 -0
- data/.rspec +2 -0
- data/.travis.yml +6 -13
- data/CHANGES.txt +11 -0
- data/Gemfile +0 -4
- data/README.rdoc +26 -9
- data/Rakefile +16 -3
- data/lib/rsolr.rb +38 -12
- data/lib/rsolr/char.rb +3 -21
- data/lib/rsolr/client.rb +75 -75
- data/lib/rsolr/document.rb +59 -0
- data/lib/rsolr/field.rb +87 -0
- data/lib/rsolr/generator.rb +5 -0
- data/lib/rsolr/json.rb +60 -0
- data/lib/rsolr/response.rb +2 -2
- data/lib/rsolr/uri.rb +2 -52
- data/lib/rsolr/version.rb +1 -1
- data/lib/rsolr/xml.rb +38 -107
- data/rsolr.gemspec +7 -3
- data/spec/api/client_spec.rb +90 -92
- data/spec/api/document_spec.rb +48 -0
- data/spec/api/error_spec.rb +2 -1
- data/spec/api/json_spec.rb +198 -0
- data/spec/api/pagination_spec.rb +3 -9
- data/spec/api/rsolr_spec.rb +3 -11
- data/spec/api/uri_spec.rb +2 -93
- data/spec/api/xml_spec.rb +45 -11
- data/spec/integration/solr5_spec.rb +9 -1
- data/spec/spec_helper.rb +88 -2
- metadata +44 -15
- data/lib/rsolr/connection.rb +0 -74
- data/spec/api/char_spec.rb +0 -23
- data/spec/api/connection_spec.rb +0 -140
- data/tasks/rdoc.rake +0 -11
- data/tasks/rsolr.rake +0 -10
- data/tasks/spec.rake +0 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1ca1fd66200c07e8e4ffc42bc8d71e6735a7294b7c53485ed8b49f8cfc99ac68
|
4
|
+
data.tar.gz: 3a0b50c5807543beed8ddc533cb8d446909176d61d1022ef0d8bb26ee1250648
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1a4bf74cc57d3523c4774f86c895b2e4a6bed229cc67499278fad4cf320575c68df1774d1fb0615108ca5ced0267798cea42a3e4c96723d6f2fb0f4294f38bcb
|
7
|
+
data.tar.gz: a51ec9142aba1761511058ed8614f600325e32551e6ae23b1638e2654b67e8a5ef3b8db1f6653171b67c492264079f368f95a0856ce1d7db5d1e5a06998b32d8
|
data/.gitignore
CHANGED
data/.rspec
ADDED
data/.travis.yml
CHANGED
@@ -1,21 +1,14 @@
|
|
1
|
-
addons:
|
2
|
-
apt:
|
3
|
-
packages:
|
4
|
-
- libgmp-dev
|
5
1
|
language: ruby
|
6
2
|
sudo: false
|
7
3
|
rvm:
|
8
|
-
- 2.
|
9
|
-
- 2.
|
10
|
-
-
|
11
|
-
|
12
|
-
notifications:
|
13
|
-
irc: "irc.freenode.org#blacklight"
|
14
|
-
email:
|
15
|
-
- blacklight-commits@googlegroups.com
|
4
|
+
- 2.6
|
5
|
+
- 2.5
|
6
|
+
- 2.4
|
7
|
+
- jruby
|
16
8
|
|
17
9
|
env:
|
18
10
|
global:
|
19
11
|
- JRUBY_OPTS="-J-Xms512m -J-Xmx1024m"
|
20
12
|
- NOKOGIRI_USE_SYSTEM_LIBRARIES=true
|
21
|
-
|
13
|
+
|
14
|
+
jdk: openjdk8
|
data/CHANGES.txt
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
2.0.0.pre1
|
2
|
+
|
3
|
+
In this release, we've added many new features, including:
|
4
|
+
|
5
|
+
- a new JSON request generator (enabled by default, replacing the XML-based requests) (@mootprinter)
|
6
|
+
- using Faraday for added flexibility for HTTP configuration
|
7
|
+
- native support for nested child documents and atomic updates in RSolr::Document and RSolr::Client.add
|
8
|
+
- better support for custom field value converters (@solenko)
|
9
|
+
- removing code deprecated in RSolr 1.x (@vipulnsward, and others)
|
10
|
+
|
11
|
+
|
1
12
|
1.0.12
|
2
13
|
- Fix bug where specifying the wt property as a string, would add the supplied value to the default ('ruby') rather than overriding it.
|
3
14
|
|
data/Gemfile
CHANGED
data/README.rdoc
CHANGED
@@ -11,7 +11,6 @@ The code docs http://www.rubydoc.info/gems/rsolr
|
|
11
11
|
gem install rsolr
|
12
12
|
|
13
13
|
== Example:
|
14
|
-
require 'rubygems'
|
15
14
|
require 'rsolr'
|
16
15
|
|
17
16
|
# Direct connection
|
@@ -19,7 +18,17 @@ The code docs http://www.rubydoc.info/gems/rsolr
|
|
19
18
|
|
20
19
|
# Connecting over a proxy server
|
21
20
|
solr = RSolr.connect :url => 'http://solrserver.com', :proxy=>'http://user:pass@proxy.example.com:8080'
|
21
|
+
|
22
|
+
# Using an alternate Faraday adapter
|
23
|
+
solr = RSolr.connect :url => 'http://solrserver.com', :adapter => :em_http
|
22
24
|
|
25
|
+
# Using a custom Faraday connection
|
26
|
+
conn = Faraday.new do |faraday|
|
27
|
+
faraday.response :logger # log requests to STDOUT
|
28
|
+
faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
|
29
|
+
end
|
30
|
+
solr = RSolr.connect conn, :url => 'http://solrserver.com'
|
31
|
+
|
23
32
|
# send a request to /select
|
24
33
|
response = solr.get 'select', :params => {:q => '*:*'}
|
25
34
|
|
@@ -34,6 +43,14 @@ The +:request+ attribute contains the original request context. You can use this
|
|
34
43
|
|
35
44
|
The +:response+ attribute contains the original response. This object contains the +:status+, +:body+ and +:headers+ keys.
|
36
45
|
|
46
|
+
== Request formats
|
47
|
+
|
48
|
+
By default, RSolr uses the Solr JSON command format for all requests.
|
49
|
+
|
50
|
+
RSolr.connect :url => 'http://solrserver.com', update_format: :json # the default
|
51
|
+
# or
|
52
|
+
RSolr.connect :url => 'http://solrserver.com', update_format: :xml
|
53
|
+
|
37
54
|
== Timeouts
|
38
55
|
The read and connect timeout settings can be set when creating a new instance of RSolr:
|
39
56
|
solr = RSolr.connect(:read_timeout => 120, :open_timeout => 120)
|
@@ -44,6 +61,7 @@ A 503 is usually a temporary error which RSolr may retry if requested. You may s
|
|
44
61
|
Only requests which specify a Retry-After header will be retried, after waiting the indicated retry interval, otherwise RSolr will treat the request as a 500. You may specify a maximum Retry-After interval to wait with the +:retry_after_limit+ option (default: one second).
|
45
62
|
solr = RSolr.connect(:retry_503 => 1, :retry_after_limit => 1)
|
46
63
|
|
64
|
+
For additional control, consider using a custom Faraday connection (see above) using its `retry` middleware.
|
47
65
|
|
48
66
|
== Querying
|
49
67
|
Use the #get / #post method to send search requests to the /select handler:
|
@@ -119,9 +137,9 @@ Multiple documents via #add
|
|
119
137
|
The optional +:add_attributes+ hash can also be used to set Solr "add" document attributes:
|
120
138
|
solr.add documents, :add_attributes => {:commitWithin => 10}
|
121
139
|
|
122
|
-
Raw
|
123
|
-
solr.update :
|
124
|
-
solr.update :
|
140
|
+
Raw commands via #update
|
141
|
+
solr.update data: '<commit/>', headers: { 'Content-Type' => 'text/xml' }
|
142
|
+
solr.update data: { optimize: true }.to_json, headers: { 'Content-Type' => 'application/json' }
|
125
143
|
|
126
144
|
When adding, you can also supply "add" xml element attributes and/or a block for manipulating other "add" related elements (docs and fields) by calling the +xml+ method directly:
|
127
145
|
|
@@ -155,14 +173,13 @@ Delete by array of queries
|
|
155
173
|
== Response Formats
|
156
174
|
The default response format is Ruby. When the +:wt+ param is set to +:ruby+, the response is eval'd resulting in a Hash. You can get a raw response by setting the +:wt+ to +"ruby"+ - notice, the string -- not a symbol. RSolr will eval the Ruby string ONLY if the :wt value is :ruby. All other response formats are available as expected, +:wt=>'xml'+ etc..
|
157
175
|
|
158
|
-
===Evaluated Ruby
|
176
|
+
===Evaluated Ruby:
|
159
177
|
solr.get 'select', :params => {:wt => :ruby} # notice :ruby is a Symbol
|
160
|
-
===Raw Ruby
|
178
|
+
===Raw Ruby:
|
161
179
|
solr.get 'select', :params => {:wt => 'ruby'} # notice 'ruby' is a String
|
162
|
-
|
163
180
|
===XML:
|
164
181
|
solr.get 'select', :params => {:wt => :xml}
|
165
|
-
===JSON:
|
182
|
+
===JSON (default):
|
166
183
|
solr.get 'select', :params => {:wt => :json}
|
167
184
|
|
168
185
|
==Related Resources & Projects
|
@@ -170,7 +187,7 @@ The default response format is Ruby. When the +:wt+ param is set to +:ruby+, the
|
|
170
187
|
* {rsolr-ext}[http://github.com/mwmitchell/rsolr-ext] -- An extension kit for RSolr
|
171
188
|
* {rsolr-direct}[http://github.com/mwmitchell/rsolr-direct] -- JRuby direct connection for RSolr
|
172
189
|
* {rsolr-nokogiri}[http://github.com/mwmitchell/rsolr-nokogiri] -- Gives RSolr Nokogiri for XML generation.
|
173
|
-
* {SunSpot}[http://github.com/
|
190
|
+
* {SunSpot}[http://github.com/sunspot/sunspot] -- An awesome Solr DSL, built with RSolr
|
174
191
|
* {Blacklight}[http://blacklightopac.org] -- A "next generation" Library OPAC, built with RSolr
|
175
192
|
* {java_bin}[http://github.com/kennyj/java_bin] -- Provides javabin/binary parsing for RSolr
|
176
193
|
* {Solr}[http://lucene.apache.org/solr/] -- The Apache Solr project
|
data/Rakefile
CHANGED
@@ -1,6 +1,19 @@
|
|
1
|
-
require 'rake'
|
2
1
|
require 'bundler/gem_tasks'
|
3
2
|
|
4
|
-
|
3
|
+
task default: ['spec']
|
5
4
|
|
6
|
-
|
5
|
+
require 'rspec/core/rake_task'
|
6
|
+
|
7
|
+
RSpec::Core::RakeTask.new(:spec)
|
8
|
+
|
9
|
+
# Rdoc
|
10
|
+
require 'rdoc/task'
|
11
|
+
|
12
|
+
desc 'Generate documentation for the rsolr gem.'
|
13
|
+
RDoc::Task.new(:doc) do |rdoc|
|
14
|
+
rdoc.rdoc_dir = 'doc'
|
15
|
+
rdoc.title = 'RSolr'
|
16
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
17
|
+
rdoc.rdoc_files.include('README.rdoc')
|
18
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
19
|
+
end
|
data/lib/rsolr.rb
CHANGED
@@ -1,16 +1,27 @@
|
|
1
1
|
module RSolr
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
require 'rsolr/version'
|
3
|
+
|
4
|
+
autoload :Char, 'rsolr/char'
|
5
|
+
autoload :Client, 'rsolr/client'
|
6
|
+
autoload :Document, 'rsolr/document'
|
7
|
+
autoload :Error, 'rsolr/error'
|
8
|
+
autoload :Field, 'rsolr/field'
|
9
|
+
autoload :Generator, 'rsolr/generator'
|
10
|
+
autoload :HashWithResponse, 'rsolr/response'
|
11
|
+
autoload :JSON, 'rsolr/json'
|
12
|
+
autoload :Response, 'rsolr/response'
|
13
|
+
autoload :Uri, 'rsolr/uri'
|
14
|
+
autoload :Xml, 'rsolr/xml'
|
15
|
+
|
5
16
|
def self.connect *args
|
6
|
-
|
7
|
-
opts
|
8
|
-
|
17
|
+
opts = args.pop if args.last.is_a?(::Hash)
|
18
|
+
opts ||= {}
|
19
|
+
|
20
|
+
connection = args.first
|
21
|
+
|
22
|
+
Client.new connection, opts
|
9
23
|
end
|
10
|
-
|
11
|
-
# RSolr.escape, which is deprecated as of 2015-02
|
12
|
-
extend Char
|
13
|
-
|
24
|
+
|
14
25
|
# backslash escape characters that have special meaning to Solr query parser
|
15
26
|
# per http://lucene.apache.org/core/4_0_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#Escaping_Special_Characters
|
16
27
|
# + - & | ! ( ) { } [ ] ^ " ~ * ? : \ /
|
@@ -22,5 +33,20 @@ module RSolr
|
|
22
33
|
# so the result sent to Solr is ultimately a single backslash in front of the particular character
|
23
34
|
str.gsub(/([+\-&|!\(\)\{\}\[\]\^"~\*\?:\\\/])/, '\\\\\1')
|
24
35
|
end
|
25
|
-
|
26
|
-
|
36
|
+
|
37
|
+
module Array
|
38
|
+
def self.wrap(object)
|
39
|
+
if object.nil?
|
40
|
+
[nil]
|
41
|
+
elsif object.respond_to?(:to_ary)
|
42
|
+
object.to_ary || [object]
|
43
|
+
elsif object.is_a? Hash
|
44
|
+
[object]
|
45
|
+
elsif object.is_a? Enumerable
|
46
|
+
object
|
47
|
+
else
|
48
|
+
[object]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/rsolr/char.rb
CHANGED
@@ -1,24 +1,6 @@
|
|
1
|
-
#
|
2
|
-
# @deprecated remove this module when we remove the method (duh)
|
1
|
+
# :nodoc:
|
3
2
|
module RSolr::Char
|
4
|
-
|
5
|
-
|
6
|
-
# that isn't a word character
|
7
|
-
# @deprecated - this is incorrect Solr escaping
|
8
|
-
def escape value
|
9
|
-
warn "[DEPRECATION] `RSolr.escape` is deprecated (and incorrect). Use `RSolr.solr_escape` instead."
|
10
|
-
value.gsub(/(\W)/, '\\\\\1')
|
3
|
+
def self.included(*)
|
4
|
+
warn 'RSolr::Char is deprecated without replacement, and will be removed in RSolr 3.x'
|
11
5
|
end
|
12
|
-
|
13
|
-
# LUCENE_CHAR_RX = /([\+\-\!\(\)\[\]\^\"\~\*\?\:\\]+)/
|
14
|
-
# LUCENE_WORD_RX = /(OR|AND|NOT)/
|
15
|
-
#
|
16
|
-
# # More specific/lucene escape sequence
|
17
|
-
# def lucene_escape string
|
18
|
-
# delim = " "
|
19
|
-
# string.gsub(LUCENE_CHAR_RX, '\\\\\1').split(delim).map { |v|
|
20
|
-
# v.gsub(LUCENE_WORD_RX, '\\\\\1')
|
21
|
-
# }.join(delim)
|
22
|
-
# end
|
23
|
-
|
24
6
|
end
|
data/lib/rsolr/client.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'faraday'
|
5
|
+
require 'uri'
|
5
6
|
|
6
7
|
class RSolr::Client
|
8
|
+
DEFAULT_URL = 'http://127.0.0.1:8983/solr/'
|
7
9
|
|
8
10
|
class << self
|
9
11
|
def default_wt
|
10
|
-
@default_wt
|
12
|
+
@default_wt ||= :json
|
11
13
|
end
|
12
14
|
|
13
15
|
def default_wt= value
|
@@ -15,33 +17,41 @@ class RSolr::Client
|
|
15
17
|
end
|
16
18
|
end
|
17
19
|
|
18
|
-
attr_reader :
|
20
|
+
attr_reader :uri, :proxy, :update_format, :options, :update_path
|
19
21
|
|
20
22
|
def initialize connection, options = {}
|
21
23
|
@proxy = @uri = nil
|
22
24
|
@connection = connection
|
23
25
|
unless false === options[:url]
|
24
|
-
|
25
|
-
url << "/" unless url[-1] == ?/
|
26
|
-
@uri = RSolr::Uri.create url
|
26
|
+
@uri = extract_url_from_options(options)
|
27
27
|
if options[:proxy]
|
28
28
|
proxy_url = options[:proxy].dup
|
29
29
|
proxy_url << "/" unless proxy_url.nil? or proxy_url[-1] == ?/
|
30
|
-
@proxy =
|
30
|
+
@proxy = ::URI.parse proxy_url if proxy_url
|
31
31
|
elsif options[:proxy] == false
|
32
32
|
@proxy = false # used to avoid setting the proxy from the environment.
|
33
33
|
end
|
34
34
|
end
|
35
|
+
@update_format = options.delete(:update_format) || RSolr::JSON::Generator
|
35
36
|
@update_path = options.fetch(:update_path, 'update')
|
36
37
|
@options = options
|
37
38
|
end
|
38
39
|
|
40
|
+
def extract_url_from_options(options)
|
41
|
+
url = options[:url] ? options[:url].dup : DEFAULT_URL
|
42
|
+
url << "/" unless url[-1] == ?/
|
43
|
+
uri = ::URI.parse(url)
|
44
|
+
# URI::HTTPS is a subclass of URI::HTTP, so this check accepts HTTP(S)
|
45
|
+
raise ArgumentError, "You must provide an HTTP(S) url." unless uri.kind_of?(URI::HTTP)
|
46
|
+
uri
|
47
|
+
end
|
48
|
+
|
39
49
|
# returns the request uri object.
|
40
50
|
def base_request_uri
|
41
51
|
base_uri.request_uri if base_uri
|
42
52
|
end
|
43
53
|
|
44
|
-
# returns the
|
54
|
+
# returns the URI uri object.
|
45
55
|
def base_uri
|
46
56
|
@uri
|
47
57
|
end
|
@@ -80,11 +90,10 @@ class RSolr::Client
|
|
80
90
|
#
|
81
91
|
def update opts = {}
|
82
92
|
opts[:headers] ||= {}
|
83
|
-
opts[:headers]['Content-Type'] ||=
|
93
|
+
opts[:headers]['Content-Type'] ||= builder.content_type
|
84
94
|
post opts.fetch(:path, update_path), opts
|
85
95
|
end
|
86
96
|
|
87
|
-
#
|
88
97
|
# +add+ creates xml "add" documents and sends the xml data to the +update+ method
|
89
98
|
#
|
90
99
|
# http://wiki.apache.org/solr/UpdateXmlMessages#add.2BAC8-update
|
@@ -101,7 +110,7 @@ class RSolr::Client
|
|
101
110
|
#
|
102
111
|
def add doc, opts = {}
|
103
112
|
add_attributes = opts.delete :add_attributes
|
104
|
-
update opts.merge(:data =>
|
113
|
+
update opts.merge(:data => builder.add(doc, add_attributes))
|
105
114
|
end
|
106
115
|
|
107
116
|
# send "commit" xml with opts
|
@@ -110,7 +119,7 @@ class RSolr::Client
|
|
110
119
|
#
|
111
120
|
def commit opts = {}
|
112
121
|
commit_attrs = opts.delete :commit_attributes
|
113
|
-
update opts.merge(:data =>
|
122
|
+
update opts.merge(:data => builder.commit( commit_attrs ))
|
114
123
|
end
|
115
124
|
|
116
125
|
# send "optimize" xml with opts.
|
@@ -119,7 +128,7 @@ class RSolr::Client
|
|
119
128
|
#
|
120
129
|
def optimize opts = {}
|
121
130
|
optimize_attributes = opts.delete :optimize_attributes
|
122
|
-
update opts.merge(:data =>
|
131
|
+
update opts.merge(:data => builder.optimize(optimize_attributes))
|
123
132
|
end
|
124
133
|
|
125
134
|
# send </rollback>
|
@@ -128,14 +137,14 @@ class RSolr::Client
|
|
128
137
|
#
|
129
138
|
# NOTE: solr 1.4 only
|
130
139
|
def rollback opts = {}
|
131
|
-
update opts.merge(:data =>
|
140
|
+
update opts.merge(:data => builder.rollback)
|
132
141
|
end
|
133
142
|
|
134
143
|
# Delete one or many documents by id
|
135
144
|
# solr.delete_by_id 10
|
136
145
|
# solr.delete_by_id([12, 41, 199])
|
137
146
|
def delete_by_id id, opts = {}
|
138
|
-
update opts.merge(:data =>
|
147
|
+
update opts.merge(:data => builder.delete_by_id(id))
|
139
148
|
end
|
140
149
|
|
141
150
|
# delete one or many documents by query.
|
@@ -145,12 +154,19 @@ class RSolr::Client
|
|
145
154
|
# solr.delete_by_query 'available:0'
|
146
155
|
# solr.delete_by_query ['quantity:0', 'manu:"FQ"']
|
147
156
|
def delete_by_query query, opts = {}
|
148
|
-
update opts.merge(:data =>
|
157
|
+
update opts.merge(:data => builder.delete_by_query(query))
|
149
158
|
end
|
150
159
|
|
151
|
-
|
152
|
-
|
153
|
-
|
160
|
+
def builder
|
161
|
+
@builder ||= if update_format.is_a? Class
|
162
|
+
update_format.new
|
163
|
+
elsif update_format == :json
|
164
|
+
RSolr::JSON::Generator.new
|
165
|
+
elsif update_format == :xml
|
166
|
+
RSolr::Xml::Generator.new
|
167
|
+
else
|
168
|
+
update_format
|
169
|
+
end
|
154
170
|
end
|
155
171
|
|
156
172
|
# +send_and_receive+ is the main request method responsible for sending requests to the +connection+ object.
|
@@ -177,48 +193,21 @@ class RSolr::Client
|
|
177
193
|
|
178
194
|
#
|
179
195
|
def execute request_context
|
196
|
+
raw_response = begin
|
197
|
+
response = connection.send(request_context[:method], request_context[:uri].to_s) do |req|
|
198
|
+
req.body = request_context[:data] if request_context[:method] == :post and request_context[:data]
|
199
|
+
req.headers.merge!(request_context[:headers]) if request_context[:headers]
|
200
|
+
end
|
180
201
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
raw_response = connection.execute self, request_context
|
202
|
+
{ status: response.status.to_i, headers: response.headers, body: response.body.force_encoding('utf-8') }
|
203
|
+
rescue Errno::ECONNREFUSED, defined?(Faraday::ConnectionFailed) ? Faraday::ConnectionFailed : Faraday::Error::ConnectionFailed
|
204
|
+
raise RSolr::Error::ConnectionRefused, request_context.inspect
|
205
|
+
rescue Faraday::Error => e
|
206
|
+
raise RSolr::Error::Http.new(request_context, e.response)
|
187
207
|
end
|
188
|
-
|
189
208
|
adapt_response(request_context, raw_response) unless raw_response.nil?
|
190
209
|
end
|
191
210
|
|
192
|
-
def retry_503?(request_context, response)
|
193
|
-
return false if response.nil?
|
194
|
-
status = response[:status] && response[:status].to_i
|
195
|
-
return false unless status == 503
|
196
|
-
retry_503 = request_context[:retry_503]
|
197
|
-
return false unless retry_503 && retry_503 > 0
|
198
|
-
retry_after_limit = request_context[:retry_after_limit] || 1
|
199
|
-
retry_after = retry_after(response)
|
200
|
-
return false unless retry_after && retry_after <= retry_after_limit
|
201
|
-
true
|
202
|
-
end
|
203
|
-
|
204
|
-
# Retry-After can be a relative number of seconds from now, or an RFC 1123 Date.
|
205
|
-
# If the latter, attempt to convert it to a relative time in seconds.
|
206
|
-
def retry_after(response)
|
207
|
-
retry_after = Array(response[:headers]['Retry-After'] || response[:headers]['retry-after']).flatten.first.to_s
|
208
|
-
if retry_after =~ /\A[0-9]+\Z/
|
209
|
-
retry_after = retry_after.to_i
|
210
|
-
else
|
211
|
-
begin
|
212
|
-
retry_after_date = DateTime.parse(retry_after)
|
213
|
-
retry_after = retry_after_date.to_time - Time.now
|
214
|
-
retry_after = nil if retry_after < 0
|
215
|
-
rescue ArgumentError
|
216
|
-
retry_after = retry_after.to_i
|
217
|
-
end
|
218
|
-
end
|
219
|
-
retry_after
|
220
|
-
end
|
221
|
-
|
222
211
|
# +build_request+ accepts a path and options hash,
|
223
212
|
# then prepares a normalized hash to return for sending
|
224
213
|
# to a solr connection driver.
|
@@ -250,10 +239,6 @@ class RSolr::Client
|
|
250
239
|
opts[:path] = path
|
251
240
|
opts[:uri] = base_uri.merge(path.to_s + (query ? "?#{query}" : "")) if base_uri
|
252
241
|
|
253
|
-
[:open_timeout, :read_timeout, :retry_503, :retry_after_limit].each do |k|
|
254
|
-
opts[k] = @options[k]
|
255
|
-
end
|
256
|
-
|
257
242
|
opts
|
258
243
|
end
|
259
244
|
|
@@ -285,7 +270,6 @@ class RSolr::Client
|
|
285
270
|
def adapt_response request, response
|
286
271
|
raise "The response does not have the correct keys => :body, :headers, :status" unless
|
287
272
|
%W(body headers status) == response.keys.map{|k|k.to_s}.sort
|
288
|
-
raise RSolr::Error::Http.new request, response unless [200,302].include? response[:status]
|
289
273
|
|
290
274
|
result = if respond_to? "evaluate_#{request[:params][:wt]}_response", true
|
291
275
|
send "evaluate_#{request[:params][:wt]}_response", request, response
|
@@ -299,6 +283,26 @@ class RSolr::Client
|
|
299
283
|
|
300
284
|
result
|
301
285
|
end
|
286
|
+
|
287
|
+
def connection
|
288
|
+
@connection ||= begin
|
289
|
+
conn_opts = { request: {} }
|
290
|
+
conn_opts[:url] = uri.to_s
|
291
|
+
conn_opts[:proxy] = proxy if proxy
|
292
|
+
conn_opts[:request][:open_timeout] = options[:open_timeout] if options[:open_timeout]
|
293
|
+
conn_opts[:request][:timeout] = options[:read_timeout] if options[:read_timeout]
|
294
|
+
conn_opts[:request][:params_encoder] = Faraday::FlatParamsEncoder
|
295
|
+
|
296
|
+
Faraday.new(conn_opts) do |conn|
|
297
|
+
conn.basic_auth(uri.user, uri.password) if uri.user && uri.password
|
298
|
+
conn.response :raise_error
|
299
|
+
conn.request :retry, max: options[:retry_after_limit], interval: 0.05,
|
300
|
+
interval_randomness: 0.5, backoff_factor: 2,
|
301
|
+
exceptions: ['Faraday::Error', 'Timeout::Error'] if options[:retry_503]
|
302
|
+
conn.adapter options[:adapter] || Faraday.default_adapter
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
302
306
|
|
303
307
|
protected
|
304
308
|
|
@@ -319,21 +323,17 @@ class RSolr::Client
|
|
319
323
|
# instead, giving full access to the
|
320
324
|
# request/response objects.
|
321
325
|
def evaluate_ruby_response request, response
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
raise RSolr::Error::InvalidRubyResponse.new request, response
|
326
|
-
end
|
326
|
+
Kernel.eval response[:body].to_s
|
327
|
+
rescue SyntaxError
|
328
|
+
raise RSolr::Error::InvalidRubyResponse.new request, response
|
327
329
|
end
|
328
330
|
|
329
331
|
def evaluate_json_response request, response
|
330
|
-
return response[:body]
|
332
|
+
return if response[:body].nil? || response[:body].empty?
|
331
333
|
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
raise RSolr::Error::InvalidJsonResponse.new request, response
|
336
|
-
end
|
334
|
+
JSON.parse response[:body].to_s
|
335
|
+
rescue JSON::ParserError
|
336
|
+
raise RSolr::Error::InvalidJsonResponse.new request, response
|
337
337
|
end
|
338
338
|
|
339
339
|
def default_wt
|