herdst_servicecall 0.1.5

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: edcb93afbd7eb625014ac88fa8fbdcbfe5ecca6ccf91c3a3355c8b4b46893977
4
+ data.tar.gz: 1225417249d81bf83ae5091e8d157c972bf41649db094b2338326788e4bec664
5
+ SHA512:
6
+ metadata.gz: 678cde9436e7f4e0b56ef6b7d6728161268144caef2fb0048850cd4d340c8d13172f1d0024f91f9ac670d21e430573e83eb4593720da40e76dfd756c2bc4a51e
7
+ data.tar.gz: f3d4513df4c007aa1b292f6746f8c523aacba28a1ceb46e753e634b2b9f56cf2237b2c3616d80794908ff66f3ee340f556feaa9982c421cdcf42491d7076f5b2
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2020 Matthew Mills
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # Servicecall
2
+ Short description and motivation.
3
+
4
+ ## Usage
5
+ How to use my plugin.
6
+
7
+ ## Installation
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'servicecall'
12
+ ```
13
+
14
+ And then execute:
15
+ ```bash
16
+ $ bundle
17
+ ```
18
+
19
+ Or install it yourself as:
20
+ ```bash
21
+ $ gem install servicecall
22
+ ```
23
+
24
+ ## Install config
25
+ ```rails generate servicecall:install```
26
+
27
+ ## Contributing
28
+ Contribution directions go here.
29
+
30
+ ## License
31
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,29 @@
1
+ ENV["TZ"] = "UTC"
2
+
3
+ begin
4
+ require 'bundler/setup'
5
+ rescue LoadError
6
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
7
+ end
8
+
9
+ require 'rdoc/task'
10
+
11
+ RDoc::Task.new(:rdoc) do |rdoc|
12
+ rdoc.rdoc_dir = 'rdoc'
13
+ rdoc.title = 'HerdstServicecall'
14
+ rdoc.options << '--line-numbers'
15
+ rdoc.rdoc_files.include('README.md')
16
+ rdoc.rdoc_files.include('lib/**/*.rb')
17
+ end
18
+
19
+ require 'bundler/gem_tasks'
20
+
21
+ require 'rake/testtask'
22
+
23
+ Rake::TestTask.new(:test) do |t|
24
+ t.libs << 'test'
25
+ t.pattern = 'test/**/*_test.rb'
26
+ t.verbose = false
27
+ end
28
+
29
+ task default: :test
@@ -0,0 +1,12 @@
1
+ require 'rails/generators/base'
2
+
3
+
4
+ module HerdstServicecall
5
+ class InstallGenerator < Rails::Generators::Base
6
+ source_root File.expand_path("../../templates", __FILE__)
7
+
8
+ def create_initializer_file
9
+ template "herdst_servicecall.rb", "config/initializers/herdst_servicecall.rb"
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ # Configures service call
2
+ HerdstServicecall.setup do |config|
3
+
4
+ config.jwt_secret "secret"
5
+
6
+ config.register_service :service_one, "http://localhost:3000"
7
+ config.register_service :service_two, "http://localhost:3001"
8
+ config.register_service :service_three, "http://localhost:3002"
9
+
10
+ config.on("user_created", "user#created")
11
+
12
+ end
@@ -0,0 +1,44 @@
1
+ require 'jwt'
2
+ require 'json'
3
+
4
+ require "herdst_servicecall/railtie"
5
+ require "herdst_servicecall/configurator"
6
+ require "herdst_servicecall/caller"
7
+ require "herdst_servicecall/receiver"
8
+ require "herdst_servicecall/middleware"
9
+ require "herdst_servicecall/request"
10
+ require "herdst_servicecall/response"
11
+ require "herdst_servicecall/responder"
12
+ require "herdst_servicecall/responder_error"
13
+ require "herdst_servicecall/mocker" if (ENV["RAILS_ENV"] == "test") || (ENV["WORKER_ENV"] == "test")
14
+
15
+
16
+ module HerdstServicecall
17
+
18
+
19
+ @@config = Configurator.new
20
+ @@caller = Caller.new(@@config)
21
+ @@receiver = Receiver.new(@@config)
22
+
23
+
24
+ def self.config
25
+ @@config
26
+ end
27
+
28
+
29
+ def self.receive(token, data)
30
+ @@receiver.receive(token, data)
31
+ end
32
+
33
+
34
+ def self.call(service_name, event_name, data)
35
+ @@caller.call(service_name, event_name, data)
36
+ end
37
+
38
+
39
+ def self.setup(&block)
40
+ yield @@config if block_given?
41
+ end
42
+
43
+
44
+ end
@@ -0,0 +1,58 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+
4
+
5
+ module HerdstServicecall
6
+ class Caller
7
+
8
+
9
+ attr_accessor :config, :responder
10
+
11
+
12
+ def initialize(config)
13
+ self.config = config
14
+ end
15
+
16
+
17
+ def call(service_name, event_name, data)
18
+ service_endpoint = @config.get_service(service_name.to_sym)
19
+
20
+ raise "No service endpoint!" unless service_endpoint
21
+
22
+ call_endpoint = service_endpoint + @config.event_path + "?" + { :token => get_token }.to_query
23
+
24
+ response = send_request!(call_endpoint, Request.new(event_name, data))
25
+
26
+ Response.parse(response)
27
+ end
28
+
29
+
30
+ private
31
+ def send_request!(endpoint, service_request)
32
+ uri = URI.parse(endpoint)
33
+ http = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == "https")
34
+ request = Net::HTTP::Post.new(uri.to_s)
35
+
36
+ request.content_type = "application/json"
37
+ request.body = service_request.to_json
38
+
39
+ make_request!(http, request)
40
+ end
41
+
42
+ def get_token
43
+ payload = {
44
+ :iat => (Time.now.utc.to_i - 1),
45
+ :nbf => (Time.now.utc.to_i - 10),
46
+ :exp => (Time.now.utc.to_i + 300)
47
+ }
48
+
49
+ JWT.encode(payload, self.config.jwt_secret, self.config.jwt_algorithm)
50
+ end
51
+
52
+ def make_request!(http, request)
53
+ http.request(request)
54
+ end
55
+
56
+
57
+ end
58
+ end
@@ -0,0 +1,40 @@
1
+ module HerdstServicecall
2
+ class Configurator
3
+
4
+
5
+ def initialize
6
+ @config = Hash.new.with_indifferent_access
7
+ @config[:services] = Hash.new
8
+ @config[:events] = Hash.new
9
+ @config[:event_path] = "/servicecall/event"
10
+ @config[:jwt_secret] = nil
11
+ @config[:jwt_algorithm] = "HS256"
12
+ end
13
+
14
+
15
+ def register_service(name, endpoint)
16
+ @config[:services][name.to_sym] = endpoint
17
+ end
18
+
19
+
20
+ def get_service(name)
21
+ @config[:services][name.to_sym]
22
+ end
23
+
24
+
25
+ def on(event_name, action)
26
+ @config[:events][event_name.to_sym] = action
27
+ end
28
+
29
+
30
+ def method_missing(method, *args)
31
+ if (args.size == 1)
32
+ @config[method.to_sym] = args.first
33
+ else
34
+ @config[method.to_sym]
35
+ end
36
+ end
37
+
38
+
39
+ end
40
+ end
@@ -0,0 +1,43 @@
1
+ module HerdstServicecall
2
+ class Middleware
3
+
4
+
5
+ def initialize(app)
6
+ @app = app
7
+ @event_path = HerdstServicecall.config.event_path
8
+ end
9
+
10
+
11
+ def call(env)
12
+ if env["REQUEST_METHOD"] == "POST"
13
+ req = nil
14
+
15
+ unless env["REQUEST_PATH"]
16
+ req = Rack::Request.new(env)
17
+
18
+ env["REQUEST_PATH"] = req.path
19
+ end
20
+
21
+ if env["REQUEST_PATH"] == @event_path
22
+ req = Rack::Request.new(env) unless req
23
+ body = req.body.read
24
+ token = Rack::Utils.parse_nested_query(req.query_string)["token"] rescue nil
25
+
26
+ if body
27
+ response = HerdstServicecall.receive(token, body)
28
+
29
+ return [
30
+ response.code,
31
+ { "Content-Type" => "application/json" },
32
+ [ response.to_json ]
33
+ ]
34
+ end
35
+ end
36
+ end
37
+
38
+ return @app.call(env)
39
+ end
40
+
41
+
42
+ end
43
+ end
@@ -0,0 +1,44 @@
1
+ require "minitest/mock"
2
+
3
+
4
+ module HerdstServicecall
5
+ class Mocker
6
+
7
+
8
+ def self.mock_call(event, body, code = 200, &block)
9
+ stub_call(:call, event, body, code) do
10
+ yield if block_given?
11
+ end
12
+ end
13
+
14
+
15
+ private
16
+ def self.stub_call(method, event, body, code = 200)
17
+ calls = []
18
+
19
+ Caller.class_eval do
20
+ alias_method :"new_#{method}", method
21
+
22
+ define_method(method) do |*args|
23
+ calls << args
24
+
25
+ Response.new(event, code, body)
26
+ end
27
+ end
28
+
29
+ begin
30
+ yield if block_given?
31
+ ensure
32
+ Caller.class_eval do
33
+ undef_method method
34
+ alias_method method, :"new_#{method}"
35
+ undef_method :"new_#{method}"
36
+ end
37
+ end
38
+
39
+ calls
40
+ end
41
+
42
+
43
+ end
44
+ end
@@ -0,0 +1,17 @@
1
+ module HerdstServicecall
2
+ class Railtie < ::Rails::Railtie
3
+
4
+
5
+ initializer "herdst_servicecall.configure_rails_initialization" do |app|
6
+ app.middleware.insert_after Rack::TempfileReaper, Middleware
7
+ end
8
+
9
+ generators do
10
+ generator_path = File.expand_path("../../generators/herdst_servicecall", __FILE__)
11
+
12
+ require "#{generator_path}/install_generator"
13
+ end
14
+
15
+
16
+ end
17
+ end
@@ -0,0 +1,66 @@
1
+ module HerdstServicecall
2
+ class Receiver
3
+
4
+
5
+ attr_accessor :config, :events
6
+
7
+
8
+ def initialize(config)
9
+ self.config = config
10
+ end
11
+
12
+
13
+ def receive(token, data)
14
+ request = Request.new(nil, nil)
15
+
16
+ begin
17
+ verify_token!(token)
18
+
19
+ request.parse!(data)
20
+
21
+ action = self.config.events[request.event.to_sym] rescue nil
22
+
23
+ raise ResponderError.new(request.event, "Invalid event") unless action
24
+
25
+ action_class_name, action_name = action.split("#")
26
+ action_class = "#{action_class_name.classify}ServiceEvent".constantize.new(request.event, request.body)
27
+ response = action_class.send(action_name, request.body)
28
+
29
+ Response.new(request.event, 200, response)
30
+ rescue Exception => ex
31
+ if ex.instance_of?(ResponderError)
32
+ ex.response
33
+
34
+ elsif ex.instance_of?(JWT::VerificationError)
35
+ Response.new(request.event, 400, {
36
+ :error => ex.message
37
+ })
38
+
39
+ elsif ex.instance_of?(JWT::DecodeError)
40
+ Response.new(request.event, 400, {
41
+ :error => "Invalid token"
42
+ })
43
+
44
+ else
45
+ Response.new(request.event, 400, {
46
+ :error => ex.message
47
+ })
48
+
49
+ end
50
+ end
51
+ end
52
+
53
+
54
+ private
55
+ def verify_token!(token)
56
+ JWT.decode(
57
+ token,
58
+ self.config.jwt_secret,
59
+ true,
60
+ { algorithm: self.config.jwt_algorithm }
61
+ )
62
+ end
63
+
64
+
65
+ end
66
+ end
@@ -0,0 +1,37 @@
1
+ module HerdstServicecall
2
+ class Request
3
+
4
+
5
+ attr_accessor :event, :body
6
+
7
+
8
+ def initialize(event, body)
9
+ self.event = event
10
+ self.body = body ?
11
+ (body.respond_to?(:with_indifferent_access) ? body.with_indifferent_access : body) :
12
+ nil
13
+ end
14
+
15
+
16
+ def to_json
17
+ {
18
+ :event => self.event,
19
+ :data => self.body
20
+ }.to_json
21
+ end
22
+
23
+
24
+ def parse!(data)
25
+ body = JSON.parse(data) rescue nil
26
+
27
+ raise "Invalid body" unless body
28
+
29
+ self.event = body["event"]
30
+ self.body = body["data"].respond_to?(:with_indifferent_access) ?
31
+ body["data"].with_indifferent_access :
32
+ body["data"]
33
+ end
34
+
35
+
36
+ end
37
+ end
@@ -0,0 +1,17 @@
1
+ module HerdstServicecall
2
+ class Responder
3
+
4
+
5
+ def initialize(event, data)
6
+ @event = event
7
+ @data = data
8
+ end
9
+
10
+
11
+ def reject!(data, code = 400)
12
+ raise ResponderError.new(@event, data, code)
13
+ end
14
+
15
+
16
+ end
17
+ end
@@ -0,0 +1,48 @@
1
+ module HerdstServicecall
2
+ class ResponderError < Exception
3
+
4
+
5
+ def initialize(event, data, code = 400)
6
+ @event = event
7
+ @code = code
8
+ @response = Response.new(event, code, get_body(data))
9
+ end
10
+
11
+
12
+ def event
13
+ @event
14
+ end
15
+
16
+
17
+ def code
18
+ @code
19
+ end
20
+
21
+
22
+ def response
23
+ @response
24
+ end
25
+
26
+
27
+ private
28
+ def get_body(data)
29
+ body = data
30
+
31
+ if data.is_a?(String)
32
+ body = {
33
+ :message => data
34
+ }
35
+ end
36
+
37
+ if data.is_a?(ActiveModel::Validations) && ((data.errors.empty? == false) || (data.valid? == false))
38
+ body = {
39
+ :message => "A validation error occured",
40
+ :errors => data.errors
41
+ }
42
+ end
43
+
44
+ body
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,55 @@
1
+ module HerdstServicecall
2
+ class Response
3
+
4
+
5
+ attr_accessor :event, :body, :code
6
+
7
+
8
+ def initialize(event, code, body)
9
+ self.event = event
10
+ self.code = code
11
+ self.body = body ?
12
+ (body.respond_to?(:with_indifferent_access) ? body.with_indifferent_access : body) :
13
+ nil
14
+ end
15
+
16
+
17
+ def was_successful?
18
+ code && code >= 200 && code < 400
19
+ end
20
+
21
+
22
+ def error(default = "Unknown Error")
23
+ if (self.was_successful? == false)
24
+ return (self.body == nil) ? { :message => default } : self.body
25
+ end
26
+
27
+ return nil
28
+ end
29
+
30
+
31
+ def to_json
32
+ {
33
+ :event => self.event,
34
+ :success => self.was_successful?,
35
+ :data => self.body
36
+ }.to_json
37
+ end
38
+
39
+
40
+ def [](key)
41
+ self.body ? self.body[key] : nil
42
+ end
43
+
44
+
45
+ def self.parse(response)
46
+ body = JSON.parse(response.body) rescue nil
47
+ event = body && body["event"]
48
+ data = body && body["data"]
49
+
50
+ self.new(event, response.code.to_i, data)
51
+ end
52
+
53
+
54
+ end
55
+ end
@@ -0,0 +1,3 @@
1
+ module HerdstServicecall
2
+ VERSION = '0.1.5'
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :servicecall do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: herdst_servicecall
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.5
5
+ platform: ruby
6
+ authors:
7
+ - Herd.St
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-06-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 6.0.3
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 6.0.3.2
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: 6.0.3
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 6.0.3.2
33
+ - !ruby/object:Gem::Dependency
34
+ name: jwt
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '2.2'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '2.2'
47
+ - !ruby/object:Gem::Dependency
48
+ name: sqlite3
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.3'
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: 1.3.11
57
+ type: :development
58
+ prerelease: false
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - "~>"
62
+ - !ruby/object:Gem::Version
63
+ version: '1.3'
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: 1.3.11
67
+ description: Caller other services from with the app.
68
+ email:
69
+ - devops@herd.st
70
+ executables: []
71
+ extensions: []
72
+ extra_rdoc_files: []
73
+ files:
74
+ - MIT-LICENSE
75
+ - README.md
76
+ - Rakefile
77
+ - lib/generators/herdst_servicecall/install_generator.rb
78
+ - lib/generators/templates/herdst_servicecall.rb
79
+ - lib/herdst_servicecall.rb
80
+ - lib/herdst_servicecall/caller.rb
81
+ - lib/herdst_servicecall/configurator.rb
82
+ - lib/herdst_servicecall/middleware.rb
83
+ - lib/herdst_servicecall/mocker.rb
84
+ - lib/herdst_servicecall/railtie.rb
85
+ - lib/herdst_servicecall/receiver.rb
86
+ - lib/herdst_servicecall/request.rb
87
+ - lib/herdst_servicecall/responder.rb
88
+ - lib/herdst_servicecall/responder_error.rb
89
+ - lib/herdst_servicecall/response.rb
90
+ - lib/herdst_servicecall/version.rb
91
+ - lib/tasks/servicecall_tasks.rake
92
+ homepage: https://herd.st
93
+ licenses:
94
+ - Nonstandard
95
+ metadata:
96
+ allowed_push_host: https://rubygems.org/
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubygems_version: 3.2.20
113
+ signing_key:
114
+ specification_version: 4
115
+ summary: Caller other services.
116
+ test_files: []