solr4r 0.0.1
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 +7 -0
- data/COPYING +663 -0
- data/ChangeLog +7 -0
- data/README +40 -0
- data/Rakefile +23 -0
- data/TODO +3 -0
- data/lib/solr4r/builder.rb +291 -0
- data/lib/solr4r/client.rb +184 -0
- data/lib/solr4r/request.rb +122 -0
- data/lib/solr4r/response.rb +103 -0
- data/lib/solr4r/version.rb +27 -0
- data/lib/solr4r.rb +42 -0
- data/spec/solr4r/builder_spec.rb +210 -0
- data/spec/spec_helper.rb +3 -0
- metadata +106 -0
data/README
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
= solr4r - A Ruby client for Apache Solr
|
2
|
+
|
3
|
+
== VERSION
|
4
|
+
|
5
|
+
This documentation refers to solr4r version 0.0.1
|
6
|
+
|
7
|
+
|
8
|
+
== DESCRIPTION
|
9
|
+
|
10
|
+
TODO
|
11
|
+
|
12
|
+
|
13
|
+
== LINKS
|
14
|
+
|
15
|
+
Documentation:: http://blackwinter.github.com/solr4r
|
16
|
+
Source code:: http://github.com/blackwinter/solr4r
|
17
|
+
RubyGem:: http://rubygems.org/gems/solr4r
|
18
|
+
|
19
|
+
|
20
|
+
== AUTHORS
|
21
|
+
|
22
|
+
* Jens Wille <mailto:jens.wille@gmail.com>
|
23
|
+
|
24
|
+
|
25
|
+
== LICENSE AND COPYRIGHT
|
26
|
+
|
27
|
+
Copyright (C) 2014 Jens Wille
|
28
|
+
|
29
|
+
solr4r is free software: you can redistribute it and/or modify it
|
30
|
+
under the terms of the GNU Affero General Public License as published by
|
31
|
+
the Free Software Foundation, either version 3 of the License, or (at your
|
32
|
+
option) any later version.
|
33
|
+
|
34
|
+
solr4r is distributed in the hope that it will be useful, but
|
35
|
+
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
36
|
+
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
37
|
+
License for more details.
|
38
|
+
|
39
|
+
You should have received a copy of the GNU Affero General Public License
|
40
|
+
along with solr4r. If not, see <http://www.gnu.org/licenses/>.
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path(%q{../lib/solr4r/version}, __FILE__)
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'hen'
|
5
|
+
|
6
|
+
Hen.lay! {{
|
7
|
+
gem: {
|
8
|
+
name: %q{solr4r},
|
9
|
+
version: Solr4R::VERSION,
|
10
|
+
summary: %q{A Ruby client for Apache Solr},
|
11
|
+
description: %q{Access the Apache Solr search server from Ruby},
|
12
|
+
author: %q{Jens Wille},
|
13
|
+
email: %q{jens.wille@gmail.com},
|
14
|
+
license: %q{AGPL-3.0},
|
15
|
+
homepage: :blackwinter,
|
16
|
+
dependencies: { curb: ['~> 0.8', '> 0.8.5'], nokogiri: '~> 1.6' },
|
17
|
+
|
18
|
+
required_ruby_version: '>= 1.9.3'
|
19
|
+
}
|
20
|
+
}}
|
21
|
+
rescue LoadError => err
|
22
|
+
warn "Please install the `hen' gem. (#{err})"
|
23
|
+
end
|
data/TODO
ADDED
@@ -0,0 +1,291 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
#--
|
4
|
+
###############################################################################
|
5
|
+
# #
|
6
|
+
# solr4r -- A Ruby client for Apache Solr #
|
7
|
+
# #
|
8
|
+
# Copyright (C) 2014 Jens Wille #
|
9
|
+
# #
|
10
|
+
# Mir is free software: you can redistribute it and/or modify it under the #
|
11
|
+
# terms of the GNU Affero General Public License as published by the Free #
|
12
|
+
# Software Foundation, either version 3 of the License, or (at your option) #
|
13
|
+
# any later version. #
|
14
|
+
# #
|
15
|
+
# solr4r is distributed in the hope that it will be useful, but WITHOUT ANY #
|
16
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
|
17
|
+
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for #
|
18
|
+
# more details. #
|
19
|
+
# #
|
20
|
+
# You should have received a copy of the GNU Affero General Public License #
|
21
|
+
# along with solr4r. If not, see <http://www.gnu.org/licenses/>. #
|
22
|
+
# #
|
23
|
+
###############################################################################
|
24
|
+
#++
|
25
|
+
|
26
|
+
require 'nokogiri'
|
27
|
+
|
28
|
+
module Solr4R
|
29
|
+
|
30
|
+
Document = Nokogiri::XML::Document
|
31
|
+
|
32
|
+
class Builder < Nokogiri::XML::Builder
|
33
|
+
|
34
|
+
DEFAULT_OPTIONS = {
|
35
|
+
encoding: 'UTF-8'
|
36
|
+
}
|
37
|
+
|
38
|
+
def initialize(options = {})
|
39
|
+
if block_given?
|
40
|
+
raise ArgumentError,
|
41
|
+
'block argument not supported, use options hash instead'
|
42
|
+
end
|
43
|
+
|
44
|
+
super(@options = DEFAULT_OPTIONS.merge(options))
|
45
|
+
|
46
|
+
@_solr_doc = @doc
|
47
|
+
end
|
48
|
+
|
49
|
+
# See Schema[http://wiki.apache.org/solr/UpdateXmlMessages#add.2Freplace_documents].
|
50
|
+
#
|
51
|
+
# Examples:
|
52
|
+
#
|
53
|
+
# # single document
|
54
|
+
# add(employeeId: '05991', office: 'Bridgewater', skills: %w[Perl Java])
|
55
|
+
#
|
56
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
57
|
+
# <add>
|
58
|
+
# <doc>
|
59
|
+
# <field name="employeeId">05991</field>
|
60
|
+
# <field name="office">Bridgewater</field>
|
61
|
+
# <field name="skills">Perl</field>
|
62
|
+
# <field name="skills">Java</field>
|
63
|
+
# </doc>
|
64
|
+
# </add>
|
65
|
+
#
|
66
|
+
# # multiple documents
|
67
|
+
# add([{ employeeId: '05992', office: 'Blackwater' }, { employeeId: '05993', skills: 'Ruby' }])
|
68
|
+
#
|
69
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
70
|
+
# <add>
|
71
|
+
# <doc>
|
72
|
+
# <field name="employeeId">05992</field>
|
73
|
+
# <field name="office">Blackwater</field>
|
74
|
+
# </doc>
|
75
|
+
# <doc>
|
76
|
+
# <field name="employeeId">05993</field>
|
77
|
+
# <field name="skills">Ruby</field>
|
78
|
+
# </doc>
|
79
|
+
# </add>
|
80
|
+
#
|
81
|
+
# # add attributes
|
82
|
+
# add([id: 42, text: 'blah'], commitWithin: 23)
|
83
|
+
#
|
84
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
85
|
+
# <add commitWithin="23">
|
86
|
+
# <doc>
|
87
|
+
# <field name="id">42</field>
|
88
|
+
# <field name="text">blah</field>
|
89
|
+
# </doc>
|
90
|
+
# </add>
|
91
|
+
#
|
92
|
+
# # document attributes
|
93
|
+
# add([[{ id: 42, text: 'blah' }, { boost: 10.0 }]])
|
94
|
+
#
|
95
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
96
|
+
# <add>
|
97
|
+
# <doc boost="10.0">
|
98
|
+
# <field name="id">42</field>
|
99
|
+
# <field name="text">blah</field>
|
100
|
+
# </doc>
|
101
|
+
# </add>
|
102
|
+
#
|
103
|
+
# # field attributes
|
104
|
+
# add(id: 42, text: ['blah', boost: 2.0])
|
105
|
+
#
|
106
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
107
|
+
# <add>
|
108
|
+
# <doc>
|
109
|
+
# <field name="id">42</field>
|
110
|
+
# <field boost="2.0" name="text">blah</field>
|
111
|
+
# </doc>
|
112
|
+
# </add>
|
113
|
+
#
|
114
|
+
# # all attributes together
|
115
|
+
# add([[{ id: 42, text: ['blah', boost: 2.0] }, { boost: 10.0 }]], commitWithin: 23)
|
116
|
+
#
|
117
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
118
|
+
# <add commitWithin="23">
|
119
|
+
# <doc boost="10.0">
|
120
|
+
# <field name="id">42</field>
|
121
|
+
# <field boost="2.0" name="text">blah</field>
|
122
|
+
# </doc>
|
123
|
+
# </add>
|
124
|
+
def add(doc, attributes = {})
|
125
|
+
to_xml(:add, attributes) { |add_node|
|
126
|
+
doc = [doc] unless doc.is_a?(Array)
|
127
|
+
doc.each { |hash, doc_attributes|
|
128
|
+
doc_(doc_attributes) { |doc_node|
|
129
|
+
hash.each { |key, values|
|
130
|
+
values = values.is_a?(Array) ? values.dup : [values]
|
131
|
+
|
132
|
+
field_attributes = values.last.is_a?(Hash) ? values.pop : {}
|
133
|
+
field_attributes = field_attributes.merge(name: key)
|
134
|
+
|
135
|
+
values.each { |value| doc_node.field_(value, field_attributes) }
|
136
|
+
}
|
137
|
+
}
|
138
|
+
}
|
139
|
+
}
|
140
|
+
end
|
141
|
+
|
142
|
+
# See Schema[http://wiki.apache.org/solr/UpdateXmlMessages#A.22commit.22_and_.22optimize.22].
|
143
|
+
#
|
144
|
+
# Examples:
|
145
|
+
#
|
146
|
+
# commit
|
147
|
+
#
|
148
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
149
|
+
# <commit/>
|
150
|
+
#
|
151
|
+
# commit(softCommit: true)
|
152
|
+
#
|
153
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
154
|
+
# <commit softCommit="true"/>
|
155
|
+
def commit(attributes = {})
|
156
|
+
to_xml(:commit, attributes)
|
157
|
+
end
|
158
|
+
|
159
|
+
# See Schema[http://wiki.apache.org/solr/UpdateXmlMessages#A.22commit.22_and_.22optimize.22].
|
160
|
+
#
|
161
|
+
# Examples:
|
162
|
+
#
|
163
|
+
# optimize
|
164
|
+
#
|
165
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
166
|
+
# <optimize/>
|
167
|
+
#
|
168
|
+
# optimize(maxSegments: 42)
|
169
|
+
#
|
170
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
171
|
+
# <optimize maxSegments="42"/>
|
172
|
+
def optimize(attributes = {})
|
173
|
+
to_xml(:optimize, attributes)
|
174
|
+
end
|
175
|
+
|
176
|
+
# See Schema[http://wiki.apache.org/solr/UpdateXmlMessages#A.22rollback.22].
|
177
|
+
#
|
178
|
+
# Example:
|
179
|
+
#
|
180
|
+
# rollback
|
181
|
+
#
|
182
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
183
|
+
# <rollback/>
|
184
|
+
def rollback
|
185
|
+
to_xml(:rollback)
|
186
|
+
end
|
187
|
+
|
188
|
+
# See Schema[http://wiki.apache.org/solr/UpdateXmlMessages#A.22delete.22_documents_by_ID_and_by_Query].
|
189
|
+
#
|
190
|
+
# Examples:
|
191
|
+
#
|
192
|
+
# # single ID
|
193
|
+
# delete(id: '05991')
|
194
|
+
#
|
195
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
196
|
+
# <delete>
|
197
|
+
# <id>05991</id>
|
198
|
+
# </delete>
|
199
|
+
#
|
200
|
+
# # multiple IDs
|
201
|
+
# delete(id: %w[05991 06000])
|
202
|
+
#
|
203
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
204
|
+
# <delete>
|
205
|
+
# <id>05991</id>
|
206
|
+
# <id>06000</id>
|
207
|
+
# </delete>
|
208
|
+
#
|
209
|
+
# # single query
|
210
|
+
# delete(query: 'office:Bridgewater')
|
211
|
+
#
|
212
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
213
|
+
# <delete>
|
214
|
+
# <query>office:Bridgewater</query>
|
215
|
+
# </delete>
|
216
|
+
#
|
217
|
+
# # multiple queries
|
218
|
+
# delete(query: %w[office:Bridgewater office:Osaka])
|
219
|
+
#
|
220
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
221
|
+
# <delete>
|
222
|
+
# <query>office:Bridgewater</query>
|
223
|
+
# <query>office:Osaka</query>
|
224
|
+
# </delete>
|
225
|
+
#
|
226
|
+
# # query hash
|
227
|
+
# delete(query: { office: 'Bridgewater', skills: 'Perl' })
|
228
|
+
#
|
229
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
230
|
+
# <delete>
|
231
|
+
# <query>office:Bridgewater</query>
|
232
|
+
# <query>skills:Perl</query>
|
233
|
+
# </delete>
|
234
|
+
#
|
235
|
+
# # query hash with array
|
236
|
+
# delete(query: { office: %w[Bridgewater Osaka] })
|
237
|
+
#
|
238
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
239
|
+
# <delete>
|
240
|
+
# <query>office:Bridgewater</query>
|
241
|
+
# <query>office:Osaka</query>
|
242
|
+
# </delete>
|
243
|
+
#
|
244
|
+
# # both IDs and queries
|
245
|
+
# delete(id: %w[05991 06000], query: { office: %w[Bridgewater Osaka] })
|
246
|
+
#
|
247
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
248
|
+
# <delete>
|
249
|
+
# <id>05991</id>
|
250
|
+
# <id>06000</id>
|
251
|
+
# <query>office:Bridgewater</query>
|
252
|
+
# <query>office:Osaka</query>
|
253
|
+
# </delete>
|
254
|
+
def delete(hash)
|
255
|
+
to_xml(:delete) { |delete_node|
|
256
|
+
hash.each { |key, values|
|
257
|
+
values = [values] unless values.is_a?(Array)
|
258
|
+
values.each { |value|
|
259
|
+
ary = []
|
260
|
+
|
261
|
+
if value.is_a?(Hash)
|
262
|
+
value.each { |k, v| Array(v).each { |w| ary << "#{k}:#{w}" } }
|
263
|
+
else
|
264
|
+
ary << value
|
265
|
+
end
|
266
|
+
|
267
|
+
ary.each { |v| delete_node.method_missing(key, v) }
|
268
|
+
}
|
269
|
+
}
|
270
|
+
}
|
271
|
+
end
|
272
|
+
|
273
|
+
def inspect
|
274
|
+
'#<%s:0x%x @options=%p>' % [
|
275
|
+
self.class, object_id, @options
|
276
|
+
]
|
277
|
+
end
|
278
|
+
|
279
|
+
private
|
280
|
+
|
281
|
+
def to_xml(name, attributes = {}, &block)
|
282
|
+
self.parent = self.doc = @_solr_doc.dup
|
283
|
+
|
284
|
+
method_missing(name, attributes, &block)
|
285
|
+
|
286
|
+
super(&nil)
|
287
|
+
end
|
288
|
+
|
289
|
+
end
|
290
|
+
|
291
|
+
end
|
@@ -0,0 +1,184 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
#--
|
4
|
+
###############################################################################
|
5
|
+
# #
|
6
|
+
# solr4r -- A Ruby client for Apache Solr #
|
7
|
+
# #
|
8
|
+
# Copyright (C) 2014 Jens Wille #
|
9
|
+
# #
|
10
|
+
# Mir is free software: you can redistribute it and/or modify it under the #
|
11
|
+
# terms of the GNU Affero General Public License as published by the Free #
|
12
|
+
# Software Foundation, either version 3 of the License, or (at your option) #
|
13
|
+
# any later version. #
|
14
|
+
# #
|
15
|
+
# solr4r is distributed in the hope that it will be useful, but WITHOUT ANY #
|
16
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
|
17
|
+
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for #
|
18
|
+
# more details. #
|
19
|
+
# #
|
20
|
+
# You should have received a copy of the GNU Affero General Public License #
|
21
|
+
# along with solr4r. If not, see <http://www.gnu.org/licenses/>. #
|
22
|
+
# #
|
23
|
+
###############################################################################
|
24
|
+
#++
|
25
|
+
|
26
|
+
require 'uri'
|
27
|
+
|
28
|
+
module Solr4R
|
29
|
+
|
30
|
+
class Client
|
31
|
+
|
32
|
+
DEFAULT_HOST = 'localhost'
|
33
|
+
DEFAULT_PATH = 'solr/'
|
34
|
+
DEFAULT_PORT = 8983
|
35
|
+
|
36
|
+
DEFAULT_PARAMS = {
|
37
|
+
wt: :json
|
38
|
+
}
|
39
|
+
|
40
|
+
DEFAULT_ENDPOINTS = %w[select query spell suggest terms] <<
|
41
|
+
['ping', path: 'admin/ping', method: :head] <<
|
42
|
+
['dump', path: 'debug/dump']
|
43
|
+
|
44
|
+
DEFAULT_SELECT_PATH = 'select'
|
45
|
+
|
46
|
+
DEFAULT_UPDATE_PATH = 'update'
|
47
|
+
|
48
|
+
MATCH_ALL_QUERY = '*:*'
|
49
|
+
|
50
|
+
def initialize(options = {})
|
51
|
+
if options.is_a?(String)
|
52
|
+
url, options = options, {}
|
53
|
+
else
|
54
|
+
url = options.fetch(:url, default_url(options))
|
55
|
+
end
|
56
|
+
|
57
|
+
self.url, self.options = URI.parse(url), options
|
58
|
+
|
59
|
+
self.request = options.fetch(:request, Request.new)
|
60
|
+
self.builder = options.fetch(:builder, Builder.new)
|
61
|
+
|
62
|
+
self.default_params = options.fetch(:default_params, DEFAULT_PARAMS)
|
63
|
+
|
64
|
+
register_endpoints(options.fetch(:endpoints, DEFAULT_ENDPOINTS))
|
65
|
+
end
|
66
|
+
|
67
|
+
attr_accessor :url, :options, :request, :builder, :default_params
|
68
|
+
|
69
|
+
def register_endpoints(endpoints)
|
70
|
+
endpoints.each { |args| register_endpoint(*args) } if endpoints
|
71
|
+
self
|
72
|
+
end
|
73
|
+
|
74
|
+
def register_endpoint(path, options = {})
|
75
|
+
name, path = path, options.fetch(:path, path)
|
76
|
+
|
77
|
+
if error = invalid_endpoint?(name.to_s)
|
78
|
+
raise ArgumentError, "invalid endpoint: #{name} (#{error})"
|
79
|
+
else
|
80
|
+
define_singleton_method(name) { |_params = {}, _options = {}, &block|
|
81
|
+
send_request(path, options.merge(_options.merge(
|
82
|
+
params: options.fetch(:params, {}).merge(_params))), &block)
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
self
|
87
|
+
end
|
88
|
+
|
89
|
+
def get(path, params = {}, options = {}, &block)
|
90
|
+
send_request(path, options.merge(method: :get, params: params), &block)
|
91
|
+
end
|
92
|
+
|
93
|
+
def post(path, data = nil, options = {}, &block)
|
94
|
+
send_request(path, options.merge(method: :post, data: data), &block)
|
95
|
+
end
|
96
|
+
|
97
|
+
def head(path, params = {}, options = {}, &block)
|
98
|
+
send_request(path, options.merge(method: :head, params: params), &block)
|
99
|
+
end
|
100
|
+
|
101
|
+
def update(data, options = {}, path = DEFAULT_UPDATE_PATH, &block)
|
102
|
+
options = amend_options(options, :headers, 'Content-Type' => 'text/xml')
|
103
|
+
post(path, data, options, &block)
|
104
|
+
end
|
105
|
+
|
106
|
+
# See Builder#add.
|
107
|
+
def add(doc, attributes = {}, options = {}, &block)
|
108
|
+
update(builder.add(doc, attributes), options, &block)
|
109
|
+
end
|
110
|
+
|
111
|
+
# See Builder#commit.
|
112
|
+
def commit(attributes = {}, options = {}, &block)
|
113
|
+
update(builder.commit(attributes), options, &block)
|
114
|
+
end
|
115
|
+
|
116
|
+
# See Builder#optimize.
|
117
|
+
def optimize(attributes = {}, options = {}, &block)
|
118
|
+
update(builder.optimize(attributes), options, &block)
|
119
|
+
end
|
120
|
+
|
121
|
+
# See Builder#rollback.
|
122
|
+
def rollback(options = {}, &block)
|
123
|
+
update(builder.rollback, options, &block)
|
124
|
+
end
|
125
|
+
|
126
|
+
# See Builder#delete.
|
127
|
+
def delete(hash, options = {}, &block)
|
128
|
+
update(builder.delete(hash), options, &block)
|
129
|
+
end
|
130
|
+
|
131
|
+
# See #delete.
|
132
|
+
def delete_by_id(id, options = {}, &block)
|
133
|
+
delete({ id: id }, options, &block)
|
134
|
+
end
|
135
|
+
|
136
|
+
# See #delete.
|
137
|
+
def delete_by_query(query, options = {}, &block)
|
138
|
+
delete({ query: query }, options, &block)
|
139
|
+
end
|
140
|
+
|
141
|
+
# See #delete_by_query.
|
142
|
+
def delete_all!(options = {}, &block)
|
143
|
+
delete_by_query(MATCH_ALL_QUERY, options, &block)
|
144
|
+
end
|
145
|
+
|
146
|
+
def count(params = {}, options = {}, path = DEFAULT_SELECT_PATH, &block)
|
147
|
+
params = params.merge(rows: 0)
|
148
|
+
params[:q] ||= MATCH_ALL_QUERY
|
149
|
+
get(path, params, options, &block)
|
150
|
+
end
|
151
|
+
|
152
|
+
def inspect
|
153
|
+
'#<%s:0x%x @url=%p, @default_params=%p>' % [
|
154
|
+
self.class, object_id, url, default_params
|
155
|
+
]
|
156
|
+
end
|
157
|
+
|
158
|
+
private
|
159
|
+
|
160
|
+
def default_url(options)
|
161
|
+
'http://%s:%d/%s' % [
|
162
|
+
options.fetch(:host, DEFAULT_HOST),
|
163
|
+
options.fetch(:port, DEFAULT_PORT),
|
164
|
+
options.fetch(:path, DEFAULT_PATH)
|
165
|
+
]
|
166
|
+
end
|
167
|
+
|
168
|
+
def amend_options(options, key, value)
|
169
|
+
options.merge(key => value.merge(options.fetch(key, {})))
|
170
|
+
end
|
171
|
+
|
172
|
+
def send_request(path, options, &block)
|
173
|
+
options = amend_options(options, :params, default_params)
|
174
|
+
request.execute(URI.join(url, path), options, &block)
|
175
|
+
end
|
176
|
+
|
177
|
+
def invalid_endpoint?(name)
|
178
|
+
'method already defined' if respond_to?(name) || (
|
179
|
+
respond_to?(name, true) && !DEFAULT_ENDPOINTS.flatten.include?(name))
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
183
|
+
|
184
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
#--
|
4
|
+
###############################################################################
|
5
|
+
# #
|
6
|
+
# solr4r -- A Ruby client for Apache Solr #
|
7
|
+
# #
|
8
|
+
# Copyright (C) 2014 Jens Wille #
|
9
|
+
# #
|
10
|
+
# Mir is free software: you can redistribute it and/or modify it under the #
|
11
|
+
# terms of the GNU Affero General Public License as published by the Free #
|
12
|
+
# Software Foundation, either version 3 of the License, or (at your option) #
|
13
|
+
# any later version. #
|
14
|
+
# #
|
15
|
+
# solr4r is distributed in the hope that it will be useful, but WITHOUT ANY #
|
16
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
|
17
|
+
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for #
|
18
|
+
# more details. #
|
19
|
+
# #
|
20
|
+
# You should have received a copy of the GNU Affero General Public License #
|
21
|
+
# along with solr4r. If not, see <http://www.gnu.org/licenses/>. #
|
22
|
+
# #
|
23
|
+
###############################################################################
|
24
|
+
#++
|
25
|
+
|
26
|
+
require 'curl'
|
27
|
+
|
28
|
+
module Solr4R
|
29
|
+
|
30
|
+
class Request < Curl::Easy
|
31
|
+
|
32
|
+
DEFAULT_VERB = :get
|
33
|
+
|
34
|
+
DEFAULT_USER_AGENT = "Solr4R/#{VERSION}"
|
35
|
+
|
36
|
+
RESPONSE_ATTRIBUTES = {
|
37
|
+
# request
|
38
|
+
headers: :request_headers,
|
39
|
+
last_effective_url: :request_url,
|
40
|
+
post_body: :post_body,
|
41
|
+
params: :request_params,
|
42
|
+
verb: :request_verb,
|
43
|
+
|
44
|
+
# response
|
45
|
+
body_str: :response_body,
|
46
|
+
content_type: :content_type,
|
47
|
+
header_str: :response_header,
|
48
|
+
response_code: :response_code
|
49
|
+
}
|
50
|
+
|
51
|
+
def initialize(options = {})
|
52
|
+
if block_given?
|
53
|
+
raise ArgumentError,
|
54
|
+
'block argument not supported, use options hash instead'
|
55
|
+
end
|
56
|
+
|
57
|
+
super()
|
58
|
+
|
59
|
+
self.options = options.merge(params: nil, verb: nil)
|
60
|
+
set_options
|
61
|
+
end
|
62
|
+
|
63
|
+
attr_accessor :options, :params, :verb
|
64
|
+
|
65
|
+
def execute(request_url, options = {}, &block)
|
66
|
+
prepare_request(request_url, options, &block)
|
67
|
+
|
68
|
+
send("http_#{verb}")
|
69
|
+
|
70
|
+
Response.new { |response|
|
71
|
+
RESPONSE_ATTRIBUTES.each { |attribute, key|
|
72
|
+
response.send("#{key}=", send(attribute))
|
73
|
+
}
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
def reset
|
78
|
+
super.tap {
|
79
|
+
set_options
|
80
|
+
headers['User-Agent'] ||= DEFAULT_USER_AGENT
|
81
|
+
}
|
82
|
+
end
|
83
|
+
|
84
|
+
def inspect
|
85
|
+
'#<%s:0x%x @options=%p, @verb=%p, @url=%p, @response_code=%p>' % [
|
86
|
+
self.class, object_id, options, verb, url, response_code
|
87
|
+
]
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def set_options
|
93
|
+
options.each { |key, value| send("#{key}=", value) }
|
94
|
+
end
|
95
|
+
|
96
|
+
def prepare_request(request_url, options)
|
97
|
+
reset
|
98
|
+
|
99
|
+
self.url = Curl.urlalize(request_url.to_s,
|
100
|
+
self.params = options.fetch(:params, {}))
|
101
|
+
|
102
|
+
case self.verb = options.fetch(:method, DEFAULT_VERB)
|
103
|
+
when :get, :head
|
104
|
+
# ok
|
105
|
+
when :post, :delete, :patch
|
106
|
+
self.post_body = Curl.postalize(options[:data])
|
107
|
+
when :put
|
108
|
+
self.put_data = Curl.postalize(options[:data])
|
109
|
+
else
|
110
|
+
raise ArgumentError, "verb not supported: #{verb}"
|
111
|
+
end
|
112
|
+
|
113
|
+
headers.update(options[:headers]) if options[:headers]
|
114
|
+
|
115
|
+
yield self if block_given?
|
116
|
+
|
117
|
+
self
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|