protobuffy 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 +7 -0
- data/.gitignore +21 -0
- data/.travis.yml +12 -0
- data/.yardopts +5 -0
- data/CHANGES.md +261 -0
- data/CONTRIBUTING.md +16 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +14 -0
- data/README.md +58 -0
- data/Rakefile +61 -0
- data/bin/protoc-gen-ruby +17 -0
- data/bin/rpc_server +4 -0
- data/examples/bin/reverse-client-http +4 -0
- data/examples/bin/reverse-client-socket +4 -0
- data/examples/bin/reverse-client-zmq +4 -0
- data/examples/config.ru +6 -0
- data/examples/definitions/example/reverse.proto +12 -0
- data/examples/lib/example/reverse-client.rb +23 -0
- data/examples/lib/example/reverse-service.rb +9 -0
- data/examples/lib/example/reverse.pb.rb +36 -0
- data/lib/protobuf.rb +106 -0
- data/lib/protobuf/cli.rb +249 -0
- data/lib/protobuf/code_generator.rb +41 -0
- data/lib/protobuf/decoder.rb +74 -0
- data/lib/protobuf/deprecator.rb +42 -0
- data/lib/protobuf/descriptors.rb +3 -0
- data/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +52 -0
- data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +249 -0
- data/lib/protobuf/encoder.rb +62 -0
- data/lib/protobuf/enum.rb +319 -0
- data/lib/protobuf/exceptions.rb +9 -0
- data/lib/protobuf/field.rb +74 -0
- data/lib/protobuf/field/base_field.rb +280 -0
- data/lib/protobuf/field/bool_field.rb +53 -0
- data/lib/protobuf/field/bytes_field.rb +81 -0
- data/lib/protobuf/field/double_field.rb +26 -0
- data/lib/protobuf/field/enum_field.rb +57 -0
- data/lib/protobuf/field/field_array.rb +86 -0
- data/lib/protobuf/field/fixed32_field.rb +25 -0
- data/lib/protobuf/field/fixed64_field.rb +29 -0
- data/lib/protobuf/field/float_field.rb +38 -0
- data/lib/protobuf/field/int32_field.rb +22 -0
- data/lib/protobuf/field/int64_field.rb +22 -0
- data/lib/protobuf/field/integer_field.rb +24 -0
- data/lib/protobuf/field/message_field.rb +66 -0
- data/lib/protobuf/field/sfixed32_field.rb +28 -0
- data/lib/protobuf/field/sfixed64_field.rb +29 -0
- data/lib/protobuf/field/signed_integer_field.rb +30 -0
- data/lib/protobuf/field/sint32_field.rb +22 -0
- data/lib/protobuf/field/sint64_field.rb +22 -0
- data/lib/protobuf/field/string_field.rb +35 -0
- data/lib/protobuf/field/uint32_field.rb +22 -0
- data/lib/protobuf/field/uint64_field.rb +22 -0
- data/lib/protobuf/field/varint_field.rb +68 -0
- data/lib/protobuf/generators/base.rb +71 -0
- data/lib/protobuf/generators/enum_generator.rb +42 -0
- data/lib/protobuf/generators/extension_generator.rb +28 -0
- data/lib/protobuf/generators/field_generator.rb +132 -0
- data/lib/protobuf/generators/file_generator.rb +140 -0
- data/lib/protobuf/generators/group_generator.rb +113 -0
- data/lib/protobuf/generators/message_generator.rb +99 -0
- data/lib/protobuf/generators/printable.rb +161 -0
- data/lib/protobuf/generators/service_generator.rb +27 -0
- data/lib/protobuf/http.rb +20 -0
- data/lib/protobuf/lifecycle.rb +46 -0
- data/lib/protobuf/logger.rb +86 -0
- data/lib/protobuf/message.rb +182 -0
- data/lib/protobuf/message/fields.rb +122 -0
- data/lib/protobuf/message/serialization.rb +84 -0
- data/lib/protobuf/optionable.rb +23 -0
- data/lib/protobuf/rpc/buffer.rb +79 -0
- data/lib/protobuf/rpc/client.rb +168 -0
- data/lib/protobuf/rpc/connector.rb +21 -0
- data/lib/protobuf/rpc/connectors/base.rb +54 -0
- data/lib/protobuf/rpc/connectors/common.rb +172 -0
- data/lib/protobuf/rpc/connectors/http.rb +90 -0
- data/lib/protobuf/rpc/connectors/socket.rb +73 -0
- data/lib/protobuf/rpc/connectors/zmq.rb +205 -0
- data/lib/protobuf/rpc/dynamic_discovery.pb.rb +47 -0
- data/lib/protobuf/rpc/env.rb +58 -0
- data/lib/protobuf/rpc/error.rb +28 -0
- data/lib/protobuf/rpc/error/client_error.rb +31 -0
- data/lib/protobuf/rpc/error/server_error.rb +43 -0
- data/lib/protobuf/rpc/middleware.rb +25 -0
- data/lib/protobuf/rpc/middleware/exception_handler.rb +36 -0
- data/lib/protobuf/rpc/middleware/logger.rb +91 -0
- data/lib/protobuf/rpc/middleware/request_decoder.rb +83 -0
- data/lib/protobuf/rpc/middleware/response_encoder.rb +88 -0
- data/lib/protobuf/rpc/middleware/runner.rb +18 -0
- data/lib/protobuf/rpc/rpc.pb.rb +53 -0
- data/lib/protobuf/rpc/server.rb +39 -0
- data/lib/protobuf/rpc/servers/http/server.rb +101 -0
- data/lib/protobuf/rpc/servers/http_runner.rb +34 -0
- data/lib/protobuf/rpc/servers/socket/server.rb +113 -0
- data/lib/protobuf/rpc/servers/socket/worker.rb +56 -0
- data/lib/protobuf/rpc/servers/socket_runner.rb +34 -0
- data/lib/protobuf/rpc/servers/zmq/broker.rb +155 -0
- data/lib/protobuf/rpc/servers/zmq/server.rb +313 -0
- data/lib/protobuf/rpc/servers/zmq/util.rb +47 -0
- data/lib/protobuf/rpc/servers/zmq/worker.rb +105 -0
- data/lib/protobuf/rpc/servers/zmq_runner.rb +51 -0
- data/lib/protobuf/rpc/service.rb +179 -0
- data/lib/protobuf/rpc/service_directory.rb +245 -0
- data/lib/protobuf/rpc/service_dispatcher.rb +46 -0
- data/lib/protobuf/rpc/service_filters.rb +273 -0
- data/lib/protobuf/rpc/stat.rb +148 -0
- data/lib/protobuf/socket.rb +22 -0
- data/lib/protobuf/tasks.rb +1 -0
- data/lib/protobuf/tasks/compile.rake +61 -0
- data/lib/protobuf/version.rb +3 -0
- data/lib/protobuf/wire_type.rb +10 -0
- data/lib/protobuf/zmq.rb +21 -0
- data/proto/dynamic_discovery.proto +44 -0
- data/proto/google/protobuf/compiler/plugin.proto +147 -0
- data/proto/google/protobuf/descriptor.proto +620 -0
- data/proto/rpc.proto +62 -0
- data/protobuffy.gemspec +37 -0
- data/spec/benchmark/tasks.rb +113 -0
- data/spec/bin/protoc-gen-ruby_spec.rb +18 -0
- data/spec/data/data.bin +3 -0
- data/spec/data/types.bin +0 -0
- data/spec/encoding/all_types_spec.rb +91 -0
- data/spec/encoding/extreme_values_spec.rb +0 -0
- data/spec/functional/socket_server_spec.rb +59 -0
- data/spec/functional/zmq_server_spec.rb +103 -0
- data/spec/lib/protobuf/cli_spec.rb +267 -0
- data/spec/lib/protobuf/code_generator_spec.rb +60 -0
- data/spec/lib/protobuf/enum_spec.rb +239 -0
- data/spec/lib/protobuf/field/int32_field_spec.rb +7 -0
- data/spec/lib/protobuf/field/string_field_spec.rb +46 -0
- data/spec/lib/protobuf/field_spec.rb +194 -0
- data/spec/lib/protobuf/generators/base_spec.rb +87 -0
- data/spec/lib/protobuf/generators/enum_generator_spec.rb +68 -0
- data/spec/lib/protobuf/generators/extension_generator_spec.rb +43 -0
- data/spec/lib/protobuf/generators/field_generator_spec.rb +99 -0
- data/spec/lib/protobuf/generators/file_generator_spec.rb +29 -0
- data/spec/lib/protobuf/generators/message_generator_spec.rb +0 -0
- data/spec/lib/protobuf/generators/service_generator_spec.rb +43 -0
- data/spec/lib/protobuf/lifecycle_spec.rb +89 -0
- data/spec/lib/protobuf/logger_spec.rb +136 -0
- data/spec/lib/protobuf/message_spec.rb +368 -0
- data/spec/lib/protobuf/optionable_spec.rb +46 -0
- data/spec/lib/protobuf/rpc/client_spec.rb +66 -0
- data/spec/lib/protobuf/rpc/connector_spec.rb +26 -0
- data/spec/lib/protobuf/rpc/connectors/base_spec.rb +50 -0
- data/spec/lib/protobuf/rpc/connectors/common_spec.rb +170 -0
- data/spec/lib/protobuf/rpc/connectors/connector_spec.rb +13 -0
- data/spec/lib/protobuf/rpc/connectors/http_spec.rb +61 -0
- data/spec/lib/protobuf/rpc/connectors/socket_spec.rb +24 -0
- data/spec/lib/protobuf/rpc/connectors/zmq_spec.rb +129 -0
- data/spec/lib/protobuf/rpc/middleware/exception_handler_spec.rb +62 -0
- data/spec/lib/protobuf/rpc/middleware/logger_spec.rb +49 -0
- data/spec/lib/protobuf/rpc/middleware/request_decoder_spec.rb +115 -0
- data/spec/lib/protobuf/rpc/middleware/response_encoder_spec.rb +75 -0
- data/spec/lib/protobuf/rpc/servers/http/server_spec.rb +104 -0
- data/spec/lib/protobuf/rpc/servers/socket_server_spec.rb +38 -0
- data/spec/lib/protobuf/rpc/servers/zmq/server_spec.rb +41 -0
- data/spec/lib/protobuf/rpc/servers/zmq/util_spec.rb +55 -0
- data/spec/lib/protobuf/rpc/servers/zmq/worker_spec.rb +35 -0
- data/spec/lib/protobuf/rpc/service_directory_spec.rb +295 -0
- data/spec/lib/protobuf/rpc/service_dispatcher_spec.rb +52 -0
- data/spec/lib/protobuf/rpc/service_filters_spec.rb +484 -0
- data/spec/lib/protobuf/rpc/service_spec.rb +161 -0
- data/spec/lib/protobuf/rpc/stat_spec.rb +151 -0
- data/spec/lib/protobuf_spec.rb +78 -0
- data/spec/spec_helper.rb +57 -0
- data/spec/support/all.rb +7 -0
- data/spec/support/packed_field.rb +22 -0
- data/spec/support/server.rb +94 -0
- data/spec/support/test/all_types.data.bin +0 -0
- data/spec/support/test/all_types.data.txt +119 -0
- data/spec/support/test/defaults.pb.rb +25 -0
- data/spec/support/test/defaults.proto +9 -0
- data/spec/support/test/enum.pb.rb +59 -0
- data/spec/support/test/enum.proto +34 -0
- data/spec/support/test/extended.pb.rb +22 -0
- data/spec/support/test/extended.proto +10 -0
- data/spec/support/test/extreme_values.data.bin +0 -0
- data/spec/support/test/google_unittest.pb.rb +543 -0
- data/spec/support/test/google_unittest.proto +713 -0
- data/spec/support/test/google_unittest_import.pb.rb +37 -0
- data/spec/support/test/google_unittest_import.proto +64 -0
- data/spec/support/test/google_unittest_import_public.pb.rb +8 -0
- data/spec/support/test/google_unittest_import_public.proto +38 -0
- data/spec/support/test/multi_field_extensions.pb.rb +56 -0
- data/spec/support/test/multi_field_extensions.proto +33 -0
- data/spec/support/test/resource.pb.rb +117 -0
- data/spec/support/test/resource.proto +94 -0
- data/spec/support/test/resource_service.rb +26 -0
- data/spec/support/test_app_file.rb +2 -0
- data/spec/support/tolerance_matcher.rb +40 -0
- metadata +367 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'protobuf/rpc/rpc.pb'
|
2
|
+
|
3
|
+
module Protobuf
|
4
|
+
module Rpc
|
5
|
+
ClientError = Struct.new("ClientError", :code, :message)
|
6
|
+
|
7
|
+
# Base PbError class for client and server errors
|
8
|
+
class PbError < StandardError
|
9
|
+
attr_reader :error_type
|
10
|
+
|
11
|
+
def initialize(message='An unknown RpcError occurred', error_type='RPC_ERROR')
|
12
|
+
@error_type = error_type.is_a?(String) ? Socketrpc::ErrorReason.const_get(error_type) : error_type
|
13
|
+
super message
|
14
|
+
end
|
15
|
+
|
16
|
+
def encode
|
17
|
+
to_response.encode
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_response
|
21
|
+
Socketrpc::Response.new(:error => message, :error_reason => error_type)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
require 'protobuf/rpc/error/server_error'
|
28
|
+
require 'protobuf/rpc/error/client_error'
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'protobuf/rpc/error'
|
2
|
+
|
3
|
+
module Protobuf
|
4
|
+
module Rpc
|
5
|
+
|
6
|
+
class InvalidRequestProto < PbError
|
7
|
+
def initialize(message='Invalid request type given')
|
8
|
+
super message, 'INVALID_REQUEST_PROTO'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class BadResponseProto < PbError
|
13
|
+
def initialize(message='Bad response type from server')
|
14
|
+
super message, 'BAD_RESPONSE_PROTO'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class UnkownHost < PbError
|
19
|
+
def initialize(message='Unknown host or port')
|
20
|
+
super message, 'UNKNOWN_HOST'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class IOError < PbError
|
25
|
+
def initialize(message='IO Error occurred')
|
26
|
+
super message, 'IO_ERROR'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'protobuf/rpc/rpc.pb'
|
2
|
+
|
3
|
+
module Protobuf
|
4
|
+
module Rpc
|
5
|
+
|
6
|
+
class BadRequestData < PbError
|
7
|
+
def initialize message='Unable to parse request'
|
8
|
+
super message, 'BAD_REQUEST_DATA'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class BadRequestProto < PbError
|
13
|
+
def initialize message='Request is of wrong type'
|
14
|
+
super message, 'BAD_REQUEST_PROTO'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class ServiceNotFound < PbError
|
19
|
+
def initialize message='Service class not found'
|
20
|
+
super message, 'SERVICE_NOT_FOUND'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class MethodNotFound < PbError
|
25
|
+
def initialize message='Service method not found'
|
26
|
+
super message, 'METHOD_NOT_FOUND'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class RpcError < PbError
|
31
|
+
def initialize message='RPC exception occurred'
|
32
|
+
super message, 'RPC_ERROR'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class RpcFailed < PbError
|
37
|
+
def initialize message='RPC failed'
|
38
|
+
super message, 'RPC_FAILED'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'middleware'
|
2
|
+
|
3
|
+
require 'protobuf/rpc/middleware/exception_handler'
|
4
|
+
require 'protobuf/rpc/middleware/logger'
|
5
|
+
require 'protobuf/rpc/middleware/request_decoder'
|
6
|
+
require 'protobuf/rpc/middleware/response_encoder'
|
7
|
+
require 'protobuf/rpc/middleware/runner'
|
8
|
+
|
9
|
+
module Protobuf
|
10
|
+
module Rpc
|
11
|
+
def self.middleware
|
12
|
+
@middleware ||= ::Middleware::Builder.new(:runner_class => ::Protobuf::Rpc::Middleware::Runner)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Ensure the middleware stack is initialized
|
16
|
+
middleware
|
17
|
+
end
|
18
|
+
|
19
|
+
Rpc.middleware.use(Rpc::Middleware::ExceptionHandler)
|
20
|
+
Rpc.middleware.use(Rpc::Middleware::RequestDecoder)
|
21
|
+
Rpc.middleware.use(Rpc::Middleware::Logger)
|
22
|
+
Rpc.middleware.use(Rpc::Middleware::ResponseEncoder)
|
23
|
+
|
24
|
+
ActiveSupport.run_load_hooks(:protobuf_rpc_middleware, Rpc)
|
25
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Protobuf
|
2
|
+
module Rpc
|
3
|
+
module Middleware
|
4
|
+
class ExceptionHandler
|
5
|
+
include ::Protobuf::Logger::LogMethods
|
6
|
+
|
7
|
+
attr_reader :app
|
8
|
+
|
9
|
+
def initialize(app)
|
10
|
+
@app = app
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
app.call(env)
|
15
|
+
rescue => exception
|
16
|
+
log_exception(exception)
|
17
|
+
|
18
|
+
# Rescue exceptions, re-wrap them as generic Protobuf errors,
|
19
|
+
# and encode them
|
20
|
+
env.response = wrap_exception(exception)
|
21
|
+
env.encoded_response = env.response.encode
|
22
|
+
env
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
# Wrap exceptions in a generic Protobuf errors unless they already are
|
28
|
+
#
|
29
|
+
def wrap_exception(exception)
|
30
|
+
exception = RpcFailed.new(exception.message) unless exception.is_a?(PbError)
|
31
|
+
exception
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Protobuf
|
2
|
+
module Rpc
|
3
|
+
module Middleware
|
4
|
+
class Logger
|
5
|
+
def initialize(app)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
# TODO: Figure out how to control when logs are flushed
|
10
|
+
def call(env)
|
11
|
+
instrumenter.start
|
12
|
+
instrumenter.flush(env) # Log request stats
|
13
|
+
|
14
|
+
env = @app.call(env)
|
15
|
+
|
16
|
+
instrumenter.stop
|
17
|
+
instrumenter.flush(env) # Log response stats
|
18
|
+
|
19
|
+
env
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def instrumenter
|
25
|
+
@instrumenter ||= Instrumenter.new
|
26
|
+
end
|
27
|
+
|
28
|
+
# TODO: Replace this with ActiveSupport::Notifications and log subscribers
|
29
|
+
# TODO: Consider adopting Rails-style logging so we can track serialization
|
30
|
+
# time as well as ActiveRecord time, etc.:
|
31
|
+
#
|
32
|
+
# Started GET "/" for 127.0.0.1 at 2014-02-12 09:40:29 -0700
|
33
|
+
# Processing by ReleasesController#index as HTML
|
34
|
+
# Rendered releases/_release.html.erb (0.0ms)
|
35
|
+
# Rendered releases/_release.html.erb (0.0ms)
|
36
|
+
# Rendered releases/_release.html.erb (0.0ms)
|
37
|
+
# Rendered releases/_release.html.erb (0.0ms)
|
38
|
+
# Rendered releases/index.html.erb within layouts/application (11.0ms)
|
39
|
+
# Completed 200 OK in 142ms (Views: 117.6ms | ActiveRecord: 1.7ms)
|
40
|
+
#
|
41
|
+
class Instrumenter
|
42
|
+
attr_reader :env
|
43
|
+
|
44
|
+
def flush(env)
|
45
|
+
Protobuf::Logger.info { to_s(env) }
|
46
|
+
end
|
47
|
+
|
48
|
+
def start
|
49
|
+
@start_time = ::Time.now.utc
|
50
|
+
end
|
51
|
+
|
52
|
+
def stop
|
53
|
+
@end_time = ::Time.now.utc
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_s(env)
|
57
|
+
@env = env
|
58
|
+
|
59
|
+
[
|
60
|
+
"[SRV]",
|
61
|
+
env.client_host,
|
62
|
+
env.worker_id,
|
63
|
+
rpc,
|
64
|
+
sizes,
|
65
|
+
elapsed_time,
|
66
|
+
@end_time.try(:iso8601)
|
67
|
+
].compact.join(' - ')
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def elapsed_time
|
73
|
+
(@start_time && @end_time ? "#{(@end_time - @start_time).round(4)}s" : nil)
|
74
|
+
end
|
75
|
+
|
76
|
+
def rpc
|
77
|
+
env.service_name && env.method_name ? "#{env.service_name}##{env.method_name}" : nil
|
78
|
+
end
|
79
|
+
|
80
|
+
def sizes
|
81
|
+
if env.encoded_response?
|
82
|
+
"#{env.encoded_request.size}B/#{env.encoded_response.size}B"
|
83
|
+
else
|
84
|
+
"#{env.encoded_request.size}B/-"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Protobuf
|
2
|
+
module Rpc
|
3
|
+
module Middleware
|
4
|
+
class RequestDecoder
|
5
|
+
include ::Protobuf::Logger::LogMethods
|
6
|
+
|
7
|
+
attr_reader :app, :env
|
8
|
+
|
9
|
+
def initialize(app)
|
10
|
+
@app = app
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
@env = env
|
15
|
+
|
16
|
+
env.service_name = service_name
|
17
|
+
env.method_name = method_name
|
18
|
+
env.request = request
|
19
|
+
env.client_host = request_wrapper.caller
|
20
|
+
|
21
|
+
env.rpc_service = service
|
22
|
+
env.rpc_method = rpc_method
|
23
|
+
env.request_type = rpc_method.request_type
|
24
|
+
env.response_type = rpc_method.response_type
|
25
|
+
|
26
|
+
app.call(env)
|
27
|
+
end
|
28
|
+
|
29
|
+
def log_signature
|
30
|
+
env.signature || super
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def method_name
|
36
|
+
@method_name ||= begin
|
37
|
+
method_name = request_wrapper.method_name.underscore.to_sym
|
38
|
+
|
39
|
+
unless service.rpc_method?(method_name)
|
40
|
+
raise MethodNotFound.new("#{service.name}##{method_name} is not a defined RPC method.")
|
41
|
+
end
|
42
|
+
|
43
|
+
method_name
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def request
|
48
|
+
@request ||= begin
|
49
|
+
data = request_wrapper.request_proto
|
50
|
+
rpc_method.request_type.decode(data)
|
51
|
+
end
|
52
|
+
rescue => exception
|
53
|
+
raise BadRequestData.new("Unable to decode request: #{exception.message}")
|
54
|
+
end
|
55
|
+
|
56
|
+
# Decode the incoming request object into our expected request object
|
57
|
+
#
|
58
|
+
def request_wrapper
|
59
|
+
@request_wrapper ||= begin
|
60
|
+
log_debug { sign_message("Decoding request: #{env.encoded_request}") }
|
61
|
+
Socketrpc::Request.decode(env.encoded_request)
|
62
|
+
end
|
63
|
+
rescue => exception
|
64
|
+
raise BadRequestData.new("Unable to decode request: #{exception.message}")
|
65
|
+
end
|
66
|
+
|
67
|
+
def rpc_method
|
68
|
+
@rpc_method ||= service.rpcs[method_name]
|
69
|
+
end
|
70
|
+
|
71
|
+
def service
|
72
|
+
@service ||= service_name.constantize
|
73
|
+
rescue NameError
|
74
|
+
raise ServiceNotFound.new("Service class #{service_name} is not defined.")
|
75
|
+
end
|
76
|
+
|
77
|
+
def service_name
|
78
|
+
@service_name ||= request_wrapper.service_name
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Protobuf
|
2
|
+
module Rpc
|
3
|
+
module Middleware
|
4
|
+
class ResponseEncoder
|
5
|
+
include ::Protobuf::Logger::LogMethods
|
6
|
+
|
7
|
+
attr_reader :app, :env
|
8
|
+
|
9
|
+
def initialize(app)
|
10
|
+
@app = app
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
@env = app.call(env)
|
15
|
+
|
16
|
+
env.response = response
|
17
|
+
env.encoded_response = encoded_response
|
18
|
+
env
|
19
|
+
end
|
20
|
+
|
21
|
+
def log_signature
|
22
|
+
env.signature || super
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
# Encode the response wrapper to return to the client
|
28
|
+
#
|
29
|
+
def encoded_response
|
30
|
+
log_debug { sign_message("Encoding response: #{response.inspect}") }
|
31
|
+
|
32
|
+
env.encoded_response = wrapped_response.encode
|
33
|
+
rescue => exception
|
34
|
+
log_exception(exception)
|
35
|
+
|
36
|
+
# Rescue encoding exceptions, re-wrap them as generic protobuf errors,
|
37
|
+
# and re-raise them
|
38
|
+
raise PbError.new(exception.message)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Prod the object to see if we can produce a proto object as a response
|
42
|
+
# candidate. Validate the candidate protos.
|
43
|
+
def response
|
44
|
+
@response ||= begin
|
45
|
+
candidate = env.response
|
46
|
+
case
|
47
|
+
when candidate.is_a?(Message) then
|
48
|
+
validate!(candidate)
|
49
|
+
when candidate.respond_to?(:to_proto) then
|
50
|
+
validate!(candidate.to_proto)
|
51
|
+
when candidate.respond_to?(:to_hash) then
|
52
|
+
env.response_type.new(candidate.to_hash)
|
53
|
+
when candidate.is_a?(PbError) then
|
54
|
+
candidate
|
55
|
+
else
|
56
|
+
validate!(candidate)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Ensure that the response candidate we've been given is of the type
|
62
|
+
# we expect so that deserialization on the client side works.
|
63
|
+
#
|
64
|
+
def validate!(candidate)
|
65
|
+
actual = candidate.class
|
66
|
+
expected = env.response_type
|
67
|
+
|
68
|
+
if expected != actual
|
69
|
+
raise BadResponseProto.new("Expected response to be of type #{expected.name} but was #{actual.name}")
|
70
|
+
end
|
71
|
+
|
72
|
+
candidate
|
73
|
+
end
|
74
|
+
|
75
|
+
# The middleware stack returns either an error or response proto. Package
|
76
|
+
# it up so that it's in the correct spot in the response wrapper
|
77
|
+
#
|
78
|
+
def wrapped_response
|
79
|
+
if response.is_a?(Protobuf::Rpc::PbError)
|
80
|
+
Socketrpc::Response.new(:error => response.message, :error_reason => response.error_type)
|
81
|
+
else
|
82
|
+
Socketrpc::Response.new(:response_proto => response.encode)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'middleware/runner'
|
2
|
+
|
3
|
+
module Protobuf
|
4
|
+
module Rpc
|
5
|
+
module Middleware
|
6
|
+
class Runner < ::Middleware::Runner
|
7
|
+
# Override the default middleware runner so we can ensure that the
|
8
|
+
# service dispatcher is the last thing called in the stack.
|
9
|
+
#
|
10
|
+
def initialize(stack)
|
11
|
+
stack << Protobuf::Rpc::ServiceDispatcher
|
12
|
+
|
13
|
+
super(stack)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|