rsolr 0.13.0.pre → 1.0.0.beta
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.
- data/README.rdoc +48 -29
- data/VERSION +1 -1
- data/lib/rsolr/char.rb +9 -0
- data/lib/rsolr/client.rb +80 -58
- data/lib/rsolr/error.rb +122 -0
- data/lib/rsolr/http.rb +106 -0
- data/lib/rsolr/uri.rb +55 -0
- data/lib/rsolr/xml.rb +161 -0
- data/lib/rsolr.rb +18 -39
- data/spec/api/rsolr_client_spec.rb +195 -0
- data/spec/api/rsolr_error_spec.rb +4 -0
- data/spec/api/rsolr_http_spec.rb +4 -0
- data/spec/api/rsolr_spec.rb +11 -23
- data/spec/api/rsolr_uri_spec.rb +70 -0
- data/spec/api/{message_spec.rb → rsolr_xml_spec.rb} +5 -4
- metadata +14 -18
- data/lib/rsolr/connection/httpable.rb +0 -101
- data/lib/rsolr/connection/net_http.rb +0 -30
- data/lib/rsolr/connection/utils.rb +0 -74
- data/lib/rsolr/connection.rb +0 -9
- data/lib/rsolr/message/document.rb +0 -48
- data/lib/rsolr/message/field.rb +0 -20
- data/lib/rsolr/message/generator.rb +0 -89
- data/lib/rsolr/message.rb +0 -8
- data/spec/api/client_spec.rb +0 -115
- data/spec/api/connection/httpable_spec.rb +0 -157
- data/spec/api/connection/net_http_spec.rb +0 -137
- data/spec/api/connection/utils_spec.rb +0 -84
- data/spec/integration/http_errors_spec.rb +0 -12
@@ -1,101 +0,0 @@
|
|
1
|
-
# A module that defines the interface and top-level logic for http based connection classes.
|
2
|
-
# Httpable provides URL parsing and handles proxy logic.
|
3
|
-
|
4
|
-
module RSolr::Connection::Httpable
|
5
|
-
|
6
|
-
include RSolr::Connection::Utils
|
7
|
-
|
8
|
-
attr_reader :opts, :uri, :proxy
|
9
|
-
|
10
|
-
# opts can have:
|
11
|
-
# :url => 'http://localhost:8080/solr'
|
12
|
-
def initialize opts={}
|
13
|
-
opts[:url] ||= 'http://127.0.0.1:8983/solr'
|
14
|
-
@opts = opts
|
15
|
-
@uri = URI.parse opts[:url]
|
16
|
-
@proxy = URI.parse opts[:proxy] if opts[:proxy]
|
17
|
-
end
|
18
|
-
|
19
|
-
# send a request to the connection
|
20
|
-
# request '/select', :q=>'*:*'
|
21
|
-
#
|
22
|
-
# request '/update', {:wt=>:xml}, '</commit>'
|
23
|
-
#
|
24
|
-
# force a post where the post body is the param query
|
25
|
-
# request '/update', "<optimize/>", :method=>:post
|
26
|
-
#
|
27
|
-
def request path, params={}, *extra
|
28
|
-
extra = extra.dup
|
29
|
-
opts = extra[-1].kind_of?(Hash) ? extra.pop : {}
|
30
|
-
data = extra[0]
|
31
|
-
|
32
|
-
context = create_http_context path, params, data, opts
|
33
|
-
|
34
|
-
error = nil
|
35
|
-
|
36
|
-
begin
|
37
|
-
|
38
|
-
# if data is being sent, this is a POST
|
39
|
-
if context[:data]
|
40
|
-
response = self.post context[:path], context[:data], context[:headers]
|
41
|
-
# use POST if :method => :post
|
42
|
-
elsif opts[:method] == :post
|
43
|
-
response = self.post context[:path], context[:query], context[:headers]
|
44
|
-
# GET
|
45
|
-
else
|
46
|
-
response = self.get context[:path]
|
47
|
-
end
|
48
|
-
|
49
|
-
# spray out our response into variables...
|
50
|
-
body, status_code, message = response
|
51
|
-
|
52
|
-
# merge the response into the http context
|
53
|
-
context.merge!(:body => body, :status_code => status_code, :message => message)
|
54
|
-
|
55
|
-
rescue
|
56
|
-
# throw RequestError?
|
57
|
-
context[:message] = $!.to_s
|
58
|
-
end
|
59
|
-
|
60
|
-
# if no :message but a non-200, throw a "SolrRequestError" ?
|
61
|
-
unless context[:status_code] == 200
|
62
|
-
error = context[:message] || "Non-200 Response Status Code"
|
63
|
-
raise RSolr::RequestError.new("#{error} -> #{context.inspect}")
|
64
|
-
end
|
65
|
-
|
66
|
-
context
|
67
|
-
end
|
68
|
-
|
69
|
-
# -> should this stuff be in a "ReqResContext" class? ->
|
70
|
-
|
71
|
-
# creates a Hash based "context"
|
72
|
-
# that contains all of the information sent to Solr
|
73
|
-
# The keys are:
|
74
|
-
# :host, :path, :params, :query, :data, :headers
|
75
|
-
def create_http_context path, params, data=nil, opts={}
|
76
|
-
context = {:host => base_url, :path => build_url(path), :params => params, :query => hash_to_query(params), :data => data}
|
77
|
-
if opts[:method] == :post
|
78
|
-
raise "Don't send POST data when using :method => :post" unless data.to_s.empty?
|
79
|
-
# force a POST, use the query string as the POST body
|
80
|
-
context.merge! :data => hash_to_query(params), :headers => {'Content-Type' => 'application/x-www-form-urlencoded'}
|
81
|
-
elsif data
|
82
|
-
# standard POST, using "data" as the POST body
|
83
|
-
context.merge! :headers => {'Content-Type' => 'text/xml; charset=utf-8'}
|
84
|
-
else
|
85
|
-
context.merge! :path => build_url(path, params)
|
86
|
-
end
|
87
|
-
context
|
88
|
-
end
|
89
|
-
|
90
|
-
# accepts a path/string and optional hash of query params
|
91
|
-
# returns a string that represents the full url
|
92
|
-
def build_url path, params={}
|
93
|
-
full_path = @uri.path + path
|
94
|
-
super full_path, params, @uri.query
|
95
|
-
end
|
96
|
-
|
97
|
-
def base_url
|
98
|
-
"#{@uri.scheme}://#{@uri.host}" + (@uri.port ? ":#{@uri.port}" : "")
|
99
|
-
end
|
100
|
-
|
101
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
require 'net/http'
|
2
|
-
|
3
|
-
#
|
4
|
-
# Connection for standard HTTP Solr server
|
5
|
-
#
|
6
|
-
class RSolr::Connection::NetHttp
|
7
|
-
|
8
|
-
include RSolr::Connection::Httpable
|
9
|
-
|
10
|
-
def connection
|
11
|
-
if @proxy
|
12
|
-
proxy_user, proxy_pass = @proxy.userinfo.split(/:/) if @proxy.userinfo
|
13
|
-
@connection ||= Net::HTTP.Proxy(@proxy.host, @proxy.port, proxy_user, proxy_pass).new(@uri.host, @uri.port)
|
14
|
-
else
|
15
|
-
@connection ||= Net::HTTP.new(@uri.host, @uri.port)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
# maybe follow Rack and do [status, headers, body]
|
20
|
-
def get url
|
21
|
-
net_http_response = self.connection.get url
|
22
|
-
[net_http_response.code.to_i, net_http_response.message, net_http_response.body]
|
23
|
-
end
|
24
|
-
|
25
|
-
def post url, data, headers={}
|
26
|
-
net_http_response = self.connection.post url, data, headers
|
27
|
-
[net_http_response.code.to_i, net_http_response.message, net_http_response.body]
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
@@ -1,74 +0,0 @@
|
|
1
|
-
# Helpful utility methods for building queries to a Solr server
|
2
|
-
# This includes helpers that the Direct connection can use -- not specific to http, for example
|
3
|
-
module RSolr::Connection::Utils
|
4
|
-
|
5
|
-
# Performs URI escaping so that you can construct proper
|
6
|
-
# query strings faster. Use this rather than the cgi.rb
|
7
|
-
# version since it's faster. (Stolen from Rack).
|
8
|
-
def escape(s)
|
9
|
-
s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/n) {
|
10
|
-
#'%'+$1.unpack('H2'*$1.size).join('%').upcase
|
11
|
-
'%'+$1.unpack('H2'*bytesize($1)).join('%').upcase
|
12
|
-
}.tr(' ', '+')
|
13
|
-
end
|
14
|
-
|
15
|
-
# encodes the string as utf-8 in Ruby 1.9
|
16
|
-
# returns the unaltered string in Ruby 1.8
|
17
|
-
def encode_utf8 string
|
18
|
-
(string.respond_to?(:force_encoding) and string.respond_to?(:encoding)) ?
|
19
|
-
string.force_encoding(Encoding::UTF_8) : string
|
20
|
-
end
|
21
|
-
|
22
|
-
# Return the bytesize of String; uses String#size under Ruby 1.8 and
|
23
|
-
# String#bytesize under 1.9.
|
24
|
-
if ''.respond_to?(:bytesize)
|
25
|
-
def bytesize(string)
|
26
|
-
string.bytesize
|
27
|
-
end
|
28
|
-
else
|
29
|
-
def bytesize(string)
|
30
|
-
string.size
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
# creates and returns a url as a string
|
35
|
-
# "url" is the base url
|
36
|
-
# "params" is an optional hash of GET style query params
|
37
|
-
# "string_query" is an extra query string that will be appended to the
|
38
|
-
# result of "url" and "params".
|
39
|
-
def build_url url='', params={}, string_query=''
|
40
|
-
queries = [string_query, hash_to_query(params)]
|
41
|
-
queries.delete_if{|i| i.to_s.empty?}
|
42
|
-
url += "?#{queries.join('&')}" unless queries.empty?
|
43
|
-
url
|
44
|
-
end
|
45
|
-
|
46
|
-
# converts a key value pair to an escaped string:
|
47
|
-
# Example:
|
48
|
-
# build_param(:id, 1) == "id=1"
|
49
|
-
def build_param(k,v)
|
50
|
-
"#{escape(k)}=#{escape(v)}"
|
51
|
-
end
|
52
|
-
|
53
|
-
#
|
54
|
-
# converts hash into URL query string, keys get an alpha sort
|
55
|
-
# if a value is an array, the array values get mapped to the same key:
|
56
|
-
# hash_to_query(:q=>'blah-query', :fq=>['f1', 'f1'], :facet=>true, 'facet.field'=>['location_facet', 'format_facet'])
|
57
|
-
# returns:
|
58
|
-
# ?q=blah-query&fq=f1&fq=f2&facet=true&facet.field=location_facet&facet.field=format.facet
|
59
|
-
#
|
60
|
-
# if a value is empty/nil etc., it is tossed out
|
61
|
-
#
|
62
|
-
def hash_to_query(params)
|
63
|
-
mapped = params.map do |k, v|
|
64
|
-
next if v.to_s.empty?
|
65
|
-
if v.class == Array
|
66
|
-
hash_to_query(v.map { |x| [k, x] })
|
67
|
-
else
|
68
|
-
build_param k, v
|
69
|
-
end
|
70
|
-
end
|
71
|
-
mapped.compact.join("&")
|
72
|
-
end
|
73
|
-
|
74
|
-
end
|
data/lib/rsolr/connection.rb
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
# A class that represents a "doc" xml element for a solr update
|
2
|
-
class RSolr::Message::Document
|
3
|
-
|
4
|
-
# "attrs" is a hash for setting the "doc" xml attributes
|
5
|
-
# "fields" is an array of Field objects
|
6
|
-
attr_accessor :attrs, :fields
|
7
|
-
|
8
|
-
# "doc_hash" must be a Hash/Mash object
|
9
|
-
# If a value in the "doc_hash" is an array,
|
10
|
-
# a field object is created for each value...
|
11
|
-
def initialize(doc_hash = {})
|
12
|
-
@fields = []
|
13
|
-
doc_hash.each_pair do |field,values|
|
14
|
-
# create a new field for each value (multi-valued)
|
15
|
-
# put non-array values into an array
|
16
|
-
values = [values] unless values.is_a?(Array)
|
17
|
-
values.each do |v|
|
18
|
-
next if v.to_s.empty?
|
19
|
-
@fields << RSolr::Message::Field.new({:name=>field}, v.to_s)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
@attrs={}
|
23
|
-
end
|
24
|
-
|
25
|
-
# returns an array of fields that match the "name" arg
|
26
|
-
def fields_by_name(name)
|
27
|
-
@fields.select{|f|f.name==name}
|
28
|
-
end
|
29
|
-
|
30
|
-
# returns the *first* field that matches the "name" arg
|
31
|
-
def field_by_name(name)
|
32
|
-
@fields.detect{|f|f.name==name}
|
33
|
-
end
|
34
|
-
|
35
|
-
#
|
36
|
-
# Add a field value to the document. Options map directly to
|
37
|
-
# XML attributes in the Solr <field> node.
|
38
|
-
# See http://wiki.apache.org/solr/UpdateXmlMessages#head-8315b8028923d028950ff750a57ee22cbf7977c6
|
39
|
-
#
|
40
|
-
# === Example:
|
41
|
-
#
|
42
|
-
# document.add_field('title', 'A Title', :boost => 2.0)
|
43
|
-
#
|
44
|
-
def add_field(name, value, options = {})
|
45
|
-
@fields << RSolr::Message::Field.new(options.merge({:name=>name}), value)
|
46
|
-
end
|
47
|
-
|
48
|
-
end
|
data/lib/rsolr/message/field.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
# A class that represents a "doc"/"field" xml element for a solr update
|
2
|
-
class RSolr::Message::Field
|
3
|
-
|
4
|
-
# "attrs" is a hash for setting the "doc" xml attributes
|
5
|
-
# "value" is the text value for the node
|
6
|
-
attr_accessor :attrs, :value
|
7
|
-
|
8
|
-
# "attrs" must be a hash
|
9
|
-
# "value" should be something that responds to #_to_s
|
10
|
-
def initialize(attrs, value)
|
11
|
-
@attrs = attrs
|
12
|
-
@value = value
|
13
|
-
end
|
14
|
-
|
15
|
-
# the value of the "name" attribute
|
16
|
-
def name
|
17
|
-
@attrs[:name]
|
18
|
-
end
|
19
|
-
|
20
|
-
end
|
@@ -1,89 +0,0 @@
|
|
1
|
-
class RSolr::Message::Generator
|
2
|
-
|
3
|
-
def build &block
|
4
|
-
require 'builder'
|
5
|
-
b = ::Builder::XmlMarkup.new(:indent=>0, :margin=>0, :encoding => 'UTF-8')
|
6
|
-
b.instruct!
|
7
|
-
block_given? ? yield(b) : b
|
8
|
-
end
|
9
|
-
|
10
|
-
# generates "add" xml for updating solr
|
11
|
-
# "data" can be a hash or an array of hashes.
|
12
|
-
# - each hash should be a simple key=>value pair representing a solr doc.
|
13
|
-
# If a value is an array, multiple fields will be created.
|
14
|
-
#
|
15
|
-
# "add_attrs" can be a hash for setting the add xml element attributes.
|
16
|
-
#
|
17
|
-
# This method can also accept a block.
|
18
|
-
# The value yielded to the block is a Message::Document; for each solr doc in "data".
|
19
|
-
# You can set xml element attributes for each "doc" element or individual "field" elements.
|
20
|
-
#
|
21
|
-
# For example:
|
22
|
-
#
|
23
|
-
# solr.add({:id=>1, :nickname=>'Tim'}, {:boost=>5.0, :commitWithin=>1.0}) do |doc_msg|
|
24
|
-
# doc_msg.attrs[:boost] = 10.00 # boost the document
|
25
|
-
# nickname = doc_msg.field_by_name(:nickname)
|
26
|
-
# nickname.attrs[:boost] = 20 if nickname.value=='Tim' # boost a field
|
27
|
-
# end
|
28
|
-
#
|
29
|
-
# would result in an add element having the attributes boost="10.0"
|
30
|
-
# and a commitWithin="1.0".
|
31
|
-
# Each doc element would have a boost="10.0".
|
32
|
-
# The "nickname" field would have a boost="20.0"
|
33
|
-
# if the doc had a "nickname" field with the value of "Tim".
|
34
|
-
#
|
35
|
-
def add data, add_attrs={}, &block
|
36
|
-
data = [data] unless data.is_a?(Array)
|
37
|
-
build do |xml|
|
38
|
-
xml.add(add_attrs) do |add_node|
|
39
|
-
data.each do |doc|
|
40
|
-
doc = RSolr::Message::Document.new(doc) if doc.respond_to?(:each_pair)
|
41
|
-
yield doc if block_given?
|
42
|
-
add_node.doc(doc.attrs) do |doc_node|
|
43
|
-
doc.fields.each do |field_obj|
|
44
|
-
doc_node.field field_obj.value, field_obj.attrs
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
# generates a <commit/> message
|
53
|
-
def commit(opts={})
|
54
|
-
build {|xml| xml.commit opts}
|
55
|
-
end
|
56
|
-
|
57
|
-
# generates a <optimize/> message
|
58
|
-
def optimize(opts={})
|
59
|
-
build {|xml| xml.optimize opts}
|
60
|
-
end
|
61
|
-
|
62
|
-
# generates a <rollback/> message
|
63
|
-
def rollback opts={}
|
64
|
-
build {|xml| xml.rollback opts}
|
65
|
-
end
|
66
|
-
|
67
|
-
# generates a <delete><id>ID</id></delete> message
|
68
|
-
# "ids" can be a single value or array of values
|
69
|
-
def delete_by_id(ids)
|
70
|
-
ids = [ids] unless ids.is_a?(Array)
|
71
|
-
build do |xml|
|
72
|
-
xml.delete do |delete_node|
|
73
|
-
ids.each { |id| delete_node.id(id) }
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
# generates a <delete><query>ID</query></delete> message
|
79
|
-
# "queries" can be a single value or an array of values
|
80
|
-
def delete_by_query(queries)
|
81
|
-
queries = [queries] unless queries.is_a?(Array)
|
82
|
-
build do |xml|
|
83
|
-
xml.delete do |delete_node|
|
84
|
-
queries.each { |query| delete_node.query query }
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
end
|
data/lib/rsolr/message.rb
DELETED
data/spec/api/client_spec.rb
DELETED
@@ -1,115 +0,0 @@
|
|
1
|
-
describe RSolr::Client do
|
2
|
-
|
3
|
-
let(:client){ RSolr::Client.new('') }
|
4
|
-
|
5
|
-
context :method_missing do
|
6
|
-
|
7
|
-
it 'a non-existent method should be forwarded to #method_missing and then to #request' do
|
8
|
-
client.should_receive(:request).
|
9
|
-
with('/music', :q=>'Coltrane')
|
10
|
-
client.music :q=>'Coltrane'
|
11
|
-
end
|
12
|
-
|
13
|
-
end
|
14
|
-
|
15
|
-
context :update do
|
16
|
-
|
17
|
-
it 'should forward /update to #request("/update")' do
|
18
|
-
client.should_receive(:request)#.
|
19
|
-
# with('/update', {:wt=>:ruby}, "my xml message")
|
20
|
-
client.update "my xml message"
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'should forward #add calls to #update' do
|
24
|
-
client.should_receive(:update) {|value,params|
|
25
|
-
value.should == "<?xml version=\"1.0\" encoding=\"UTF-8\"?><add><doc><field name=\"id\">1</field></doc></add>"
|
26
|
-
}
|
27
|
-
client.add(:id=>1)
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'should forward #commit calls to #update' do
|
31
|
-
client.should_receive(:update).
|
32
|
-
with("<?xml version=\"1.0\" encoding=\"UTF-8\"?><commit/>")
|
33
|
-
client.commit
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'should forward #commit calls with options to #update' do
|
37
|
-
opts = {:waitFlush => false, :waitSearcher => false, :expungeDeletes => true}
|
38
|
-
# when client.commit is called, it eventually calls update
|
39
|
-
client.should_receive(:update).
|
40
|
-
with(opts)
|
41
|
-
# client.message is calls to create the xml
|
42
|
-
client.message.should_receive(:commit).
|
43
|
-
and_return(opts)
|
44
|
-
client.commit(opts)
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'should forward #optimize calls to #update' do
|
48
|
-
client.should_receive(:update).
|
49
|
-
with("<?xml version=\"1.0\" encoding=\"UTF-8\"?><optimize/>")
|
50
|
-
client.optimize
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'should forward #optimize calls with options to #update' do
|
54
|
-
opts = {:maxSegments => 5, :waitFlush => false}
|
55
|
-
# when client.commit is called, it eventually calls update
|
56
|
-
client.should_receive(:update).
|
57
|
-
with(opts)
|
58
|
-
# client.message is calls to create the xml
|
59
|
-
client.message.should_receive(:optimize).
|
60
|
-
and_return(opts)
|
61
|
-
client.optimize(opts)
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'should forward #rollback calls to #update' do
|
65
|
-
client.should_receive(:update).
|
66
|
-
with("<?xml version=\"1.0\" encoding=\"UTF-8\"?><rollback/>")
|
67
|
-
client.rollback
|
68
|
-
end
|
69
|
-
|
70
|
-
it 'should forward #delete_by_id calls to #update' do
|
71
|
-
client.should_receive(:update).
|
72
|
-
with("<?xml version=\"1.0\" encoding=\"UTF-8\"?><delete><id>1</id></delete>")
|
73
|
-
client.delete_by_id 1
|
74
|
-
end
|
75
|
-
|
76
|
-
it 'should forward #delete_by_query calls to #update' do
|
77
|
-
client.should_receive(:update).
|
78
|
-
with("<?xml version=\"1.0\" encoding=\"UTF-8\"?><delete><query>blah</query></delete>")
|
79
|
-
client.delete_by_query 'blah'
|
80
|
-
end
|
81
|
-
|
82
|
-
end
|
83
|
-
|
84
|
-
context :request do
|
85
|
-
|
86
|
-
it 'should forward #request calls to the connection' do
|
87
|
-
client.connection.should_receive(:request).
|
88
|
-
with('/music', :q=>'Coltrane', :wt=>:ruby).
|
89
|
-
# empty params so that Client doesn't try to evalulate to Ruby;
|
90
|
-
# -- this happens if the :wt equal :ruby
|
91
|
-
and_return(:params=>{})
|
92
|
-
client.request '/music', :q=>'Coltrane'
|
93
|
-
end
|
94
|
-
|
95
|
-
end
|
96
|
-
|
97
|
-
context :adapt_response do
|
98
|
-
|
99
|
-
it 'should not try to evaluate ruby when the :qt is not :ruby' do
|
100
|
-
body = '{:time=>"NOW"}'
|
101
|
-
result = client.send(:adapt_response, {:body=>body, :params=>{}})
|
102
|
-
result.should be_a(String)
|
103
|
-
result.should == body
|
104
|
-
end
|
105
|
-
|
106
|
-
it 'should evaluate ruby responses when the :wt is :ruby' do
|
107
|
-
body = '{:time=>"NOW"}'
|
108
|
-
result = client.send(:adapt_response, {:body=>body, :params=>{:wt=>:ruby}})
|
109
|
-
result.should be_a(Hash)
|
110
|
-
result.should == {:time=>"NOW"}
|
111
|
-
end
|
112
|
-
|
113
|
-
end
|
114
|
-
|
115
|
-
end
|
@@ -1,157 +0,0 @@
|
|
1
|
-
describe RSolr::Connection::Httpable do
|
2
|
-
|
3
|
-
# calls #let to set "net_http" as method accessor
|
4
|
-
class R
|
5
|
-
include RSolr::Connection::Httpable
|
6
|
-
end
|
7
|
-
|
8
|
-
module HttpableHelper
|
9
|
-
def self.included base
|
10
|
-
base.let(:httpable){R.new}
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
context 'new' do
|
15
|
-
|
16
|
-
include HttpableHelper
|
17
|
-
|
18
|
-
it 'should define an intialize method that accepts a hash argument' do
|
19
|
-
lambda{R.new({})}.should_not raise_error
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'should have an #opts attribute after creation' do
|
23
|
-
httpable.should respond_to(:opts)
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'should have an #uri attribute after creation' do
|
27
|
-
httpable.should respond_to(:uri)
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
context 'opts and uri' do
|
33
|
-
|
34
|
-
it 'should allow setting the opts' do
|
35
|
-
opts = {:url=>'blah'}
|
36
|
-
r = R.new(opts)
|
37
|
-
r.opts.should == opts
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'should parser the url option into a URI object' do
|
41
|
-
opts = {:url => 'http://xyz:1010/solr'}
|
42
|
-
r = R.new(opts)
|
43
|
-
r.uri.should be_a(URI)
|
44
|
-
r.uri.host.should == 'xyz'
|
45
|
-
end
|
46
|
-
|
47
|
-
end
|
48
|
-
|
49
|
-
context :build_url do
|
50
|
-
|
51
|
-
include HttpableHelper
|
52
|
-
|
53
|
-
it 'should build a full path and create a query string' do
|
54
|
-
r = httpable
|
55
|
-
r.build_url("/select", :q=>1).should == '/solr/select?q=1'
|
56
|
-
end
|
57
|
-
|
58
|
-
it 'should build a full path without a query string' do
|
59
|
-
r = httpable
|
60
|
-
r.build_url("/select").should == '/solr/select'
|
61
|
-
end
|
62
|
-
|
63
|
-
end
|
64
|
-
|
65
|
-
context :create_http_context do
|
66
|
-
|
67
|
-
include HttpableHelper
|
68
|
-
|
69
|
-
it "should build a simple GET context" do
|
70
|
-
r = httpable
|
71
|
-
result = r.create_http_context('/select', :q=>'a', :fq=>'b')
|
72
|
-
expected = {:path=>"/solr/select?q=a&fq=b", :params=>{:q=>"a", :fq=>"b"}, :data=>nil, :query=>"q=a&fq=b", :host=>"http://127.0.0.1:8983"}
|
73
|
-
|
74
|
-
result.keys.all? {|v| expected.keys.include?(v) }
|
75
|
-
result.values.all? {|v| expected.values.include?(v) }
|
76
|
-
end
|
77
|
-
|
78
|
-
it "should build a POST context" do
|
79
|
-
r = httpable
|
80
|
-
result = r.create_http_context('/select', {:wt => :xml}, '<commit/>')
|
81
|
-
expected = {:path=>"/solr/select", :params=>{:wt=>:xml}, :headers=>{"Content-Type"=>"text/xml; charset=utf-8"}, :data=>"<commit/>", :query=>"wt=xml", :host=>"http://127.0.0.1:8983"}
|
82
|
-
result.should == expected
|
83
|
-
end
|
84
|
-
|
85
|
-
it "should raise an exception when trying to use POST data AND :method => :post" do
|
86
|
-
r = httpable
|
87
|
-
lambda{
|
88
|
-
r.create_http_context('/select', {:wt => :xml}, '<commit/>', :method => :post)
|
89
|
-
}.should raise_error("Don't send POST data when using :method => :post")
|
90
|
-
end
|
91
|
-
|
92
|
-
it "should form-encoded POST context" do
|
93
|
-
r = httpable
|
94
|
-
result = r.create_http_context('/select', {:q => 'some gigantic query string that is too big for GET (for example)'}, nil, :method => :post)
|
95
|
-
result.should == {:path=>"/solr/select", :params=>{:q=>"some gigantic query string that is too big for GET (for example)"}, :headers=>{"Content-Type"=>"application/x-www-form-urlencoded"}, :data=>"q=some+gigantic+query+string+that+is+too+big+for+GET+%28for+example%29", :query=>"q=some+gigantic+query+string+that+is+too+big+for+GET+%28for+example%29", :host=>"http://127.0.0.1:8983"}
|
96
|
-
end
|
97
|
-
|
98
|
-
end
|
99
|
-
|
100
|
-
context :request do
|
101
|
-
|
102
|
-
include HttpableHelper
|
103
|
-
|
104
|
-
it "should be able to build a request context, pass the url to #get and return a full context" do
|
105
|
-
httpable.should_receive(:create_http_context).
|
106
|
-
with("/admin/ping", {}, nil, {}).
|
107
|
-
and_return({:path => '/solr/admin/ping'})
|
108
|
-
httpable.should_receive(:get).
|
109
|
-
with('/solr/admin/ping').
|
110
|
-
and_return(["asdfasdf", 200, "OK"])
|
111
|
-
response = httpable.request '/admin/ping'
|
112
|
-
response.should == {:status_code=>200, :message=>"OK", :path=>"/solr/admin/ping", :body=>"asdfasdf"}
|
113
|
-
end
|
114
|
-
|
115
|
-
it 'should send a get to itself with params' do
|
116
|
-
httpable.should_receive(:get).
|
117
|
-
with("/solr/blahasdf?id=1").
|
118
|
-
and_return(["", 200, "OK"])
|
119
|
-
r = httpable.request('/blahasdf', :id=>1)
|
120
|
-
r.should == {:status_code=>200, :path=>"/solr/blahasdf?id=1", :params=>{:id=>1}, :message=>"OK", :data=>nil, :query=>"id=1", :host=>"http://127.0.0.1:8983", :body=>""}
|
121
|
-
end
|
122
|
-
|
123
|
-
it 'should raise an error if the status_code is not 200' do
|
124
|
-
httpable.should_receive(:get).
|
125
|
-
with("/solr/blah?id=1").
|
126
|
-
and_return( ["", 404, "Not Found"] )
|
127
|
-
lambda{
|
128
|
-
httpable.request('/blah', :id=>1).should == true
|
129
|
-
}.should raise_error(/Not Found/)
|
130
|
-
end
|
131
|
-
|
132
|
-
it 'should send a post to itself if data is supplied' do
|
133
|
-
httpable.should_receive(:post).
|
134
|
-
with("/solr/blah", "<commit/>", {"Content-Type"=>"text/xml; charset=utf-8"}).
|
135
|
-
and_return(["", 200, "OK"])
|
136
|
-
httpable.request('/blah', {:id=>1}, "<commit/>")#.should == expected_response
|
137
|
-
end
|
138
|
-
|
139
|
-
it 'should send a post to itself when :method=>:post is set even if no POST data is supplied' do
|
140
|
-
httpable.should_receive(:post).
|
141
|
-
with("/solr/blah", "q=testing", {"Content-Type"=>"application/x-www-form-urlencoded"}).
|
142
|
-
and_return(["", 200, "OK"])
|
143
|
-
response = httpable.request('/blah', {:q => "testing"}, :method => :post)#.should == expected_response
|
144
|
-
response[:body].should == ""
|
145
|
-
response[:path].should == "/solr/blah"
|
146
|
-
response[:message].should == "OK"
|
147
|
-
response[:status_code].should == 200
|
148
|
-
response[:params].should == {:q=>"testing"}
|
149
|
-
response[:headers].should == {"Content-Type"=>"application/x-www-form-urlencoded"}
|
150
|
-
response[:data].should == "q=testing"
|
151
|
-
response[:query].should == "q=testing"
|
152
|
-
response[:host].should == "http://127.0.0.1:8983"
|
153
|
-
end
|
154
|
-
|
155
|
-
end
|
156
|
-
|
157
|
-
end
|