gruf 1.2.7 → 2.0.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 +11 -0
- data/README.md +98 -119
- data/bin/gruf +9 -3
- data/lib/gruf.rb +4 -4
- data/lib/gruf/configuration.rb +11 -20
- data/lib/gruf/controllers/base.rb +82 -0
- data/lib/gruf/controllers/request.rb +96 -0
- data/lib/gruf/controllers/service_binder.rb +86 -0
- data/lib/gruf/error.rb +9 -0
- data/lib/gruf/errors/helpers.rb +40 -0
- data/lib/gruf/{hooks → interceptors}/active_record/connection_reset.rb +4 -10
- data/lib/gruf/interceptors/authentication/basic.rb +80 -0
- data/lib/gruf/interceptors/base.rb +51 -0
- data/lib/gruf/{instrumentation/output_metadata_timer.rb → interceptors/context.rb} +25 -15
- data/lib/gruf/interceptors/instrumentation/output_metadata_timer.rb +59 -0
- data/lib/gruf/{instrumentation → interceptors/instrumentation}/request_logging/formatters/base.rb +15 -13
- data/lib/gruf/{instrumentation → interceptors/instrumentation}/request_logging/formatters/logstash.rb +15 -13
- data/lib/gruf/{instrumentation → interceptors/instrumentation}/request_logging/formatters/plain.rb +21 -19
- data/lib/gruf/interceptors/instrumentation/request_logging/interceptor.rb +191 -0
- data/lib/gruf/interceptors/instrumentation/statsd.rb +80 -0
- data/lib/gruf/interceptors/registry.rb +131 -0
- data/lib/gruf/{authentication/none.rb → interceptors/server_interceptor.rb} +8 -7
- data/lib/gruf/interceptors/timer.rb +79 -0
- data/lib/gruf/response.rb +1 -2
- data/lib/gruf/server.rb +40 -25
- data/lib/gruf/version.rb +1 -1
- metadata +19 -20
- data/lib/gruf/authentication.rb +0 -65
- data/lib/gruf/authentication/base.rb +0 -65
- data/lib/gruf/authentication/basic.rb +0 -74
- data/lib/gruf/authentication/strategies.rb +0 -107
- data/lib/gruf/hooks/base.rb +0 -66
- data/lib/gruf/hooks/registry.rb +0 -110
- data/lib/gruf/instrumentation/base.rb +0 -114
- data/lib/gruf/instrumentation/registry.rb +0 -104
- data/lib/gruf/instrumentation/request_context.rb +0 -82
- data/lib/gruf/instrumentation/request_logging/hook.rb +0 -185
- data/lib/gruf/instrumentation/statsd.rb +0 -80
- data/lib/gruf/service.rb +0 -333
@@ -0,0 +1,82 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
5
|
+
# documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
6
|
+
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
7
|
+
# persons to whom the Software is furnished to do so, subject to the following conditions:
|
8
|
+
#
|
9
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
10
|
+
# Software.
|
11
|
+
#
|
12
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
13
|
+
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
14
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
15
|
+
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
16
|
+
#
|
17
|
+
require_relative 'request'
|
18
|
+
require_relative 'service_binder'
|
19
|
+
|
20
|
+
module Gruf
|
21
|
+
module Controllers
|
22
|
+
##
|
23
|
+
# Base controller object for Gruf gRPC requests
|
24
|
+
#
|
25
|
+
class Base
|
26
|
+
include Gruf::Errors::Helpers
|
27
|
+
|
28
|
+
# @var [Gruf::Controller::Request] request
|
29
|
+
attr_reader :request
|
30
|
+
# @var [Gruf::Error] error
|
31
|
+
attr_reader :error
|
32
|
+
|
33
|
+
##
|
34
|
+
# Initialize the controller within the given request context
|
35
|
+
#
|
36
|
+
# @param [Symbol] method_key
|
37
|
+
# @param [GRPC::GenericService] service
|
38
|
+
# @param [GRPC::RpcDesc] rpc_desc
|
39
|
+
# @param [GRPC::ActiveCall] active_call
|
40
|
+
# @param [Google::Protobuf::MessageExts] message
|
41
|
+
#
|
42
|
+
def initialize(method_key:, service:, rpc_desc:, active_call:, message:)
|
43
|
+
@request = Request.new(
|
44
|
+
method_key: method_key,
|
45
|
+
service: service,
|
46
|
+
rpc_desc: rpc_desc,
|
47
|
+
active_call: active_call,
|
48
|
+
message: message
|
49
|
+
)
|
50
|
+
@error = Gruf::Error.new
|
51
|
+
@interceptors = Gruf.interceptors.prepare(@request, @error)
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# Bind the controller to the given service and add it to the service registry
|
56
|
+
#
|
57
|
+
# @param [GRPC::GenericService] service
|
58
|
+
#
|
59
|
+
def self.bind(service)
|
60
|
+
Gruf.services << service.name.constantize
|
61
|
+
ServiceBinder.new(service).bind!(self)
|
62
|
+
end
|
63
|
+
|
64
|
+
##
|
65
|
+
# Call a method on this controller
|
66
|
+
#
|
67
|
+
# @param [Symbol] method_key
|
68
|
+
#
|
69
|
+
def call(method_key, &block)
|
70
|
+
Interceptors::Context.new(@interceptors).intercept! do
|
71
|
+
send(method_key, &block)
|
72
|
+
end
|
73
|
+
rescue GRPC::BadStatus
|
74
|
+
raise # passthrough
|
75
|
+
rescue => e
|
76
|
+
set_debug_info(e.message, e.backtrace) if Gruf.backtrace_on_error
|
77
|
+
error_message = Gruf.use_exception_message ? e.message : Gruf.internal_error_message
|
78
|
+
fail!(:internal, :unknown, error_message)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
5
|
+
# documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
6
|
+
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
7
|
+
# persons to whom the Software is furnished to do so, subject to the following conditions:
|
8
|
+
#
|
9
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
10
|
+
# Software.
|
11
|
+
#
|
12
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
13
|
+
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
14
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
15
|
+
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
16
|
+
#
|
17
|
+
module Gruf
|
18
|
+
module Controllers
|
19
|
+
##
|
20
|
+
# Encapsulates a request for a controller
|
21
|
+
#
|
22
|
+
class Request
|
23
|
+
# @var [Object] message
|
24
|
+
attr_reader :message
|
25
|
+
# @var [GRPC::ActiveCall] active_call
|
26
|
+
attr_reader :active_call
|
27
|
+
# @var [Symbol] method_key
|
28
|
+
attr_reader :method_key
|
29
|
+
# @var [Gruf::Controllers::Request::Type] type
|
30
|
+
attr_reader :type
|
31
|
+
|
32
|
+
delegate :metadata, to: :active_call
|
33
|
+
delegate :messages, :client_streamer?, :server_streamer?, :bidi_streamer?, :request_response?, to: :type
|
34
|
+
|
35
|
+
class Type
|
36
|
+
delegate :client_streamer?, :server_streamer?, :bidi_streamer?, :request_response?, to: :@rpc_desc
|
37
|
+
|
38
|
+
##
|
39
|
+
# @param [GRPC::RpcDesc] rpc_desc
|
40
|
+
#
|
41
|
+
def initialize(rpc_desc)
|
42
|
+
@rpc_desc = rpc_desc
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# @param [Symbol] method_key The method symbol of the RPC method being executed
|
48
|
+
# @param [Class] service The class of the service being executed against
|
49
|
+
# @param [GRPC::RpcDesc] rpc_desc The RPC descriptor of the call
|
50
|
+
# @param [GRPC::ActiveCall] active_call The restricted view of the call
|
51
|
+
# @param [Object] message The protobuf message (or messages) of the request
|
52
|
+
#
|
53
|
+
def initialize(method_key:, service:, rpc_desc:, active_call:, message:)
|
54
|
+
@method_key = method_key
|
55
|
+
@service = service
|
56
|
+
@active_call = active_call
|
57
|
+
@message = message
|
58
|
+
@type = Type.new(rpc_desc)
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# Returns the service name as a translated name separated by periods. Strips
|
63
|
+
# the superfluous "Service" suffix from the name
|
64
|
+
#
|
65
|
+
# @return [String]
|
66
|
+
#
|
67
|
+
def service_key
|
68
|
+
@service.name.underscore.tr('/', '.').gsub('.service', '')
|
69
|
+
end
|
70
|
+
|
71
|
+
##
|
72
|
+
# Parse the method signature into a service.method name format
|
73
|
+
#
|
74
|
+
# @return [String] The parsed service method name
|
75
|
+
#
|
76
|
+
def method_name
|
77
|
+
"#{service_key}.#{method_key}"
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# Return all messages for this request, properly handling different request types
|
82
|
+
#
|
83
|
+
# @return Enumerable<Object>
|
84
|
+
#
|
85
|
+
def messages
|
86
|
+
if client_streamer?
|
87
|
+
message.call { |msg| yield msg }
|
88
|
+
elsif bidi_streamer?
|
89
|
+
message
|
90
|
+
else
|
91
|
+
[message]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
5
|
+
# documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
6
|
+
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
7
|
+
# persons to whom the Software is furnished to do so, subject to the following conditions:
|
8
|
+
#
|
9
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
10
|
+
# Software.
|
11
|
+
#
|
12
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
13
|
+
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
14
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
15
|
+
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
16
|
+
#
|
17
|
+
module Gruf
|
18
|
+
module Controllers
|
19
|
+
##
|
20
|
+
# Binds gRPC services to a gruf controller
|
21
|
+
#
|
22
|
+
class ServiceBinder
|
23
|
+
##
|
24
|
+
# Represents a bound RPC descriptor for future-proofing internal helpers
|
25
|
+
#
|
26
|
+
class BoundDesc < SimpleDelegator; end
|
27
|
+
|
28
|
+
##
|
29
|
+
# @param [GRPC::GenericService] service
|
30
|
+
#
|
31
|
+
def initialize(service)
|
32
|
+
@service = service
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# @param [Gruf::Controllers::Base]
|
37
|
+
#
|
38
|
+
def bind!(controller)
|
39
|
+
rpc_methods.each { |name, desc| bind_method(controller, name, desc) }
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
##
|
45
|
+
# @param [Gruf::Controllers::Base] controller
|
46
|
+
# @param [Symbol] method_name
|
47
|
+
# @param [BoundDesc] desc
|
48
|
+
#
|
49
|
+
def bind_method(controller, method_name, desc)
|
50
|
+
method_key = method_name.to_s.underscore.to_sym
|
51
|
+
service_ref = @service
|
52
|
+
|
53
|
+
@service.class_eval do
|
54
|
+
if desc.request_response?
|
55
|
+
define_method(method_key) do |message, active_call|
|
56
|
+
c = controller.new(method_key: method_key, service: service_ref, message: message, active_call: active_call, rpc_desc: desc)
|
57
|
+
c.call(method_key)
|
58
|
+
end
|
59
|
+
elsif desc.client_streamer?
|
60
|
+
define_method(method_key) do |active_call|
|
61
|
+
c = controller.new(method_key: method_key, service: service_ref, message: proc { |&block| active_call.each_remote_read(&block) }, active_call: active_call, rpc_desc: desc)
|
62
|
+
c.call(method_key)
|
63
|
+
end
|
64
|
+
elsif desc.server_streamer?
|
65
|
+
define_method(method_key) do |message, active_call, &block|
|
66
|
+
c = controller.new(method_key: method_key, service: service_ref, message: message, active_call: active_call, rpc_desc: desc)
|
67
|
+
c.call(method_key, &block)
|
68
|
+
end
|
69
|
+
else # bidi
|
70
|
+
define_method(method_key) do |messages, active_call, &block|
|
71
|
+
c = controller.new(method_key: method_key, service: service_ref, message: messages, active_call: active_call, rpc_desc: desc)
|
72
|
+
c.call(method_key, &block)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
##
|
79
|
+
# @return Array<Gruf::Controllers::ServiceBinder::BoundDesc>
|
80
|
+
#
|
81
|
+
def rpc_methods
|
82
|
+
@service.rpc_descs.map { |rd| BoundDesc.new(rd) }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/gruf/error.rb
CHANGED
@@ -90,6 +90,15 @@ module Gruf
|
|
90
90
|
@field_errors << Errors::Field.new(field_name, error_code, message)
|
91
91
|
end
|
92
92
|
|
93
|
+
##
|
94
|
+
# Return true if there are any present field errors
|
95
|
+
#
|
96
|
+
# @return [Boolean] True if the service has any field errors
|
97
|
+
#
|
98
|
+
def has_field_errors?
|
99
|
+
@field_errors.any?
|
100
|
+
end
|
101
|
+
|
93
102
|
##
|
94
103
|
# Set the debugging information for the error message
|
95
104
|
#
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
5
|
+
# documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
6
|
+
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
7
|
+
# persons to whom the Software is furnished to do so, subject to the following conditions:
|
8
|
+
#
|
9
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
10
|
+
# Software.
|
11
|
+
#
|
12
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
13
|
+
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
14
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
15
|
+
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
16
|
+
#
|
17
|
+
module Gruf
|
18
|
+
module Errors
|
19
|
+
module Helpers
|
20
|
+
delegate :add_field_error, :set_debug_info, :has_field_errors?, to: :error
|
21
|
+
|
22
|
+
##
|
23
|
+
# Will issue a GRPC BadStatus exception, with a code based on the code passed.
|
24
|
+
#
|
25
|
+
# @param [Symbol] error_code The network error code that maps to gRPC status codes
|
26
|
+
# @param [Symbol] app_code The application-specific code for the error
|
27
|
+
# @param [String] message (Optional) A detail message about the error
|
28
|
+
# @param [Hash] metadata (Optional) Any metadata to inject into the trailing metadata for the response
|
29
|
+
#
|
30
|
+
def fail!(error_code, app_code = nil, message = '', metadata = {})
|
31
|
+
e = error
|
32
|
+
e.code = error_code.to_sym
|
33
|
+
e.app_code = app_code ? app_code.to_sym : e.code
|
34
|
+
e.message = message.to_s
|
35
|
+
e.metadata = metadata
|
36
|
+
e.fail!(request.active_call)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -15,25 +15,19 @@
|
|
15
15
|
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
16
16
|
#
|
17
17
|
module Gruf
|
18
|
-
module
|
18
|
+
module Interceptors
|
19
19
|
module ActiveRecord
|
20
20
|
##
|
21
21
|
# Resets the ActiveRecord connection to maintain accurate connected state in the thread pool
|
22
22
|
#
|
23
|
-
class ConnectionReset < Gruf::
|
23
|
+
class ConnectionReset < ::Gruf::Interceptors::ServerInterceptor
|
24
24
|
##
|
25
25
|
# Reset any ActiveRecord connections after a gRPC service is called. Because of the way gRPC manages its
|
26
26
|
# connection pool, we need to ensure that this is done to properly
|
27
27
|
#
|
28
|
-
|
29
|
-
# @param [Object] _response The protobuf response object
|
30
|
-
# @param [Symbol] _call_signature The gRPC method on the service that was called
|
31
|
-
# @param [Object] _request The protobuf request object
|
32
|
-
# @param [GRPC::ActiveCall] _call the gRPC core active call object, which represents marshalled data for
|
33
|
-
# the call itself
|
34
|
-
#
|
35
|
-
def after(_success, _response, _call_signature, _request, _call)
|
28
|
+
def call
|
36
29
|
::ActiveRecord::Base.clear_active_connections! if enabled?
|
30
|
+
yield
|
37
31
|
end
|
38
32
|
|
39
33
|
private
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
5
|
+
# documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
6
|
+
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
7
|
+
# persons to whom the Software is furnished to do so, subject to the following conditions:
|
8
|
+
#
|
9
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
10
|
+
# Software.
|
11
|
+
#
|
12
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
13
|
+
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
14
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
15
|
+
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
16
|
+
#
|
17
|
+
require 'base64'
|
18
|
+
|
19
|
+
module Gruf
|
20
|
+
module Interceptors
|
21
|
+
module Authentication
|
22
|
+
##
|
23
|
+
# Handles basic authentication for gRPC requests
|
24
|
+
#
|
25
|
+
class Basic < Gruf::Interceptors::ServerInterceptor
|
26
|
+
|
27
|
+
def call
|
28
|
+
fail!(:unauthenticated, :unauthenticated) unless bypass? || valid?
|
29
|
+
yield
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
##
|
35
|
+
# @return [Boolean] If this method is in the excluded list, bypass
|
36
|
+
#
|
37
|
+
def bypass?
|
38
|
+
options.fetch(:excluded_methods, []).include?(request.method_name)
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# @return [Boolean] True if the basic authentication was valid
|
43
|
+
#
|
44
|
+
def valid?
|
45
|
+
server_credentials.any? do |cred|
|
46
|
+
username = cred.fetch(:username, '').to_s
|
47
|
+
password = cred.fetch(:password, '').to_s
|
48
|
+
if username.empty?
|
49
|
+
request_password == password
|
50
|
+
else
|
51
|
+
request_credentials == "#{username}:#{password}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# @return [Array<Hash>] An array of valid server credentials for this service
|
58
|
+
#
|
59
|
+
def server_credentials
|
60
|
+
options.fetch(:credentials, [])
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# @return [String] The decoded request credentials
|
65
|
+
#
|
66
|
+
def request_credentials
|
67
|
+
credentials = request.active_call.respond_to?(:metadata) ? request.active_call.metadata['authorization'].to_s : ''
|
68
|
+
Base64.decode64(credentials.to_s.gsub('Basic ', '').strip)
|
69
|
+
end
|
70
|
+
|
71
|
+
##
|
72
|
+
# @return [String] The decoded request password
|
73
|
+
#
|
74
|
+
def request_password
|
75
|
+
@request_password ||= request_credentials.split(':').last
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
5
|
+
# documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
6
|
+
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
7
|
+
# persons to whom the Software is furnished to do so, subject to the following conditions:
|
8
|
+
#
|
9
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
10
|
+
# Software.
|
11
|
+
#
|
12
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
13
|
+
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
14
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
15
|
+
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
16
|
+
#
|
17
|
+
module Gruf
|
18
|
+
module Interceptors
|
19
|
+
##
|
20
|
+
# Base class for interception requests
|
21
|
+
#
|
22
|
+
class Base
|
23
|
+
# @var [Gruf::Controllers::Request] request
|
24
|
+
attr_reader :request
|
25
|
+
# @var [Gruf::Error] error
|
26
|
+
attr_reader :error
|
27
|
+
# @var [Hash] options
|
28
|
+
attr_reader :options
|
29
|
+
|
30
|
+
##
|
31
|
+
# @param [Gruf::Controllers::Request] request
|
32
|
+
# @param [Gruf::Error] error
|
33
|
+
# @param [Hash] options
|
34
|
+
#
|
35
|
+
def initialize(request, error, options = {})
|
36
|
+
@request = request
|
37
|
+
@error = error
|
38
|
+
@options = options || {}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
require_relative 'server_interceptor'
|
45
|
+
require_relative 'context'
|
46
|
+
require_relative 'timer'
|
47
|
+
require_relative 'active_record/connection_reset'
|
48
|
+
require_relative 'authentication/basic'
|
49
|
+
require_relative 'instrumentation/statsd'
|
50
|
+
require_relative 'instrumentation/output_metadata_timer'
|
51
|
+
require_relative 'instrumentation/request_logging/interceptor'
|