rsolr 1.0.8 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
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