rsolr 1.0.8 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e401f0dcdd04d8215eec9b67a1e7c775c41ac7f4
4
+ data.tar.gz: 6e466531f33da1560869ce39586101dfc4bbb08e
5
+ SHA512:
6
+ metadata.gz: 29a5ac0f898a33e2d8efc2a0b0b7ed618c169e63597dcc283573ae9302183f0ee983ec18e30d3c9dc100bb13e06ff86358d02ad0df91515101efc8a26f82b7f8
7
+ data.tar.gz: 1a509a26c086ffbad2543154106584989d7c40d42b747a422a622ba77fe1dd87202373ae1cd8d10727a0b61b89ad16a5cfcdc5655375ebc7d4b5733d9fa7dcb0
data/.travis.yml ADDED
@@ -0,0 +1,21 @@
1
+ addons:
2
+ apt:
3
+ packages:
4
+ - libgmp-dev
5
+ language: ruby
6
+ sudo: false
7
+ rvm:
8
+ - 2.3.1
9
+ - 2.2.5
10
+ - jruby-9.0.5.0
11
+
12
+ notifications:
13
+ irc: "irc.freenode.org#blacklight"
14
+ email:
15
+ - blacklight-commits@googlegroups.com
16
+
17
+ env:
18
+ global:
19
+ - JRUBY_OPTS="-J-Xms512m -J-Xmx1024m"
20
+ - NOKOGIRI_USE_SYSTEM_LIBRARIES=true
21
+ jdk: oraclejdk8
data/CHANGES.txt CHANGED
@@ -1,5 +1,24 @@
1
+ 1.0.12
2
+ - Fix bug where specifying the wt property as a string, would add the supplied value to the default ('ruby') rather than overriding it.
3
+
4
+ 1.0.11
5
+ - add RSolr.solr_escape method and add deprecation messages to RSolr.escape (ndushay)
6
+ - use stdlib URI.escape methods instead of homegrown in RSolr::URI (ndushay)
7
+ - fix bug with Rsolr::Uri.create adding trailing slash if query params (ndushay)
8
+ - update rake tasks (cbeer)
9
+ - add Ruby 2.2.0 to travis ci build (ndushay)
10
+ - Housekeeping (badges to README, license in gemspec, correct url in gemspec ...) (ndushay)
11
+ - Improve rdoc styling (udaykadaboina)
12
+ - Support setting default_wt per connection via its options. (jcoleman)
13
+ - eliminates the usage of per-instance `extend` (jcoleman)
14
+ - Upgrade to RSpec 3 (blackwinter, adamjonas, cbeer)
15
+ - Fixed RSolr::Error to_s (PofMagicfingers)
16
+ 1.0.10 xxx
17
+
1
18
  1.0.8
2
19
  - Fix connection refused errors in specs + add basic auth support (Denis Goeury)
20
+ - Ability to set :retry_503, the number of retry attempts for a 503 response
21
+ with a Retry-After header.
3
22
  1.0.7
4
23
  - Response body encoding is set to response charset in Ruby >= 1.9
5
24
  - Ability to set :read_timeout and :open_timeout when creating new instance of RSolr
@@ -14,4 +33,4 @@
14
33
  - Jeweler is no longer used for building the gemspec
15
34
  1.0.3
16
35
  - Proper encodings in Ruby 1.9
17
- - Applied pull request from https://github.com/mwmitchell/rsolr/pull/20
36
+ - Applied pull request from https://github.com/mwmitchell/rsolr/pull/20
data/Gemfile CHANGED
@@ -1,15 +1,9 @@
1
- source "http://rubygems.org"
1
+ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
5
  gem "builder", ">= 2.1.2"
6
6
 
7
- group :development do
8
- gem "rake", "~> 0.9.2"
9
- gem "rdoc", "~> 3.9.4"
10
- end
11
-
12
- group :test do
13
- gem "rake", "~> 0.9.2"
14
- gem "rspec", "~> 2.6.0"
7
+ if defined? RUBY_VERSION and RUBY_VERSION < "1.9"
8
+ gem 'nokogiri', "< 1.6"
15
9
  end
data/README.rdoc CHANGED
@@ -1,12 +1,14 @@
1
1
  =RSolr
2
+ {<img src="https://travis-ci.org/rsolr/rsolr.svg?branch=master" alt="Build Status" />}[https://travis-ci.org/rsolr/rsolr] {<img src="https://badge.fury.io/rb/rsolr.svg" alt="Gem Version" />}[http://badge.fury.io/rb/rsolr]
3
+
2
4
 
3
5
  A simple, extensible Ruby client for Apache Solr.
4
6
 
5
7
  ==Documentation
6
- The code docs for the last *release* can be viewed here: http://rubydoc.info/gems/rsolr/1.0.6/frames
8
+ The code docs http://www.rubydoc.info/gems/rsolr
7
9
 
8
10
  == Installation:
9
- sudo gem install rsolr
11
+ gem install rsolr
10
12
 
11
13
  == Example:
12
14
  require 'rubygems'
@@ -24,18 +26,25 @@ The code docs for the last *release* can be viewed here: http://rubydoc.info/gem
24
26
  # send a request to /catalog
25
27
  response = solr.get 'catalog', :params => {:q => '*:*'}
26
28
 
27
- When the Solr :wt is :ruby, then the response will be a Hash. This Hash is the same object returned by Solr, but evaluated as Ruby. If the :wt is not :ruby, then the response will be a String.
29
+ When the Solr +:wt+ is +:ruby+, then the response will be a Hash. This Hash is the same object returned by Solr, but evaluated as Ruby. If the +:wt+ is not +:ruby+, then the response will be a String.
28
30
 
29
- The response also exposes 2 attribute readers (for any :wt value), :request and :response. Both are Hash objects with symbolized keys.
31
+ The response also exposes 2 attribute readers (for any +:wt+ value), +:request+ and +:response+. Both are Hash objects with symbolized keys.
30
32
 
31
- The :request attribute contains the original request context. You can use this for debugging or logging. Some of the keys this object contains are :uri, :query, :method etc..
33
+ The +:request+ attribute contains the original request context. You can use this for debugging or logging. Some of the keys this object contains are +:uri+, +:query+, +:method+ etc..
32
34
 
33
- The :response attribute contains the original response. This object contains the :status, :body and :headers keys.
35
+ The +:response+ attribute contains the original response. This object contains the +:status+, +:body+ and +:headers+ keys.
34
36
 
35
37
  == Timeouts
36
38
  The read and connect timeout settings can be set when creating a new instance of RSolr:
37
39
  solr = RSolr.connect(:read_timeout => 120, :open_timeout => 120)
38
40
 
41
+ == Retry 503s
42
+ A 503 is usually a temporary error which RSolr may retry if requested. You may specify the number of retry attempts with the +:retry_503+ option.
43
+
44
+ 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
+ solr = RSolr.connect(:retry_503 => 1, :retry_after_limit => 1)
46
+
47
+
39
48
  == Querying
40
49
  Use the #get / #post method to send search requests to the /select handler:
41
50
  response = solr.get 'select', :params => {
@@ -45,7 +54,7 @@ Use the #get / #post method to send search requests to the /select handler:
45
54
  }
46
55
  response["response"]["docs"].each{|doc| puts doc["id"] }
47
56
 
48
- The :params sent into the method are sent to Solr as-is, which is to say they are converted to Solr url style, but no special mapping is used.
57
+ The +:params+ sent into the method are sent to Solr as-is, which is to say they are converted to Solr url style, but no special mapping is used.
49
58
  When an array is used, multiple parameters *with the same name* are generated for the Solr query. Example:
50
59
 
51
60
  solr.get 'select', :params => {:q=>'roses', :fq=>['red', 'violet']}
@@ -64,7 +73,7 @@ The paginate method returns WillPaginate ready "docs" objects, so for example in
64
73
  <%= will_paginate @solr_response["response"]["docs"] %>
65
74
 
66
75
  ===Method Missing
67
- The RSolr::Client class also uses method_missing for setting the request handler/path:
76
+ The +RSolr::Client+ class also uses +method_missing+ for setting the request handler/path:
68
77
 
69
78
  solr.paintings :params => {:q=>'roses', :fq=>['red', 'violet']}
70
79
 
@@ -79,7 +88,7 @@ This works with pagination as well:
79
88
  There may be cases where the query string is too long for a GET request. RSolr solves this issue by converting hash objects into form-encoded strings:
80
89
  response = solr.music :data => {:q => "*:*"}
81
90
 
82
- The :data hash is serialized as a form-encoded query string, and the correct content-type headers are sent along to Solr.
91
+ The +:data+ hash is serialized as a form-encoded query string, and the correct content-type headers are sent along to Solr.
83
92
 
84
93
  ===Sending HEAD Requests
85
94
  There may be cases where you'd like to send a HEAD request to Solr:
@@ -87,11 +96,11 @@ There may be cases where you'd like to send a HEAD request to Solr:
87
96
 
88
97
  ==Sending HTTP Headers
89
98
  Solr responds to the request headers listed here: http://wiki.apache.org/solr/SolrAndHTTPCaches
90
- To send header information to Solr using RSolr, just use the :headers option:
99
+ To send header information to Solr using RSolr, just use the +:headers+ option:
91
100
  response = solr.head "admin/ping", :headers => {"Cache-Control" => "If-None-Match"}
92
101
 
93
102
  ===Building a Request
94
- RSolr::Client provides a method for building a request context, which can be useful for debugging or logging etc.:
103
+ +RSolr::Client+ provides a method for building a request context, which can be useful for debugging or logging etc.:
95
104
  request_context = solr.build_request "select", :data => {:q => "*:*"}, :method => :post, :headers => {}
96
105
 
97
106
  To build a paginated request use build_paginated_request:
@@ -107,7 +116,7 @@ Multiple documents via #add
107
116
  documents = [{:id=>1, :price=>1.00}, {:id=>2, :price=>10.50}]
108
117
  solr.add documents
109
118
 
110
- The optional :add_attributes hash can also be used to set Solr "add" document attributes:
119
+ The optional +:add_attributes+ hash can also be used to set Solr "add" document attributes:
111
120
  solr.add documents, :add_attributes => {:commitWithin => 10}
112
121
 
113
122
  Raw XML via #update
@@ -144,7 +153,7 @@ Delete by array of queries
144
153
  solr.optimize, :optimize_attributes => {}
145
154
 
146
155
  == Response Formats
147
- 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..
156
+ 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..
148
157
 
149
158
  ===Evaluated Ruby (default)
150
159
  solr.get 'select', :params => {:wt => :ruby} # notice :ruby is a Symbol
@@ -176,27 +185,21 @@ The default response format is Ruby. When the :wt param is set to :ruby, the res
176
185
  * Send me a pull request. Bonus points for topic branches.
177
186
 
178
187
  ==Contributors
179
- * Antoine Latter
180
- * Dmitry Lihachev
181
- * Lucas Souza
182
- * Peter Kieltyka
183
- * Rob Di Marco
188
+ * Nathan Witmer
184
189
  * Magnus Bergmark
185
- * Jonathan Rochkind
186
- * Chris Beer
187
- * Craig Smith
190
+ * shima
188
191
  * Randy Souza
189
- * Colin Steele
190
- * Peter Kieltyka
191
- * Lorenzo Riccucci
192
- * Mike Perham
193
192
  * Mat Brown
194
- * Shairon Toledo
195
- * Matthew Rudy
196
- * Fouad Mardini
197
193
  * Jeremy Hinegardner
198
- * Nathan Witmer
199
- * "shima"
194
+ * Denis Goeury
195
+ * shairon toledo
196
+ * Rob Di Marco
197
+ * Peter Kieltyka
198
+ * Mike Perham
199
+ * Lucas Souza
200
+ * Dmitry Lihachev
201
+ * Antoine Latter
202
+ * Naomi Dushay
200
203
 
201
204
  ==Author
202
205
 
@@ -204,4 +207,4 @@ Matt Mitchell <mailto:goodieboy@gmail.com>
204
207
 
205
208
  ==Copyright
206
209
 
207
- Copyright (c) 2008-2010 Matt Mitchell. See LICENSE for details.
210
+ Copyright (c) 2008-2010 Matt Mitchell. See LICENSE for details.
data/Rakefile CHANGED
@@ -1,15 +1,6 @@
1
1
  require 'rake'
2
- require 'rake/testtask'
3
2
  require 'bundler/gem_tasks'
4
3
 
5
- require 'rubygems/package_task'
6
-
7
- ENV['RUBYOPT'] = '-W1'
8
-
9
- task :environment do
10
- require File.dirname(__FILE__) + '/lib/rsolr'
11
- end
12
-
13
4
  Dir['tasks/**/*.rake'].each { |t| load t }
14
5
 
15
- task :default => ['spec:api']
6
+ task :default => ['spec']
data/lib/rsolr.rb CHANGED
@@ -1,14 +1,6 @@
1
- $: << "#{File.dirname(__FILE__)}" unless $:.include? File.dirname(__FILE__)
2
-
3
- require 'rubygems'
4
-
5
1
  module RSolr
6
2
 
7
- %W(Response Char Client Error Connection Uri Xml).each{|n|autoload n.to_sym, "rsolr/#{n.downcase}"}
8
-
9
- def self.version; "1.0.8" end
10
-
11
- VERSION = self.version
3
+ Dir.glob(File.expand_path("../rsolr/*.rb", __FILE__)).each{|rb_file| require(rb_file)}
12
4
 
13
5
  def self.connect *args
14
6
  driver = Class === args[0] ? args[0] : RSolr::Connection
@@ -16,7 +8,19 @@ module RSolr
16
8
  Client.new driver.new, opts
17
9
  end
18
10
 
19
- # RSolr.escape
11
+ # RSolr.escape, which is deprecated as of 2015-02
20
12
  extend Char
21
13
 
14
+ # backslash escape characters that have special meaning to Solr query parser
15
+ # per http://lucene.apache.org/core/4_0_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#Escaping_Special_Characters
16
+ # + - & | ! ( ) { } [ ] ^ " ~ * ? : \ /
17
+ # see also http://svn.apache.org/repos/asf/lucene/dev/tags/lucene_solr_4_9_1/solr/solrj/src/java/org/apache/solr/client/solrj/util/ClientUtils.java
18
+ # escapeQueryChars method
19
+ # @return [String] str with special chars preceded by a backslash
20
+ def self.solr_escape(str)
21
+ # note that the gsub will parse the escaped backslashes, as will the ruby code sending the query to Solr
22
+ # so the result sent to Solr is ultimately a single backslash in front of the particular character
23
+ str.gsub(/([+\-&|!\(\)\{\}\[\]\^"~\*\?:\\\/])/, '\\\\\1')
24
+ end
25
+
22
26
  end
data/lib/rsolr/char.rb CHANGED
@@ -1,9 +1,12 @@
1
1
  # A module that contains (1) string related methods
2
+ # @deprecated remove this module when we remove the method (duh)
2
3
  module RSolr::Char
3
4
 
4
5
  # backslash everything
5
6
  # that isn't a word character
7
+ # @deprecated - this is incorrect Solr escaping
6
8
  def escape value
9
+ warn "[DEPRECATION] `RSolr.escape` is deprecated (and incorrect). Use `RSolr.solr_escape` instead."
7
10
  value.gsub(/(\W)/, '\\\\\1')
8
11
  end
9
12
 
@@ -18,4 +21,4 @@ module RSolr::Char
18
21
  # }.join(delim)
19
22
  # end
20
23
 
21
- end
24
+ end
data/lib/rsolr/client.rb CHANGED
@@ -1,7 +1,22 @@
1
+ begin
2
+ require 'json'
3
+ rescue LoadError
4
+ end
5
+
1
6
  class RSolr::Client
2
-
3
- attr_reader :connection, :uri, :proxy, :options
4
-
7
+
8
+ class << self
9
+ def default_wt
10
+ @default_wt || :ruby
11
+ end
12
+
13
+ def default_wt= value
14
+ @default_wt = value
15
+ end
16
+ end
17
+
18
+ attr_reader :connection, :uri, :proxy, :options, :update_path
19
+
5
20
  def initialize connection, options = {}
6
21
  @proxy = @uri = nil
7
22
  @connection = connection
@@ -13,22 +28,24 @@ class RSolr::Client
13
28
  proxy_url = options[:proxy].dup
14
29
  proxy_url << "/" unless proxy_url.nil? or proxy_url[-1] == ?/
15
30
  @proxy = RSolr::Uri.create proxy_url if proxy_url
31
+ elsif options[:proxy] == false
32
+ @proxy = false # used to avoid setting the proxy from the environment.
16
33
  end
17
34
  end
35
+ @update_path = options.fetch(:update_path, 'update')
18
36
  @options = options
19
37
  end
20
-
38
+
21
39
  # returns the request uri object.
22
40
  def base_request_uri
23
41
  base_uri.request_uri if base_uri
24
42
  end
25
-
26
- # returns the uri proxy if present,
27
- # otherwise just the uri object.
43
+
44
+ # returns the RSolr::URI uri object.
28
45
  def base_uri
29
- @proxy ? @proxy : @uri
46
+ @uri
30
47
  end
31
-
48
+
32
49
  # Create the get, post, and head methods
33
50
  %W(get post head).each do |meth|
34
51
  class_eval <<-RUBY
@@ -37,7 +54,7 @@ class RSolr::Client
37
54
  end
38
55
  RUBY
39
56
  end
40
-
57
+
41
58
  # A paginated request method.
42
59
  # Converts the page and per_page
43
60
  # arguments into "rows" and "start".
@@ -47,9 +64,9 @@ class RSolr::Client
47
64
  raise "'rows' or 'start' params should not be set when using +paginate+" if ["start", "rows"].include?(opts[:params].keys)
48
65
  execute build_paginated_request(page, per_page, path, opts)
49
66
  end
50
-
67
+
51
68
  # POST XML messages to /update with optional params.
52
- #
69
+ #
53
70
  # http://wiki.apache.org/solr/UpdateXmlMessages#add.2BAC8-update
54
71
  #
55
72
  # If not set, opts[:headers] will be set to a hash with the key
@@ -64,24 +81,24 @@ class RSolr::Client
64
81
  def update opts = {}
65
82
  opts[:headers] ||= {}
66
83
  opts[:headers]['Content-Type'] ||= 'text/xml'
67
- post 'update', opts
84
+ post opts.fetch(:path, update_path), opts
68
85
  end
69
-
70
- #
86
+
87
+ #
71
88
  # +add+ creates xml "add" documents and sends the xml data to the +update+ method
72
- #
89
+ #
73
90
  # http://wiki.apache.org/solr/UpdateXmlMessages#add.2BAC8-update
74
- #
91
+ #
75
92
  # single record:
76
- # solr.update(:id=>1, :name=>'one')
93
+ # solr.add(:id=>1, :name=>'one')
94
+ #
95
+ # add using an array
77
96
  #
78
- # update using an array
79
- #
80
- # solr.update(
97
+ # solr.add(
81
98
  # [{:id=>1, :name=>'one'}, {:id=>2, :name=>'two'}],
82
99
  # :add_attributes => {:boost=>5.0, :commitWithin=>10}
83
100
  # )
84
- #
101
+ #
85
102
  def add doc, opts = {}
86
103
  add_attributes = opts.delete :add_attributes
87
104
  update opts.merge(:data => xml.add(doc, add_attributes))
@@ -104,16 +121,16 @@ class RSolr::Client
104
121
  optimize_attributes = opts.delete :optimize_attributes
105
122
  update opts.merge(:data => xml.optimize(optimize_attributes))
106
123
  end
107
-
124
+
108
125
  # send </rollback>
109
- #
126
+ #
110
127
  # http://wiki.apache.org/solr/UpdateXmlMessages#A.22rollback.22
111
- #
128
+ #
112
129
  # NOTE: solr 1.4 only
113
130
  def rollback opts = {}
114
131
  update opts.merge(:data => xml.rollback)
115
132
  end
116
-
133
+
117
134
  # Delete one or many documents by id
118
135
  # solr.delete_by_id 10
119
136
  # solr.delete_by_id([12, 41, 199])
@@ -122,22 +139,22 @@ class RSolr::Client
122
139
  end
123
140
 
124
141
  # delete one or many documents by query.
125
- #
142
+ #
126
143
  # http://wiki.apache.org/solr/UpdateXmlMessages#A.22delete.22_by_ID_and_by_Query
127
- #
144
+ #
128
145
  # solr.delete_by_query 'available:0'
129
146
  # solr.delete_by_query ['quantity:0', 'manu:"FQ"']
130
147
  def delete_by_query query, opts = {}
131
148
  update opts.merge(:data => xml.delete_by_query(query))
132
149
  end
133
-
150
+
134
151
  # shortcut to RSolr::Xml::Generator
135
152
  def xml
136
153
  @xml ||= RSolr::Xml::Generator.new
137
154
  end
138
-
155
+
139
156
  # +send_and_receive+ is the main request method responsible for sending requests to the +connection+ object.
140
- #
157
+ #
141
158
  # "path" : A string value that usually represents a solr request handler
142
159
  # "opts" : A hash, which can contain the following keys:
143
160
  # :method : required - the http method (:get, :post or :head)
@@ -145,7 +162,7 @@ class RSolr::Client
145
162
  # :data : optional - post data -- if a hash is given, it's sent as "application/x-www-form-urlencoded; charset=UTF-8"
146
163
  # :headers : optional - hash of request headers
147
164
  # All other options are passed right along to the connection's +send_and_receive+ method (:get, :post, or :head)
148
- #
165
+ #
149
166
  # +send_and_receive+ returns either a string or hash on a successful ruby request.
150
167
  # When the :params[:wt] => :ruby, the response will be a hash, else a string.
151
168
  #
@@ -155,18 +172,53 @@ class RSolr::Client
155
172
  # then passes the request/response into +adapt_response+.
156
173
  def send_and_receive path, opts
157
174
  request_context = build_request path, opts
158
- [:open_timeout, :read_timeout].each do |k|
159
- request_context[k] = @options[k]
160
- end
161
175
  execute request_context
162
176
  end
163
-
164
- #
177
+
178
+ #
165
179
  def execute request_context
180
+
166
181
  raw_response = connection.execute self, request_context
182
+
183
+ while retry_503?(request_context, raw_response)
184
+ request_context[:retry_503] -= 1
185
+ sleep retry_after(raw_response)
186
+ raw_response = connection.execute self, request_context
187
+ end
188
+
167
189
  adapt_response(request_context, raw_response) unless raw_response.nil?
168
190
  end
169
-
191
+
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
+
170
222
  # +build_request+ accepts a path and options hash,
171
223
  # then prepares a normalized hash to return for sending
172
224
  # to a solr connection driver.
@@ -187,7 +239,7 @@ class RSolr::Client
187
239
  opts[:proxy] = proxy unless proxy.nil?
188
240
  opts[:method] ||= :get
189
241
  raise "The :data option can only be used if :method => :post" if opts[:method] != :post and opts[:data]
190
- opts[:params] = opts[:params].nil? ? {:wt => :ruby} : {:wt => :ruby}.merge(opts[:params])
242
+ opts[:params] = params_with_wt(opts[:params])
191
243
  query = RSolr::Uri.params_to_solr(opts[:params]) unless opts[:params].empty?
192
244
  opts[:query] = query
193
245
  if opts[:data].is_a? Hash
@@ -197,9 +249,20 @@ class RSolr::Client
197
249
  end
198
250
  opts[:path] = path
199
251
  opts[:uri] = base_uri.merge(path.to_s + (query ? "?#{query}" : "")) if base_uri
252
+
253
+ [:open_timeout, :read_timeout, :retry_503, :retry_after_limit].each do |k|
254
+ opts[k] = @options[k]
255
+ end
256
+
200
257
  opts
201
258
  end
202
-
259
+
260
+ def params_with_wt(params)
261
+ return { wt: default_wt } if params.nil?
262
+ return params if params.key?(:wt) || params.key?('wt')
263
+ { wt: default_wt }.merge(params)
264
+ end
265
+
203
266
  def build_paginated_request page, per_page, path, opts
204
267
  per_page = per_page.to_s.to_i
205
268
  page = page.to_s.to_i-1
@@ -208,12 +271,7 @@ class RSolr::Client
208
271
  opts[:params]["rows"] = per_page
209
272
  build_request path, opts
210
273
  end
211
-
212
- # A mixin for used by #adapt_response
213
- module Context
214
- attr_accessor :request, :response
215
- end
216
-
274
+
217
275
  # This method will evaluate the :body value
218
276
  # if the params[:uri].params[:wt] == :ruby
219
277
  # ... otherwise, the body is returned as is.
@@ -228,14 +286,22 @@ class RSolr::Client
228
286
  raise "The response does not have the correct keys => :body, :headers, :status" unless
229
287
  %W(body headers status) == response.keys.map{|k|k.to_s}.sort
230
288
  raise RSolr::Error::Http.new request, response unless [200,302].include? response[:status]
231
- result = request[:params][:wt] == :ruby ? evaluate_ruby_response(request, response) : response[:body]
232
- result.extend Context
233
- result.request, result.response = request, response
234
- result.is_a?(Hash) ? result.extend(RSolr::Response) : result
289
+
290
+ result = if respond_to? "evaluate_#{request[:params][:wt]}_response", true
291
+ send "evaluate_#{request[:params][:wt]}_response", request, response
292
+ else
293
+ response[:body]
294
+ end
295
+
296
+ if result.is_a?(Hash) || request[:method] == :head
297
+ result = RSolr::HashWithResponse.new(request, response, result)
298
+ end
299
+
300
+ result
235
301
  end
236
-
302
+
237
303
  protected
238
-
304
+
239
305
  # converts the method name for the solr request handler path.
240
306
  def method_missing name, *args
241
307
  if name.to_s =~ /^paginated?_(.+)$/
@@ -244,7 +310,7 @@ class RSolr::Client
244
310
  send_and_receive name, *args
245
311
  end
246
312
  end
247
-
313
+
248
314
  # evaluates the response[:body],
249
315
  # attempts to bring the ruby string to life.
250
316
  # If a SyntaxError is raised, then
@@ -259,5 +325,18 @@ class RSolr::Client
259
325
  raise RSolr::Error::InvalidRubyResponse.new request, response
260
326
  end
261
327
  end
262
-
328
+
329
+ def evaluate_json_response request, response
330
+ return response[:body] unless defined? JSON
331
+
332
+ begin
333
+ JSON.parse response[:body].to_s
334
+ rescue JSON::ParserError
335
+ raise RSolr::Error::InvalidJsonResponse.new request, response
336
+ end
337
+ end
338
+
339
+ def default_wt
340
+ self.options[:default_wt] || self.class.default_wt
341
+ end
263
342
  end