rubycent 0.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.
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rubycent
4
+ # Rubycent::Error
5
+ #
6
+ # Wrapper for all rubycent errors(failures).
7
+ #
8
+ class Error < StandardError; end
9
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rubycent
4
+ # Rubycent::NetworkError
5
+ #
6
+ # Raised when request to Centrifugo API failed due the network problems.
7
+ #
8
+ class NetworkError < Error
9
+ attr_accessor :original_error
10
+ end
11
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rubycent
4
+ # Rubycent::RequestError
5
+ #
6
+ # Raised when request to Centrifugo API failed in some way.
7
+ #
8
+ class RequestError < Error
9
+ attr_reader :message, :status
10
+
11
+ def initialize(message, status)
12
+ @message = message
13
+ @status = status
14
+
15
+ super(message)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rubycent
4
+ # Rubycent::ResponseError
5
+ #
6
+ # Raised when response from Centrifugo contains any error as result of API command execution.
7
+ #
8
+ class ResponseError < Error
9
+ attr_reader :message, :code
10
+
11
+ def initialize(error_data)
12
+ @message, @code = error_data.values_at('message', 'code')
13
+
14
+ super(@message)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'uri'
4
+
5
+ require 'rubycent/request'
6
+
7
+ module Rubycent
8
+ # Rubycent::Query
9
+ #
10
+ # Centrifugo API request configuration and execution
11
+ #
12
+ class Query
13
+ attr_reader :client
14
+
15
+ # @param client [Rubycent::Client]
16
+ # Rubycent client that contains all the configuration
17
+ #
18
+ def initialize(client)
19
+ @client = client
20
+ end
21
+
22
+ # Perform centrifugo API call
23
+ #
24
+ # @param method [String]
25
+ # Centrifugo command, represents centrifugo actions such as 'publish', 'broadcast', e.t.c.
26
+ #
27
+ # @param data [Hash]
28
+ # Any data that will be sent as command parameters
29
+ #
30
+ # @return [Hash] Parser request responce
31
+ #
32
+ # @raise [Rubycent::Error, Rubycent::NetworkError, Rubycent::RequestError, Rubycent::ResponseError]
33
+ #
34
+ def execute(method, data)
35
+ body = dump_body(method, data)
36
+
37
+ params = {
38
+ timeout: client.timeout,
39
+ open_timeout: client.open_timeout
40
+ }
41
+
42
+ headers = build_headers(client.api_key)
43
+ endpoint = build_endpoint(client.host, client.port, client.scheme.to_s)
44
+
45
+ Rubycent::Request.new(endpoint, params, body, headers).post
46
+ end
47
+
48
+ private
49
+
50
+ def dump_body(method, params)
51
+ MultiJson.dump(method: method, params: params)
52
+ end
53
+
54
+ def build_endpoint(host, port, scheme)
55
+ ::URI::Generic.build(scheme: scheme, host: host, port: port, path: '/api').to_s
56
+ end
57
+
58
+ def build_headers(api_key)
59
+ {
60
+ 'Content-Type' => 'application/json',
61
+ 'Authorization' => "apikey #{api_key}"
62
+ }
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+
5
+ module Rubycent
6
+ # Rubycent::Request
7
+ #
8
+ # Holds request call and response handling logic
9
+ #
10
+ class Request
11
+ attr_accessor :endpoint, :params, :body, :headers
12
+
13
+ # @param endpoint [String] Centrifugo API endpoint
14
+ #
15
+ # @param params [Hash] Additional params to configure request.
16
+ #
17
+ # @option params [Integer] :timeout
18
+ # Number of seconds to wait for the connection to open.
19
+ #
20
+ # @option params [Integer] :open_timeout
21
+ # Number of seconds to wait for one block to be read.
22
+ #
23
+ # @param body [String]
24
+ # (default: nil) JSON string representing request parameters.
25
+ #
26
+ # @param headers [Hash]
27
+ # (default: {}) Additional HTTP headers(such as Content-Type and Authorization).
28
+ #
29
+ def initialize(endpoint, params, body = nil, headers = {})
30
+ @endpoint = endpoint
31
+ @params = params
32
+ @body = body
33
+ @headers = headers
34
+ end
35
+
36
+ # Perform POST request to centrifugo API
37
+ #
38
+ # @raise [Rubycent::Error, Rubycent::NetworkError, Rubycent::RequestError, Rubycent::ResponseError]
39
+ #
40
+ # @return [Hash] Parsed response body
41
+ #
42
+ def post
43
+ response = rest_client.post(@endpoint) do |request|
44
+ configure_request(request: request, body: body, headers: headers)
45
+ end
46
+
47
+ handle_response(response)
48
+ rescue Faraday::ConnectionFailed => e
49
+ handle_error(e)
50
+ end
51
+
52
+ private
53
+
54
+ def rest_client
55
+ Faraday.new do |faraday|
56
+ faraday.adapter(Rubycent.request_adapter)
57
+ faraday.headers = @headers
58
+ end
59
+ end
60
+
61
+ def configure_request(request: nil, headers: nil, body: nil)
62
+ return if request.nil?
63
+
64
+ request.headers.merge!(headers) if headers
65
+ request.body = body if body
66
+
67
+ request.options.timeout = @params[:timeout]
68
+ request.options.open_timeout = @params[:open_timeout]
69
+ end
70
+
71
+ def handle_response(response)
72
+ response.status == 200 ? parse_response(response) : raise_error(response)
73
+ end
74
+
75
+ def parse_response(response)
76
+ MultiJson.load(response.body).tap do |data|
77
+ raise ResponseError, data['error'] if data.key?('error')
78
+ end
79
+ end
80
+
81
+ def raise_error(response)
82
+ status_code = response.status
83
+ body = response.body
84
+
85
+ message = resolve_error_message(status_code, body)
86
+
87
+ case status_code
88
+ when 400..404
89
+ raise RequestError.new(message, status_code)
90
+ else
91
+ raise Error, message
92
+ end
93
+ end
94
+
95
+ def resolve_error_message(status, additional_info = nil)
96
+ error_messages = {
97
+ 400 => "Bad request: #{additional_info}",
98
+ 401 => 'Invalid API key',
99
+ 404 => 'Route not found'
100
+ }
101
+
102
+ error_messages.fetch(status) do
103
+ "Status: #{status}. Unknown error: #{additional_info}"
104
+ end
105
+ end
106
+
107
+ def handle_error(error)
108
+ message = "#{error.message} (#{error.class})"
109
+
110
+ wrapper = NetworkError.new(message).tap do |w|
111
+ w.original_error = error
112
+ end
113
+
114
+ raise wrapper
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rubycent
4
+ VERSION = '0.1.0'
5
+ end
data/rubycent.gemspec ADDED
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'rubycent/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'rubycent'
9
+ spec.version = Rubycent::VERSION
10
+ spec.authors = ['Warshavski']
11
+ spec.email = ['p.warshavski@gmail.com']
12
+
13
+ spec.summary = 'Ruby client to communicate with Centrifugo v2 HTTP API'
14
+ spec.description = 'Ruby client to communicate with Centrifugo v2 HTTP API'
15
+ spec.homepage = 'https://github.com/Warshavski/rubycent'
16
+ spec.license = 'MIT'
17
+
18
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
19
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
20
+ if spec.respond_to?(:metadata)
21
+ spec.metadata['homepage_uri'] = spec.homepage
22
+ spec.metadata['source_code_uri'] = 'https://github.com/Warshavski/rubycent'
23
+ else
24
+ raise 'RubyGems 2.0 or newer is required to protect against ' \
25
+ 'public gem pushes.'
26
+ end
27
+
28
+ # Specify which files should be added to the gem when it is released.
29
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
30
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
31
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
32
+ end
33
+ spec.bindir = 'exe'
34
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
35
+ spec.require_paths = ['lib']
36
+
37
+ spec.add_dependency 'faraday', '~> 0.16.1'
38
+ spec.add_dependency 'jwt', '~> 2.2.1'
39
+ spec.add_dependency 'multi_json', '~> 1.13.1'
40
+
41
+ spec.add_development_dependency 'bundler'
42
+ spec.add_development_dependency 'rake', '~> 10.0'
43
+ spec.add_development_dependency 'rspec', '~> 3.0'
44
+ spec.add_development_dependency 'webmock', '~> 3.7.5'
45
+ end
metadata ADDED
@@ -0,0 +1,163 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rubycent
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Warshavski
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-09-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.16.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.16.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: jwt
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 2.2.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 2.2.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: multi_json
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 1.13.1
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 1.13.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: webmock
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 3.7.5
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 3.7.5
111
+ description: Ruby client to communicate with Centrifugo v2 HTTP API
112
+ email:
113
+ - p.warshavski@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - ".rspec"
120
+ - ".travis.yml"
121
+ - Gemfile
122
+ - LICENSE.txt
123
+ - README.md
124
+ - Rakefile
125
+ - bin/console
126
+ - bin/setup
127
+ - lib/rubycent.rb
128
+ - lib/rubycent/client.rb
129
+ - lib/rubycent/error.rb
130
+ - lib/rubycent/errors/network_error.rb
131
+ - lib/rubycent/errors/request_error.rb
132
+ - lib/rubycent/errors/response_error.rb
133
+ - lib/rubycent/query.rb
134
+ - lib/rubycent/request.rb
135
+ - lib/rubycent/version.rb
136
+ - rubycent.gemspec
137
+ homepage: https://github.com/Warshavski/rubycent
138
+ licenses:
139
+ - MIT
140
+ metadata:
141
+ homepage_uri: https://github.com/Warshavski/rubycent
142
+ source_code_uri: https://github.com/Warshavski/rubycent
143
+ post_install_message:
144
+ rdoc_options: []
145
+ require_paths:
146
+ - lib
147
+ required_ruby_version: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ required_rubygems_version: !ruby/object:Gem::Requirement
153
+ requirements:
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ version: '0'
157
+ requirements: []
158
+ rubyforge_project:
159
+ rubygems_version: 2.7.6
160
+ signing_key:
161
+ specification_version: 4
162
+ summary: Ruby client to communicate with Centrifugo v2 HTTP API
163
+ test_files: []