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