rsolr 2.5.0 → 3.0.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f44e7e34b8e615204b49052907e322c46387d858f147b7e34bd4c53edf6b336e
4
- data.tar.gz: b5ad262ba4b5777f18b817c529f9cb8768843972f394420a4798191f92a11b17
3
+ metadata.gz: 7cd06ee9f0201b75d69b9f7d02f5ad6641272e5ec8d6d1eaa1b57aaedc90daef
4
+ data.tar.gz: 277248ac909e888160f8addac51fa01d44dc26cb089b8bfcbdb3ed93263015c9
5
5
  SHA512:
6
- metadata.gz: c230788c63b34623fa05608af73c25c5c7bd6fbab106afc62c63b1347a688bf302d0b03323204b0efd047f01ddc2d957722cd5ed0f98553ec3974b7ed2653c79
7
- data.tar.gz: 606324146e3acb8cb86c726a528550fefd0bd57fdebce977fc260c5a38caf4b1c5aeca7c3f23637dcf4bf04e8fbc196e60e4cc63f9827ee7e88af01e816ce3a4
6
+ metadata.gz: e095fbdf8f63f68eeb5b9919b6cf61d745b1dd044d819f2a762dbf82bf3b9bf813b0b022c61709f57e3f080ce96104e453d22db120d2d62f1a94453cf58b145c
7
+ data.tar.gz: 8ff5849b11a1bb25f315cd5373354dd2479d7c0725d8092b76e8360fb31886f3d406f4d2cecf898003d11124af0566528aa6f9dd860680510875008a10afe046
@@ -2,43 +2,30 @@ name: CI
2
2
 
3
3
  on:
4
4
  push:
5
- branches: [ master ]
5
+ branches: [main]
6
6
  pull_request:
7
- branches: [ master ]
7
+ branches: [main]
8
8
 
9
9
  jobs:
10
10
  tests:
11
11
  runs-on: ubuntu-latest
12
12
  strategy:
13
13
  matrix:
14
- ruby: [jruby-9.3.3.0, 2.7, '3.0', '3.1']
15
- faraday: ['~> 0.17', '~> 1', '~>2']
14
+ ruby: [jruby-10.0.3.0, "3.2", "3.3", "3.4", "4.0"]
15
+ faraday: ["~> 1", "~>2"]
16
16
  steps:
17
- - uses: actions/checkout@v2
18
- - name: Set up Ruby
19
- uses: ruby/setup-ruby@v1
20
- with:
21
- ruby-version: ${{ matrix.ruby }}
22
- - name: Install dependencies
23
- run: bundle install
24
- env:
25
- FARADAY_VERSION: ${{ matrix.faraday}}
26
- - name: Run tests
27
- run: bundle exec rake
28
- env:
29
- FARADAY_VERSION: ${{ matrix.faraday}}
30
- legacy_tests:
31
- runs-on: ubuntu-latest
32
- strategy:
33
- matrix:
34
- ruby: [jruby-9.2.20.0, 2.4, 2.5, 2.6, 2.7]
35
- steps:
36
- - uses: actions/checkout@v2
37
- - name: Set up Ruby
38
- uses: ruby/setup-ruby@v1
39
- with:
40
- ruby-version: ${{ matrix.ruby }}
41
- - name: Install dependencies
42
- run: bundle install
43
- - name: Run tests
44
- run: bundle exec rake
17
+ - uses: actions/checkout@v7
18
+ - name: Set up Ruby
19
+ uses: ruby/setup-ruby@v1
20
+ with:
21
+ ruby-version: ${{ matrix.ruby }}
22
+ - name: Install dependencies
23
+ run: bundle install
24
+ env:
25
+ FARADAY_VERSION: ${{ matrix.faraday}}
26
+ - name: Start Solr
27
+ run: docker compose up -d --wait --wait-timeout 60
28
+ - name: Run tests
29
+ run: bundle exec rake
30
+ env:
31
+ FARADAY_VERSION: ${{ matrix.faraday}}
data/CHANGES.txt CHANGED
@@ -1,3 +1,25 @@
1
+ 3.0.0
2
+
3
+ - Drop faraday 0.x support by @jcoyne in https://github.com/rsolr/rsolr/pull/255
4
+ - Allow for setting a default http method by @cjcolvar in https://github.com/rsolr/rsolr/pull/252
5
+ - Move query params into data hash when using post and no data is provided by @cjcolvar in https://github.com/rsolr/rsolr/pull/253
6
+ - Support HTTP Basic Auth via a basic_auth: option (in addition to URL-embedded) by @maxkadel in https://github.com/rsolr/rsolr/pull/259
7
+ - Redact only basic auth credentials from Faraday's cause exception by @maxkadel in https://github.com/rsolr/rsolr/pull/261
8
+
9
+ **Full Changelog**: https://github.com/rsolr/rsolr/compare/v2.6.0...v3.0.0
10
+
11
+ 2.6.0
12
+
13
+ - Stop testing on Ruby 2. https://github.com/rsolr/rsolr/pull/237
14
+ - Set solr version to 8.11.3. https://github.com/rsolr/rsolr/pull/238
15
+ - Add newer rubies to the test matrix. https://github.com/rsolr/rsolr/pull/239
16
+ - Sanitizing URIs displayed in error messages. https://github.com/rsolr/rsolr/pull/236
17
+
18
+ 2.5.0
19
+
20
+ - Sorry, not human-edited: https://github.com/rsolr/rsolr/compare/v2.4.0...v2.5.0
21
+
22
+
1
23
  2.4.0
2
24
 
3
25
  - Raise specific timeout error for solr timeouts. https://github.com/rsolr/rsolr/pull/214
data/Gemfile CHANGED
@@ -4,10 +4,4 @@ gemspec
4
4
 
5
5
  gem "builder", ">= 2.1.2"
6
6
 
7
- if defined? JRUBY_VERSION
8
- # HTTP.rb (used by solr_wrapper to download solr for integration testing) fails
9
- # to download the full contents of files (under jruby)?
10
- gem "http", '< 5', platforms: :jruby
11
- end
12
-
13
7
  gem 'faraday', ENV['FARADAY_VERSION'] if ENV['FARADAY_VERSION']
data/README.md ADDED
@@ -0,0 +1,370 @@
1
+ # RSolr
2
+
3
+ A simple, extensible Ruby client for Apache Solr.
4
+
5
+ ## Documentation
6
+
7
+ The code docs: http://www.rubydoc.info/gems/rsolr
8
+
9
+ ## Installation
10
+
11
+ ```
12
+ gem install rsolr
13
+ ```
14
+
15
+ ## Example
16
+
17
+ ```ruby
18
+ require 'rsolr'
19
+
20
+ # Direct connection
21
+ solr = RSolr.connect :url => 'http://solrserver.com'
22
+
23
+ # Connecting over a proxy server
24
+ solr = RSolr.connect :url => 'http://solrserver.com', :proxy=>'http://user:pass@proxy.example.com:8080'
25
+
26
+ # Using an alternate Faraday adapter
27
+ solr = RSolr.connect :url => 'http://solrserver.com', :adapter => :em_http
28
+
29
+ # Using a custom Faraday connection
30
+ conn = Faraday.new do |faraday|
31
+ faraday.response :logger # log requests to STDOUT
32
+ faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
33
+ end
34
+ solr = RSolr.connect conn, :url => 'http://solrserver.com'
35
+
36
+ # send a request to /select
37
+ response = solr.get 'select', :params => {:q => '*:*'}
38
+
39
+ # send a request to /catalog
40
+ response = solr.get 'catalog', :params => {:q => '*:*'}
41
+ ```
42
+
43
+ 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.
44
+
45
+ The response also exposes 2 attribute readers (for any `:wt` value), `:request` and `:response`. Both are Hash objects with symbolized keys.
46
+
47
+ 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..
48
+
49
+ The `:response` attribute contains the original response. This object contains the `:status`, `:body` and `:headers` keys.
50
+
51
+ ## Basic Auth
52
+
53
+ Credentials can be embedded in the URL:
54
+
55
+ ```ruby
56
+ solr = RSolr.connect :url => 'http://user:pass@solrserver.com'
57
+ ```
58
+
59
+ or passed explicitly via `:basic_auth`, which is useful if you'd rather keep
60
+ secrets out of a URL string (logs, error messages, etc. tend to capture URLs
61
+ more casually than headers):
62
+
63
+ ```ruby
64
+ solr = RSolr.connect :url => 'http://solrserver.com', :basic_auth => { :user => 'user', :password => 'pass' }
65
+ ```
66
+
67
+ `:basic_auth` accepts string or symbol keys (`'user'`/`'password'`
68
+ work the same as `:user`/`:password`), so a hash loaded straight
69
+ from YAML config works without re-symbolizing it yourself.
70
+
71
+ If both are given, `:basic_auth` wins. Either way, this only protects the
72
+ credential from casual logging - it doesn't encrypt anything in transit, so
73
+ use `https://` if the connection isn't otherwise trusted (e.g. firewalled).
74
+
75
+ ## Request formats
76
+
77
+ By default, RSolr uses the Solr JSON command format for all requests.
78
+
79
+ ```ruby
80
+ RSolr.connect :url => 'http://solrserver.com', update_format: :json # the default
81
+ # or
82
+ RSolr.connect :url => 'http://solrserver.com', update_format: :xml
83
+ ```
84
+
85
+ ## Timeouts
86
+
87
+ The read and connect timeout settings can be set when creating a new instance of RSolr, and will
88
+ be passed on to underlying Faraday instance:
89
+
90
+ ```ruby
91
+ solr = RSolr.connect(:timeout => 120, :open_timeout => 120)
92
+ ```
93
+
94
+ ## Retry 503s
95
+
96
+ 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.
97
+
98
+ 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).
99
+
100
+ ```ruby
101
+ solr = RSolr.connect(:retry_503 => 1, :retry_after_limit => 1)
102
+ ```
103
+
104
+ For additional control, consider using a custom Faraday connection (see above) using its `retry` middleware.
105
+
106
+ ## Querying
107
+
108
+ Use the `#get` / `#post` method to send search requests to the /select handler:
109
+
110
+ ```ruby
111
+ response = solr.get 'select', :params => {
112
+ :q=>'washington',
113
+ :start=>0,
114
+ :rows=>10
115
+ }
116
+ response["response"]["docs"].each{|doc| puts doc["id"] }
117
+ ```
118
+
119
+ 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.
120
+ When an array is used, multiple parameters **with the same name** are generated for the Solr query. Example:
121
+
122
+ ```ruby
123
+ solr.get 'select', :params => {:q=>'roses', :fq=>['red', 'violet']}
124
+ ```
125
+
126
+ The above statement generates this Solr query:
127
+
128
+ ```
129
+ select?q=roses&fq=red&fq=violet
130
+ ```
131
+
132
+ ### Pagination
133
+
134
+ To paginate through a set of Solr documents, use the paginate method:
135
+
136
+ ```ruby
137
+ solr.paginate 1, 10, "select", :params => {:q => "test"}
138
+ ```
139
+
140
+ The first argument is the current page, the second is how many documents to return for each page. In other words, "page" is the "start" Solr param and "per-page" is the "rows" Solr param.
141
+
142
+ The paginate method returns WillPaginate ready "docs" objects, so for example in a Rails application, paginating is as simple as:
143
+
144
+ ```erb
145
+ <%= will_paginate @solr_response["response"]["docs"] %>
146
+ ```
147
+
148
+ ### Method Missing
149
+
150
+ The `RSolr::Client` class also uses `method_missing` for setting the request handler/path:
151
+
152
+ ```ruby
153
+ solr.paintings :params => {:q=>'roses', :fq=>['red', 'violet']}
154
+ ```
155
+
156
+ This is sent to Solr as:
157
+
158
+ ```
159
+ paintings?q=roses&fq=red&fq=violet
160
+ ```
161
+
162
+ This works with pagination as well:
163
+
164
+ ```ruby
165
+ solr.paginate_paintings 1, 10, {:q=>'roses', :fq=>['red', 'violet']}
166
+ ```
167
+
168
+ ### Using POST for Search Queries
169
+
170
+ 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:
171
+
172
+ ```ruby
173
+ response = solr.music :data => {:q => "*:*"}
174
+ ```
175
+
176
+ The `:data` hash is serialized as a form-encoded query string, and the correct content-type headers are sent along to Solr.
177
+
178
+ ### Sending HEAD Requests
179
+
180
+ There may be cases where you'd like to send a HEAD request to Solr:
181
+
182
+ ```ruby
183
+ solr.head("admin/ping").response[:status] == 200
184
+ ```
185
+
186
+ ## Sending HTTP Headers
187
+
188
+ Solr responds to the request headers listed here: http://wiki.apache.org/solr/SolrAndHTTPCaches
189
+ To send header information to Solr using RSolr, just use the `:headers` option:
190
+
191
+ ```ruby
192
+ response = solr.head "admin/ping", :headers => {"Cache-Control" => "If-None-Match"}
193
+ ```
194
+
195
+ ### Building a Request
196
+
197
+ `RSolr::Client` provides a method for building a request context, which can be useful for debugging or logging etc.:
198
+
199
+ ```ruby
200
+ request_context = solr.build_request "select", :data => {:q => "*:*"}, :method => :post, :headers => {}
201
+ ```
202
+
203
+ To build a paginated request use build_paginated_request:
204
+
205
+ ```ruby
206
+ request_context = solr.build_paginated_request 1, 10, "select", ...
207
+ ```
208
+
209
+ ## Updating Solr
210
+
211
+ Updating is done using native Ruby objects. Hashes are used for single documents and arrays are used for a collection of documents (hashes). These objects get turned into simple XML "messages". Raw XML strings can also be used.
212
+
213
+ Single document via `#add`
214
+
215
+ ```ruby
216
+ solr.add :id=>1, :price=>1.00
217
+ ```
218
+
219
+ Multiple documents via `#add`
220
+
221
+ ```ruby
222
+ documents = [{:id=>1, :price=>1.00}, {:id=>2, :price=>10.50}]
223
+ solr.add documents
224
+ ```
225
+
226
+ The optional `:add_attributes` hash can also be used to set Solr "add" document attributes:
227
+
228
+ ```ruby
229
+ solr.add documents, :add_attributes => {:commitWithin => 10}
230
+ ```
231
+
232
+ Raw commands via `#update`
233
+
234
+ ```ruby
235
+ solr.update data: '<commit/>', headers: { 'Content-Type' => 'text/xml' }
236
+ solr.update data: { optimize: true }.to_json, headers: { 'Content-Type' => 'application/json' }
237
+ ```
238
+
239
+ 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:
240
+
241
+ ```ruby
242
+ doc = {:id=>1, :price=>1.00}
243
+ add_attributes = {:allowDups=>false, :commitWithin=>10}
244
+ add_xml = solr.xml.add(doc, add_attributes) do |doc|
245
+ # boost each document
246
+ doc.attrs[:boost] = 1.5
247
+ # boost the price field:
248
+ doc.field_by_name(:price).attrs[:boost] = 2.0
249
+ end
250
+ ```
251
+
252
+ Now the "add_xml" object can be sent to Solr like:
253
+
254
+ ```ruby
255
+ solr.update :data => add_xml
256
+ ```
257
+
258
+ ### Deleting
259
+
260
+ Delete by id
261
+
262
+ ```ruby
263
+ solr.delete_by_id 1
264
+ ```
265
+
266
+ or an array of ids
267
+
268
+ ```ruby
269
+ solr.delete_by_id [1, 2, 3, 4]
270
+ ```
271
+
272
+ Delete by query:
273
+
274
+ ```ruby
275
+ solr.delete_by_query 'price:1.00'
276
+ ```
277
+
278
+ Delete by array of queries
279
+
280
+ ```ruby
281
+ solr.delete_by_query ['price:1.00', 'price:10.00']
282
+ ```
283
+
284
+ ### Commit / Optimize
285
+
286
+ ```ruby
287
+ solr.commit, :commit_attributes => {}
288
+ solr.optimize, :optimize_attributes => {}
289
+ ```
290
+
291
+ ## Response Formats
292
+
293
+ 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..
294
+
295
+ ### Evaluated Ruby:
296
+
297
+ ```ruby
298
+ solr.get 'select', :params => {:wt => :ruby} # notice :ruby is a Symbol
299
+ ```
300
+
301
+ ### Raw Ruby:
302
+
303
+ ```ruby
304
+ solr.get 'select', :params => {:wt => 'ruby'} # notice 'ruby' is a String
305
+ ```
306
+
307
+ ### XML:
308
+
309
+ ```ruby
310
+ solr.get 'select', :params => {:wt => :xml}
311
+ ```
312
+
313
+ ### JSON (default):
314
+
315
+ ```ruby
316
+ solr.get 'select', :params => {:wt => :json}
317
+ ```
318
+
319
+ ## Related Resources & Projects
320
+
321
+ * [RSolr Google Group](http://groups.google.com/group/rsolr) -- The RSolr discussion group
322
+ * [rsolr-ext](http://github.com/mwmitchell/rsolr-ext) -- An extension kit for RSolr
323
+ * [rsolr-direct](http://github.com/mwmitchell/rsolr-direct) -- JRuby direct connection for RSolr
324
+ * [rsolr-nokogiri](http://github.com/mwmitchell/rsolr-nokogiri) -- Gives RSolr Nokogiri for XML generation.
325
+ * [SunSpot](http://github.com/sunspot/sunspot) -- An awesome Solr DSL, built with RSolr
326
+ * [Blacklight](http://blacklightopac.org) -- A "next generation" Library OPAC, built with RSolr
327
+ * [java_bin](http://github.com/kennyj/java_bin) -- Provides javabin/binary parsing for RSolr
328
+ * [Solr](http://lucene.apache.org/solr/) -- The Apache Solr project
329
+ * [solr-ruby](http://wiki.apache.org/solr/solr-ruby) -- The original Solr Ruby Gem!
330
+
331
+ ## Running the tests
332
+
333
+ The integration specs (`spec/integration`) need a Solr instance;
334
+ run `docker compose up -d` before `bundle exec rspec` or
335
+ `bundle exec rake`.
336
+
337
+ ## Note on Patches/Pull Requests
338
+
339
+ * Fork the project.
340
+ * Make your feature addition or bug fix.
341
+ * Add tests for it. This is important so I don't break it in a future version unintentionally.
342
+ * Commit, do not mess with rakefile, version, or history
343
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
344
+ * Send me a pull request. Bonus points for topic branches.
345
+
346
+ ## Contributors
347
+
348
+ * Nathan Witmer
349
+ * Magnus Bergmark
350
+ * shima
351
+ * Randy Souza
352
+ * Mat Brown
353
+ * Jeremy Hinegardner
354
+ * Denis Goeury
355
+ * shairon toledo
356
+ * Rob Di Marco
357
+ * Peter Kieltyka
358
+ * Mike Perham
359
+ * Lucas Souza
360
+ * Dmitry Lihachev
361
+ * Antoine Latter
362
+ * Naomi Dushay
363
+
364
+ ## Author
365
+
366
+ Matt Mitchell <goodieboy@gmail.com>
367
+
368
+ ## Copyright
369
+
370
+ Copyright (c) 2008-2010 Matt Mitchell. See LICENSE for details.
data/Rakefile CHANGED
@@ -14,6 +14,6 @@ RDoc::Task.new(:doc) do |rdoc|
14
14
  rdoc.rdoc_dir = 'doc'
15
15
  rdoc.title = 'RSolr'
16
16
  rdoc.options << '--line-numbers' << '--inline-source'
17
- rdoc.rdoc_files.include('README.rdoc')
17
+ rdoc.rdoc_files.include('README.md')
18
18
  rdoc.rdoc_files.include('lib/**/*.rb')
19
19
  end
@@ -0,0 +1,32 @@
1
+ services:
2
+ solr:
3
+ image: solr:9
4
+ ports:
5
+ - "8983:8983"
6
+ volumes:
7
+ - ./spec/fixtures/basic_configs:/basic_configs_config/conf:ro
8
+ command: ["solr-precreate", "basic_configs", "/basic_configs_config"]
9
+ healthcheck:
10
+ test: ["CMD", "curl", "-sf", "http://localhost:8983/solr/basic_configs/admin/ping"]
11
+ interval: 2s
12
+ timeout: 5s
13
+ retries: 30
14
+
15
+ solr_auth:
16
+ image: solr:9
17
+ ports:
18
+ - "8984:8983"
19
+ volumes:
20
+ - ./spec/fixtures/basic_configs:/basic_configs_config/conf:ro
21
+ - ./spec/fixtures/security/security.json:/security-fixture/security.json:ro
22
+ entrypoint: ["bash", "-c"]
23
+ command:
24
+ - |
25
+ mkdir -p /var/solr/data &&
26
+ cp /security-fixture/security.json /var/solr/data/security.json &&
27
+ exec /opt/solr/docker/scripts/solr-precreate basic_configs /basic_configs_config
28
+ healthcheck:
29
+ test: ["CMD", "curl", "-sf", "-u", "rsolr:RSolrTest123", "http://localhost:8983/solr/basic_configs/admin/ping"]
30
+ interval: 2s
31
+ timeout: 5s
32
+ retries: 30
data/lib/rsolr/client.rb CHANGED
@@ -3,10 +3,24 @@
3
3
  require 'json'
4
4
  require 'faraday'
5
5
  require 'uri'
6
+ require 'base64'
6
7
 
7
8
  class RSolr::Client
9
+ include RSolr::Error::URICleanup
10
+
8
11
  DEFAULT_URL = 'http://127.0.0.1:8983/solr/'
9
12
 
13
+ # HTTP Basic Auth credentials, and how to render them as an Authorization header.
14
+ BasicAuth = Struct.new(:user, :password) do
15
+ def present?
16
+ !!(user && password)
17
+ end
18
+
19
+ def header_value
20
+ "Basic #{Base64.strict_encode64("#{user}:#{password}")}"
21
+ end
22
+ end
23
+
10
24
  class << self
11
25
  def default_wt
12
26
  @default_wt ||= :json
@@ -15,6 +29,14 @@ class RSolr::Client
15
29
  def default_wt= value
16
30
  @default_wt = value
17
31
  end
32
+
33
+ def default_http_method
34
+ @default_http_method ||= :get
35
+ end
36
+
37
+ def default_http_method= method
38
+ @default_http_method = method
39
+ end
18
40
  end
19
41
 
20
42
  attr_reader :uri, :proxy, :update_format, :options, :update_path
@@ -213,11 +235,11 @@ class RSolr::Client
213
235
 
214
236
  { status: response.status.to_i, headers: response.headers, body: response.body.force_encoding('utf-8') }
215
237
  rescue Faraday::TimeoutError => e
216
- raise RSolr::Error::Timeout.new(request_context, e.response)
238
+ raise RSolr::Error::Timeout.new(request_context, e.response), cause: redact_basic_auth(e)
217
239
  rescue Errno::ECONNREFUSED, defined?(Faraday::ConnectionFailed) ? Faraday::ConnectionFailed : Faraday::Error::ConnectionFailed
218
- raise RSolr::Error::ConnectionRefused, request_context.inspect
240
+ raise RSolr::Error::ConnectionRefused.new(request_context)
219
241
  rescue Faraday::Error => e
220
- raise RSolr::Error::Http.new(request_context, e.response)
242
+ raise RSolr::Error::Http.new(request_context, e.response), cause: redact_basic_auth(e)
221
243
  end
222
244
  adapt_response(request_context, raw_response) unless raw_response.nil?
223
245
  end
@@ -240,11 +262,17 @@ class RSolr::Client
240
262
  raise "path must be a string or symbol, not #{path.inspect}" unless [String,Symbol].include?(path.class)
241
263
  path = path.to_s
242
264
  opts[:proxy] = proxy unless proxy.nil?
243
- opts[:method] ||= :get
265
+ opts[:method] ||= default_http_method
244
266
  raise "The :data option can only be used if :method => :post" if opts[:method] != :post and opts[:data]
245
267
  opts[:params] = params_with_wt(opts[:params])
246
- query = RSolr::Uri.params_to_solr(opts[:params]) unless opts[:params].empty?
247
- opts[:query] = query
268
+ if opts[:method] == :post && (opts[:data].nil? || opts[:data].empty?)
269
+ # If no data hash is provided move query into data hash
270
+ # This is useful if the query string is larger than the max url length
271
+ opts[:data] = opts[:params]
272
+ else
273
+ query = RSolr::Uri.params_to_solr(opts[:params]) unless opts[:params].empty?
274
+ opts[:query] = query
275
+ end
248
276
  if opts[:data].is_a? Hash
249
277
  opts[:data] = RSolr::Uri.params_to_solr opts[:data]
250
278
  opts[:headers] ||= {}
@@ -314,28 +342,48 @@ class RSolr::Client
314
342
  conn_opts[:request][:params_encoder] = Faraday::FlatParamsEncoder
315
343
 
316
344
  Faraday.new(conn_opts) do |conn|
317
- if uri.user && uri.password
318
- case Faraday::VERSION
319
- when /^0/
320
- conn.basic_auth uri.user, uri.password
321
- when /^1/
322
- conn.request :basic_auth, uri.user, uri.password
323
- else
324
- conn.request :authorization, :basic_auth, uri.user, uri.password
325
- end
326
- end
345
+ conn.headers['Authorization'] = basic_auth.header_value if basic_auth.present?
327
346
 
328
347
  conn.response :raise_error
329
348
  conn.request :retry, max: options[:retry_after_limit], interval: 0.05,
330
349
  interval_randomness: 0.5, backoff_factor: 2,
331
350
  exceptions: ['Faraday::Error', 'Timeout::Error'] if options[:retry_503]
332
- conn.adapter options[:adapter] || Faraday.default_adapter || :net_http
351
+ conn.adapter(*Array(options[:adapter] || Faraday.default_adapter || :net_http))
333
352
  end
334
353
  end
335
354
  end
336
355
 
337
356
  protected
338
357
 
358
+ def basic_auth
359
+ if options[:basic_auth]
360
+ auth = options[:basic_auth]
361
+ BasicAuth.new(auth[:user] || auth['user'], auth[:password] || auth['password'])
362
+ else
363
+ BasicAuth.new(uri.user, uri.password)
364
+ end
365
+ end
366
+
367
+ # Faraday's own exception (kept as +cause+) embeds the request unredacted; rebuild it with just the credentials scrubbed.
368
+ def redact_basic_auth(error)
369
+ response = error.response
370
+ return error unless response.is_a?(Hash) && response[:request].is_a?(Hash)
371
+
372
+ request = response[:request].dup
373
+ request[:url] = clean_uri(request[:url]) if request[:url].respond_to?(:user)
374
+ request[:headers] = redact_authorization_header(request[:headers]) if request[:headers]
375
+
376
+ error.class.new(response.merge(request: request))
377
+ end
378
+
379
+ def redact_authorization_header(headers)
380
+ return headers unless headers['Authorization']
381
+
382
+ headers = headers.dup
383
+ headers['Authorization'] = 'REDACTED'
384
+ headers
385
+ end
386
+
339
387
  # converts the method name for the solr request handler path.
340
388
  def method_missing name, *args
341
389
  if name.to_s =~ /^paginated?_(.+)$/
@@ -369,4 +417,8 @@ class RSolr::Client
369
417
  def default_wt
370
418
  self.options[:default_wt] || self.class.default_wt
371
419
  end
420
+
421
+ def default_http_method
422
+ self.options[:default_http_method] || self.class.default_http_method
423
+ end
372
424
  end