flying-sphinx 1.2.1 → 1.3.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.
@@ -0,0 +1,20 @@
1
+ class FlyingSphinx::Request::HMAC < Faraday::Middleware
2
+ def initialize(app, identifier, api_key, service)
3
+ super app
4
+
5
+ @identifier = identifier
6
+ @api_key = api_key
7
+ @service = service
8
+ end
9
+
10
+ def call(environment)
11
+ Ey::Hmac.sign! environment, identifier, api_key,
12
+ :adapter => Ey::Hmac::Adapter::Faraday, :service => service
13
+
14
+ app.call environment
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :app, :identifier, :api_key, :service
20
+ end
@@ -1,5 +1,7 @@
1
1
  class FlyingSphinx::Response::JSON < Faraday::Response::Middleware
2
2
  def on_complete(environment)
3
+ return if environment[:request_headers]['Authorization'].nil?
4
+
3
5
  environment[:body] = MultiJson.load environment[:body]
4
6
  end
5
7
  end
@@ -10,7 +10,7 @@ class FlyingSphinx::SettingFiles
10
10
  hash = {}
11
11
 
12
12
  each_file_for_setting do |setting, file|
13
- hash["#{setting}:#{File.basename(file)}"] = File.read(file)
13
+ hash["#{setting}/#{File.basename(file)}"] = File.read(file)
14
14
  end
15
15
 
16
16
  hash['extra'] = hash.keys.join(';')
@@ -1,3 +1,3 @@
1
1
  module FlyingSphinx
2
- Version = '1.2.1'
2
+ Version = '1.3.0'
3
3
  end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+ require 'cgi'
3
+
4
+ describe 'Configuring Sphinx' do
5
+ let(:cli) { FlyingSphinx::CLI.new 'configure' }
6
+ let(:translator) { double 'Translator', :sphinx_indices => [index],
7
+ :sphinx_configuration => 'searchd { }' }
8
+ let(:index) { double 'Index' }
9
+
10
+ before :each do
11
+ allow(FlyingSphinx).to receive(:translator).and_return(translator)
12
+
13
+ stub_hmac_request(:post, 'https://flying-sphinx.com/api/my/v5/perform').
14
+ to_return(:body => '{"id":953, "status":"OK"}')
15
+ stub_hmac_request(:get, "https://flying-sphinx.com/api/my/v5/presignature").
16
+ to_return(
17
+ :body => '{"url":"https://foo","path":"bar","fields":{},"status":"OK"}'
18
+ )
19
+ stub_request(:post, "https://foo/").to_return(:status => 200)
20
+ end
21
+
22
+ it 'sends the configuration to the server' do
23
+ SuccessfulAction.new(953).matches? lambda { cli.run }
24
+
25
+ expect(
26
+ a_hmac_request(:post, 'https://flying-sphinx.com/api/my/v5/perform').
27
+ with { |request| CGI::parse(request.body)["action"] == ["configure"] }
28
+ ).to have_been_made
29
+ end
30
+
31
+ it 'handles the full request successfully' do
32
+ expect { cli.run }.to be_successful_with 953
33
+ end
34
+ end
@@ -4,10 +4,11 @@ describe 'Requesting customer information' do
4
4
  let(:configuration) { FlyingSphinx::Configuration.new 'foo', 'bar' }
5
5
 
6
6
  before :each do
7
- stub_request(:get, 'https://flying-sphinx.com/api/my/app').to_return(
8
- :status => 200,
9
- :body => '{"server":"my.sphinx.server","port":9307}'
10
- )
7
+ stub_hmac_request(:get, 'https://flying-sphinx.com/api/my/v5/app').
8
+ to_return(
9
+ :status => 200,
10
+ :body => '{"server":"my.sphinx.server","port":9307}'
11
+ )
11
12
  end
12
13
 
13
14
  it { expect(configuration.host).to eq('my.sphinx.server') }
@@ -4,12 +4,17 @@ describe 'Starting Sphinx' do
4
4
  let(:cli) { FlyingSphinx::CLI.new 'start' }
5
5
 
6
6
  before :each do
7
- stub_request(:post, 'https://flying-sphinx.com/api/my/app/start').
7
+ stub_hmac_request(:post, 'https://flying-sphinx.com/api/my/v5/perform').
8
8
  to_return(:status => 200, :body => '{"id":429, "status":"OK"}')
9
9
  end
10
10
 
11
11
  it 'makes the request to the server', :retry => 3 do
12
12
  expect { cli.run }.to be_successful_with 429
13
+
14
+ expect(
15
+ a_hmac_request(:post, 'https://flying-sphinx.com/api/my/v5/perform').
16
+ with(:body => {:action => 'start'})
17
+ ).to have_been_made
13
18
  end
14
19
  end
15
20
 
@@ -17,11 +22,16 @@ describe 'Stopping Sphinx', :retry => 3 do
17
22
  let(:cli) { FlyingSphinx::CLI.new 'stop' }
18
23
 
19
24
  before :each do
20
- stub_request(:post, 'https://flying-sphinx.com/api/my/app/stop').
25
+ stub_request(:post, 'https://flying-sphinx.com/api/my/v5/perform').
21
26
  to_return(:status => 200, :body => '{"id":537, "status":"OK"}')
22
27
  end
23
28
 
24
29
  it 'makes the request to the server', :retry => 3 do
25
30
  expect { cli.run }.to be_successful_with 537
31
+
32
+ expect(
33
+ a_hmac_request(:post, 'https://flying-sphinx.com/api/my/v5/perform').
34
+ with(:body => {:action => 'stop'})
35
+ ).to have_been_made
26
36
  end
27
37
  end
@@ -6,7 +6,7 @@ describe FlyingSphinx::Action do
6
6
  let(:socket) { double 'socket', :connect => true, :disconnect => true,
7
7
  :subscribe => true, :[] => channel, :connected => true }
8
8
  let(:channel) { double 'channel', :bind => true }
9
- let(:response) { double :body => {'status' => 'OK', 'id' => 748} }
9
+ let(:response) { {'status' => 'OK', 'id' => 748} }
10
10
  let(:logger) { double 'logger', :debug => true }
11
11
 
12
12
  before :each do
@@ -18,8 +18,6 @@ describe FlyingSphinx::API do
18
18
  it "sets up a connection with the appropriate headers" do
19
19
  faraday.should_receive(:new) do |options|
20
20
  options[:headers].should == {
21
- 'Accept' => 'application/vnd.flying-sphinx-v4+json',
22
- 'X-Flying-Sphinx-Token' => 'foo:bar',
23
21
  'X-Flying-Sphinx-Version' => FlyingSphinx::Version
24
22
  }
25
23
 
@@ -52,7 +50,7 @@ describe FlyingSphinx::API do
52
50
 
53
51
  it "sends the GET request with the given path and data" do
54
52
  request.should_receive(:url).
55
- with('/api/my/app/resource', 'param' => 'value')
53
+ with('/api/my/v5/resource', 'param' => 'value')
56
54
 
57
55
  send_request
58
56
  end
@@ -69,25 +67,7 @@ describe FlyingSphinx::API do
69
67
 
70
68
  it "sends the POST request with the given path and data" do
71
69
  connection.should_receive(:post).
72
- with('/api/my/app/resource', 'param' => 'value').
73
- and_return(response)
74
-
75
- send_request
76
- end
77
- end
78
-
79
- describe '#put' do
80
- let(:send_request) { api.put '/resource', 'param' => 'value' }
81
-
82
- before :each do
83
- connection.stub(:put => response)
84
- end
85
-
86
- it_should_behave_like 'an API call'
87
-
88
- it "sends the PUT request with the given path and data" do
89
- connection.should_receive(:put).
90
- with('/api/my/app/resource', 'param' => 'value').
70
+ with('/api/my/v5/resource', 'param' => 'value').
91
71
  and_return(response)
92
72
 
93
73
  send_request
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe FlyingSphinx::Configuration do
4
- let(:api) { double 'FlyingSphinx::API', :get => double(:body => body) }
4
+ let(:api) { double 'FlyingSphinx::API', :get => body }
5
5
  let(:body) { {'server' => 'foo.bar.com', 'port' => 9319} }
6
6
  let(:api_key) { 'foo-bar-baz' }
7
7
  let(:identifier) { 'my-identifier' }
@@ -2,11 +2,12 @@ require 'spec_helper'
2
2
 
3
3
  describe FlyingSphinx::Controller do
4
4
  let(:controller) { FlyingSphinx::Controller.new api }
5
- let(:api) { double 'API', :identifier => 'foo', :put => true }
5
+ let(:api) { double 'API', :identifier => 'foo', :put => true,
6
+ :get => {"path" => "/foo", "url" => "https://confserver", "status" => "OK"} }
6
7
  let(:action_class) { double }
7
8
  let(:configuration) { double 'TS Configuration' }
8
- let(:setting_files) { double :to_hash => {'extra' => 'wordforms:txt.txt',
9
- 'wordforms:txt.txt' => 'something'} }
9
+ let(:setting_files) { double :to_hash => {'extra' => 'wordforms/txt.txt',
10
+ 'wordforms/txt.txt' => 'something'} }
10
11
  let(:translator) { double :sphinx_configuration => 'indexer ...' }
11
12
 
12
13
  before :each do
@@ -20,38 +21,51 @@ describe FlyingSphinx::Controller do
20
21
 
21
22
  stub_const 'FlyingSphinx::SettingFiles', double(:new => setting_files)
22
23
  FlyingSphinx.stub :translator => translator
23
- end
24
24
 
25
- def ungzip(contents)
26
- io = StringIO.new contents, 'rb'
27
- reader = Zlib::GzipReader.new io
28
- reader.read
25
+ stub_request(:post, "https://confserver").to_return(:status => 200)
29
26
  end
30
27
 
31
28
  describe 'configure' do
32
29
  it 'sends data to the server' do
33
- api.should_receive(:put)
30
+ api.should_receive(:post)
34
31
 
35
32
  controller.configure
36
33
  end
37
34
 
38
- it 'sends through gzipped configuration files' do
39
- api.should_receive(:put) do |path, options|
40
- path.should == 'configure'
41
- options[:configuration]['gzip'].should == 'true'
42
- ungzip(options[:configuration]['sphinx'].read).should == 'indexer ...'
43
- ungzip(options[:configuration]['wordforms:txt.txt'].read).should == 'something'
44
- end
35
+ it 'sends through gzipped configuration archive' do
36
+ expect(api).to receive(:post).with '/perform',
37
+ :action => 'configure',
38
+ :path => '/foo'
45
39
 
46
40
  controller.configure
41
+
42
+ expect(
43
+ a_multipart_request(:post, 'https://confserver').
44
+ with_file { |contents|
45
+ reader = GZippedTar::Reader.new contents
46
+
47
+ reader.read("sphinx/raw.conf") == "indexer ..." &&
48
+ reader.read("sphinx/version.txt") == "2.2.3" &&
49
+ reader.read("wordforms/txt.txt") == "something"
50
+ }
51
+ ).to have_been_made
47
52
  end
48
53
 
49
54
  it 'sends through file if provided' do
50
- api.should_receive(:put).with 'configure',
51
- :configuration => {'sphinx' => 'searchd ...'},
52
- :sphinx_version => '2.0.6'
55
+ expect(api).to receive(:post).with '/perform',
56
+ :action => 'configure',
57
+ :path => '/foo'
53
58
 
54
59
  controller.configure 'searchd ...'
60
+
61
+ expect(
62
+ a_multipart_request(:post, 'https://confserver').
63
+ with_file { |contents|
64
+ reader = GZippedTar::Reader.new contents
65
+
66
+ reader.read("sphinx/raw.conf") == "searchd ..."
67
+ }
68
+ ).to have_been_made
55
69
  end
56
70
  end
57
71
  end
@@ -18,12 +18,12 @@ describe FlyingSphinx::SettingFiles do
18
18
  end
19
19
 
20
20
  [:stopwords, :wordforms, :exceptions].each do |setting|
21
- it "uploads #{setting} files from indices" do
21
+ it "collects #{setting} files from indices" do
22
22
  indices << index_double(setting => '/my/file/foo.txt')
23
23
 
24
24
  files.to_hash.should == {
25
- "#{setting}:foo.txt" => 'blah',
26
- 'extra' => "#{setting}:foo.txt"
25
+ "#{setting}/foo.txt" => 'blah',
26
+ 'extra' => "#{setting}/foo.txt"
27
27
  }
28
28
  end
29
29
 
@@ -32,8 +32,8 @@ describe FlyingSphinx::SettingFiles do
32
32
  indices << index_double(setting => '/my/file/foo.txt')
33
33
 
34
34
  files.to_hash.should == {
35
- "#{setting}:foo.txt" => 'blah',
36
- 'extra' => "#{setting}:foo.txt"
35
+ "#{setting}/foo.txt" => 'blah',
36
+ 'extra' => "#{setting}/foo.txt"
37
37
  }
38
38
  end
39
39
 
@@ -41,22 +41,22 @@ describe FlyingSphinx::SettingFiles do
41
41
  indices << index_double(
42
42
  setting => '/my/file/foo.txt /my/file/bar.txt')
43
43
 
44
- files.to_hash["#{setting}:foo.txt"].should == 'blah'
45
- files.to_hash["#{setting}:bar.txt"].should == 'blah'
44
+ files.to_hash["#{setting}/foo.txt"].should == 'blah'
45
+ files.to_hash["#{setting}/bar.txt"].should == 'blah'
46
46
  files.to_hash['extra'].split(';').should =~ [
47
- "#{setting}:foo.txt", "#{setting}:bar.txt"
47
+ "#{setting}/foo.txt", "#{setting}/bar.txt"
48
48
  ]
49
49
  end
50
50
  end
51
51
 
52
52
  [:mysql_ssl_cert, :mysql_ssl_key, :mysql_ssl_ca].each do |setting|
53
- it "uploads #{setting} files from indices" do
53
+ it "collects #{setting} files from sources" do
54
54
  indices << index_double(:sources => [
55
55
  source_double(setting => '/my/file/foo.txt')])
56
56
 
57
57
  files.to_hash.should == {
58
- "#{setting}:foo.txt" => 'blah',
59
- 'extra' => "#{setting}:foo.txt"
58
+ "#{setting}/foo.txt" => 'blah',
59
+ 'extra' => "#{setting}/foo.txt"
60
60
  }
61
61
  end
62
62
 
@@ -67,8 +67,8 @@ describe FlyingSphinx::SettingFiles do
67
67
  source_double(setting => '/my/file/foo.txt')])
68
68
 
69
69
  files.to_hash.should == {
70
- "#{setting}:foo.txt" => 'blah',
71
- 'extra' => "#{setting}:foo.txt"
70
+ "#{setting}/foo.txt" => 'blah',
71
+ 'extra' => "#{setting}/foo.txt"
72
72
  }
73
73
  end
74
74
 
@@ -76,10 +76,10 @@ describe FlyingSphinx::SettingFiles do
76
76
  indices << index_double(:sources => [
77
77
  source_double(setting => '/my/file/foo.txt /my/file/bar.txt')])
78
78
 
79
- files.to_hash["#{setting}:foo.txt"].should == 'blah'
80
- files.to_hash["#{setting}:bar.txt"].should == 'blah'
79
+ files.to_hash["#{setting}/foo.txt"].should == 'blah'
80
+ files.to_hash["#{setting}/bar.txt"].should == 'blah'
81
81
  files.to_hash['extra'].split(';').should =~ [
82
- "#{setting}:foo.txt", "#{setting}:bar.txt"
82
+ "#{setting}/foo.txt", "#{setting}/bar.txt"
83
83
  ]
84
84
  end
85
85
  end
@@ -4,6 +4,7 @@ require 'bundler'
4
4
  require 'dotenv'
5
5
  require 'webmock/rspec'
6
6
  require 'em-websocket'
7
+ require 'rack'
7
8
 
8
9
  Dotenv.load '.env.test'
9
10
  WebMock.disable_net_connect!
@@ -0,0 +1,23 @@
1
+ class HMACRequestPattern < WebMock::RequestPattern
2
+ def matches?(request_signature)
3
+ request_signature.headers['Authorization'].present? && super
4
+ end
5
+ end
6
+
7
+ module HMACHelpers
8
+ def stub_hmac_request(method, uri)
9
+ stub_request(method, uri).with { |request|
10
+ request.headers['Authorization'].present?
11
+ }
12
+ end
13
+
14
+ def a_hmac_request(method, uri)
15
+ HMACRequestPattern.new method, uri
16
+ end
17
+
18
+ private
19
+ end
20
+
21
+ RSpec.configure do |config|
22
+ config.include HMACHelpers
23
+ end
@@ -0,0 +1,56 @@
1
+ module MultipartHelpers
2
+ def a_multipart_request(method, uri)
3
+ MultipartRequestPattern.new method, uri
4
+ end
5
+ end
6
+
7
+ class MultipartRequestPattern < WebMock::RequestPattern
8
+ def with_file(&block)
9
+ with { |request| block.call MultipartRequestToFile.call(request) }
10
+ end
11
+ end
12
+
13
+ class MultipartRequestToFile
14
+ def self.call(request)
15
+ new(request).call
16
+ end
17
+
18
+ def initialize(request)
19
+ @request = request
20
+ end
21
+
22
+ def call
23
+ parsed["file"][:tempfile].read
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :request
29
+
30
+ def parsed
31
+ if Rack::Multipart.respond_to? :extract_multipart
32
+ Rack::Multipart.extract_multipart rack_request
33
+ else
34
+ Rack::Multipart.parse_multipart rack_env
35
+ end
36
+ end
37
+
38
+ def rack_env
39
+ transformed_headers.merge 'rack.input' => StringIO.new(request.body)
40
+ end
41
+
42
+ def rack_request
43
+ Rack::Request.new rack_env
44
+ end
45
+
46
+ def transformed_headers
47
+ request.headers.keys.inject({}) do |hash, key|
48
+ hash[key.underscore.upcase] = request.headers[key]
49
+ hash
50
+ end
51
+ end
52
+ end
53
+
54
+ RSpec.configure do |config|
55
+ config.include MultipartHelpers
56
+ end