rubycent 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []