search_flip 3.0.0 → 3.1.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 +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +37 -2
- data/lib/search_flip/aws_sigv4_plugin.rb +47 -0
- data/lib/search_flip/http_client.rb +8 -10
- data/lib/search_flip/version.rb +1 -1
- data/search_flip.gemspec +1 -0
- data/spec/search_flip/aws_sigv4_plugin_spec.rb +41 -0
- data/spec/search_flip/http_client_spec.rb +17 -0
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f4e3ca349bd68555b2826d84c17b192335752947babe02ee51c5501cb04f79ca
|
4
|
+
data.tar.gz: e95021068918513669da2730d613157ad7151995c4a25f532f4274c3a848710f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dcb46f99778d2243e6fb4187f85eb9a1db9aedc25a5f2b8287c3cdb8dcd259253bc3430e1e36521ea5794a2a9188f91473ae8d8572edc8c775ac0d234ac2e284
|
7
|
+
data.tar.gz: 1dbb3ba32c9c2a16f1c2b30aba7257dffc39b708f3e68ec8552c6d6d8ac6a751027a2899a3865051f7d1fdd7a6acd7a1f456eba552c7b50f4c2956292f41d413
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
|
2
2
|
# CHANGELOG
|
3
3
|
|
4
|
+
## v3.1.0
|
5
|
+
|
6
|
+
* Added plugin support in `SearchFlip::HTTPClient`
|
7
|
+
* Added `SearchFlip::AwsSigv4Plugin` to be able to use AWS Elasticsearch with
|
8
|
+
signed requests
|
9
|
+
|
4
10
|
## v3.0.0
|
5
11
|
|
6
12
|
* Added `Criteria#to_query`, which returns a raw query including all queries
|
data/README.md
CHANGED
@@ -475,8 +475,8 @@ end
|
|
475
475
|
```
|
476
476
|
|
477
477
|
Generally, aggregation results returned by Elasticsearch are returned as a
|
478
|
-
`SearchFlip::Result`, which basically is `Hashie::Mash
|
479
|
-
them via:
|
478
|
+
`SearchFlip::Result`, which basically is a `Hashie::Mash`, such that you can
|
479
|
+
access them via:
|
480
480
|
|
481
481
|
```ruby
|
482
482
|
query.aggregations(:username)["mrkamel"].revenue.value
|
@@ -769,6 +769,41 @@ http_client = http_client.headers(key: "value")
|
|
769
769
|
SearchFlip::Connection.new(base_url: "...", http_client: http_client)
|
770
770
|
```
|
771
771
|
|
772
|
+
## AWS Elasticsearch / Signed Requests
|
773
|
+
|
774
|
+
To use SearchFlip with AWS Elasticsearch and signed requests, you have to add
|
775
|
+
`aws-sdk-core` to your Gemfile and tell SearchFlip to use the
|
776
|
+
`SearchFlip::AwsSigv4Plugin`:
|
777
|
+
|
778
|
+
```ruby
|
779
|
+
require "search_flip/aws_sigv4_plugin"
|
780
|
+
|
781
|
+
MyConnection = SearchFlip::Connection.new(
|
782
|
+
base_url: "https://your-elasticsearch-cluster.es.amazonaws.com",
|
783
|
+
http_client: SearchFlip::HTTPClient.new(
|
784
|
+
plugins: [
|
785
|
+
SearchFlip::AwsSigv4Plugin.new(
|
786
|
+
region: "...",
|
787
|
+
access_key_id: "...",
|
788
|
+
secret_access_key: "..."
|
789
|
+
)
|
790
|
+
]
|
791
|
+
)
|
792
|
+
)
|
793
|
+
```
|
794
|
+
|
795
|
+
Again, in your index you need to specify this connection:
|
796
|
+
|
797
|
+
```ruby
|
798
|
+
class MyIndex
|
799
|
+
include SearchFlip::Index
|
800
|
+
|
801
|
+
def self.connection
|
802
|
+
MyConnection
|
803
|
+
end
|
804
|
+
end
|
805
|
+
```
|
806
|
+
|
772
807
|
## Routing and other index-time options
|
773
808
|
|
774
809
|
Override `index_options` in case you want to use routing or pass other
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require "aws-sdk-core"
|
2
|
+
require "uri"
|
3
|
+
|
4
|
+
module SearchFlip
|
5
|
+
# The SearchFlip::AwsSigV4Plugin is a plugin for the SearchFlip::HTTPClient
|
6
|
+
# to be used with AWS Elasticsearch to sign requests, i.e. add signed
|
7
|
+
# headers, before sending the request to Elasticsearch.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# MyConnection = SearchFlip::Connection.new(
|
11
|
+
# base_url: "https://your-elasticsearch-cluster.es.amazonaws.com",
|
12
|
+
# http_client: SearchFlip::HTTPClient.new(
|
13
|
+
# plugins: [
|
14
|
+
# SearchFlip::AwsSigv4Plugin.new(
|
15
|
+
# region: "...",
|
16
|
+
# access_key_id: "...",
|
17
|
+
# secret_access_key: "..."
|
18
|
+
# )
|
19
|
+
# ]
|
20
|
+
# )
|
21
|
+
# )
|
22
|
+
|
23
|
+
class AwsSigv4Plugin
|
24
|
+
attr_accessor :signer
|
25
|
+
|
26
|
+
def initialize(options = {})
|
27
|
+
self.signer = Aws::Sigv4::Signer.new({ service: "es" }.merge(options))
|
28
|
+
end
|
29
|
+
|
30
|
+
def call(request, method, uri, options = {})
|
31
|
+
full_uri = URI.parse(uri)
|
32
|
+
full_uri.query = URI.encode_www_form(options[:params]) if options[:params]
|
33
|
+
|
34
|
+
signature_request = {
|
35
|
+
http_method: method.to_s.upcase,
|
36
|
+
url: full_uri.to_s
|
37
|
+
}
|
38
|
+
|
39
|
+
signature_request[:body] = options[:body] if options.key?(:body)
|
40
|
+
signature_request[:body] = options[:json].respond_to?(:to_str) ? options[:json] : JSON.generate(options[:json]) if options[:json]
|
41
|
+
|
42
|
+
signature = signer.sign_request(signature_request)
|
43
|
+
|
44
|
+
request.headers(signature.headers)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -1,15 +1,14 @@
|
|
1
1
|
module SearchFlip
|
2
|
-
# @api private
|
3
|
-
#
|
4
2
|
# The SearchFlip::HTTPClient class wraps the http gem, is for internal use
|
5
3
|
# and responsible for the http request/response handling, ie communicating
|
6
4
|
# with Elasticsearch.
|
7
5
|
|
8
6
|
class HTTPClient
|
9
|
-
attr_accessor :request
|
7
|
+
attr_accessor :request, :plugins
|
10
8
|
|
11
|
-
def initialize
|
9
|
+
def initialize(plugins: [])
|
12
10
|
self.request = HTTP
|
11
|
+
self.plugins = plugins
|
13
12
|
end
|
14
13
|
|
15
14
|
class << self
|
@@ -30,17 +29,16 @@ module SearchFlip
|
|
30
29
|
end
|
31
30
|
|
32
31
|
[:get, :post, :put, :delete, :head].each do |method|
|
33
|
-
define_method(method) do
|
34
|
-
execute(method,
|
32
|
+
define_method(method) do |uri, options = {}|
|
33
|
+
execute(method, uri, options)
|
35
34
|
end
|
36
|
-
|
37
|
-
ruby2_keywords method
|
38
35
|
end
|
39
36
|
|
40
37
|
private
|
41
38
|
|
42
|
-
|
43
|
-
|
39
|
+
def execute(method, uri, options = {})
|
40
|
+
final_request = plugins.inject(self) { |res, cur| cur.call(res, method, uri, options) }
|
41
|
+
response = final_request.request.send(method, uri, options)
|
44
42
|
|
45
43
|
raise SearchFlip::ResponseError.new(code: response.code, body: response.body.to_s) unless response.status.success?
|
46
44
|
|
data/lib/search_flip/version.rb
CHANGED
data/search_flip.gemspec
CHANGED
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
|
|
25
25
|
MESSAGE
|
26
26
|
|
27
27
|
spec.add_development_dependency "activerecord", ">= 3.0"
|
28
|
+
spec.add_development_dependency "aws-sdk-core"
|
28
29
|
spec.add_development_dependency "bundler"
|
29
30
|
spec.add_development_dependency "factory_bot"
|
30
31
|
spec.add_development_dependency "rake"
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.expand_path("../spec_helper", __dir__)
|
2
|
+
require "search_flip/aws_sigv4_plugin"
|
3
|
+
|
4
|
+
RSpec.describe SearchFlip::AwsSigv4Plugin do
|
5
|
+
describe "#call" do
|
6
|
+
subject(:plugin) do
|
7
|
+
SearchFlip::AwsSigv4Plugin.new(
|
8
|
+
region: "us-east-1",
|
9
|
+
access_key_id: "access key",
|
10
|
+
secret_access_key: "secret access key"
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:client) { SearchFlip::HTTPClient.new }
|
15
|
+
|
16
|
+
it "adds the signed headers to the request" do
|
17
|
+
Timecop.freeze Time.parse("2020-01-01 12:00:00 UTC") do
|
18
|
+
expect(client).to receive(:headers).with(
|
19
|
+
"host" => "localhost",
|
20
|
+
"authorization" => /.*/,
|
21
|
+
"x-amz-content-sha256" => /.*/,
|
22
|
+
"x-amz-date" => /20200101T120000Z/
|
23
|
+
)
|
24
|
+
|
25
|
+
plugin.call(client, :get, "http://localhost/index")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it "feeds the http method, full url and body to the signer" do
|
30
|
+
signing_request = {
|
31
|
+
http_method: "GET",
|
32
|
+
url: "http://localhost/index?param=value",
|
33
|
+
body: JSON.generate(key: "value")
|
34
|
+
}
|
35
|
+
|
36
|
+
expect(plugin.signer).to receive(:sign_request).with(signing_request).and_call_original
|
37
|
+
|
38
|
+
plugin.call(client, :get, "http://localhost/index", params: { param: "value" }, json: { key: "value" })
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -39,6 +39,23 @@ RSpec.describe SearchFlip::HTTPClient do
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
+
describe "plugins" do
|
43
|
+
subject do
|
44
|
+
SearchFlip::HTTPClient.new(
|
45
|
+
plugins: [
|
46
|
+
->(request, _method, _uri, _options = {}) { request.headers("First-Header" => "Value") },
|
47
|
+
->(request, _method, _uri, _options = {}) { request.headers("Second-Header" => "Value") }
|
48
|
+
]
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "injects the plugins and uses their result in the request" do
|
53
|
+
stub_request(:get, "http://localhost/path").with(query: { key: "value" }, headers: { "First-Header" => "Value", "Second-Header" => "Value" }).and_return(body: "success")
|
54
|
+
|
55
|
+
expect(subject.get("http://localhost/path", params: { key: "value" }).body.to_s).to eq("success")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
42
59
|
[:via, :basic_auth, :auth].each do |method|
|
43
60
|
describe "##{method}" do
|
44
61
|
it "creates a dupped instance" do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: search_flip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Benjamin Vetter
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-06-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '3.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: aws-sdk-core
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: bundler
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -212,6 +226,7 @@ files:
|
|
212
226
|
- lib/search_flip.rb
|
213
227
|
- lib/search_flip/aggregatable.rb
|
214
228
|
- lib/search_flip/aggregation.rb
|
229
|
+
- lib/search_flip/aws_sigv4_plugin.rb
|
215
230
|
- lib/search_flip/bulk.rb
|
216
231
|
- lib/search_flip/config.rb
|
217
232
|
- lib/search_flip/connection.rb
|
@@ -238,6 +253,7 @@ files:
|
|
238
253
|
- search_flip.gemspec
|
239
254
|
- spec/delegate_matcher.rb
|
240
255
|
- spec/search_flip/aggregation_spec.rb
|
256
|
+
- spec/search_flip/aws_sigv4_plugin_spec.rb
|
241
257
|
- spec/search_flip/bulk_spec.rb
|
242
258
|
- spec/search_flip/connection_spec.rb
|
243
259
|
- spec/search_flip/criteria_spec.rb
|
@@ -278,6 +294,7 @@ summary: Full-Featured Elasticsearch Ruby Client with a Chainable DSL
|
|
278
294
|
test_files:
|
279
295
|
- spec/delegate_matcher.rb
|
280
296
|
- spec/search_flip/aggregation_spec.rb
|
297
|
+
- spec/search_flip/aws_sigv4_plugin_spec.rb
|
281
298
|
- spec/search_flip/bulk_spec.rb
|
282
299
|
- spec/search_flip/connection_spec.rb
|
283
300
|
- spec/search_flip/criteria_spec.rb
|