itsi 0.1.14 → 0.1.18

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.
Files changed (169) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +124 -109
  3. data/Cargo.toml +6 -0
  4. data/crates/itsi_error/Cargo.toml +1 -0
  5. data/crates/itsi_error/src/lib.rs +100 -10
  6. data/crates/itsi_scheduler/src/itsi_scheduler.rs +1 -1
  7. data/crates/itsi_server/Cargo.toml +8 -10
  8. data/crates/itsi_server/src/default_responses/html/401.html +68 -0
  9. data/crates/itsi_server/src/default_responses/html/403.html +68 -0
  10. data/crates/itsi_server/src/default_responses/html/404.html +68 -0
  11. data/crates/itsi_server/src/default_responses/html/413.html +71 -0
  12. data/crates/itsi_server/src/default_responses/html/429.html +68 -0
  13. data/crates/itsi_server/src/default_responses/html/500.html +71 -0
  14. data/crates/itsi_server/src/default_responses/html/502.html +71 -0
  15. data/crates/itsi_server/src/default_responses/html/503.html +68 -0
  16. data/crates/itsi_server/src/default_responses/html/504.html +69 -0
  17. data/crates/itsi_server/src/default_responses/html/index.html +238 -0
  18. data/crates/itsi_server/src/default_responses/json/401.json +6 -0
  19. data/crates/itsi_server/src/default_responses/json/403.json +6 -0
  20. data/crates/itsi_server/src/default_responses/json/404.json +6 -0
  21. data/crates/itsi_server/src/default_responses/json/413.json +6 -0
  22. data/crates/itsi_server/src/default_responses/json/429.json +6 -0
  23. data/crates/itsi_server/src/default_responses/json/500.json +6 -0
  24. data/crates/itsi_server/src/default_responses/json/502.json +6 -0
  25. data/crates/itsi_server/src/default_responses/json/503.json +6 -0
  26. data/crates/itsi_server/src/default_responses/json/504.json +6 -0
  27. data/crates/itsi_server/src/default_responses/mod.rs +11 -0
  28. data/crates/itsi_server/src/lib.rs +58 -26
  29. data/crates/itsi_server/src/prelude.rs +2 -0
  30. data/crates/itsi_server/src/ruby_types/README.md +21 -0
  31. data/crates/itsi_server/src/ruby_types/itsi_body_proxy/mod.rs +8 -6
  32. data/crates/itsi_server/src/ruby_types/itsi_grpc_call.rs +344 -0
  33. data/crates/itsi_server/src/ruby_types/{itsi_grpc_stream → itsi_grpc_response_stream}/mod.rs +121 -73
  34. data/crates/itsi_server/src/ruby_types/itsi_http_request.rs +103 -40
  35. data/crates/itsi_server/src/ruby_types/itsi_http_response.rs +8 -5
  36. data/crates/itsi_server/src/ruby_types/itsi_server/file_watcher.rs +4 -4
  37. data/crates/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +37 -17
  38. data/crates/itsi_server/src/ruby_types/itsi_server.rs +4 -3
  39. data/crates/itsi_server/src/ruby_types/mod.rs +6 -13
  40. data/crates/itsi_server/src/server/{bind.rs → binds/bind.rs} +23 -4
  41. data/crates/itsi_server/src/server/{listener.rs → binds/listener.rs} +24 -10
  42. data/crates/itsi_server/src/server/binds/mod.rs +4 -0
  43. data/crates/itsi_server/src/server/{tls.rs → binds/tls.rs} +9 -4
  44. data/crates/itsi_server/src/server/http_message_types.rs +97 -0
  45. data/crates/itsi_server/src/server/io_stream.rs +2 -1
  46. data/crates/itsi_server/src/server/middleware_stack/middleware.rs +28 -16
  47. data/crates/itsi_server/src/server/middleware_stack/middlewares/allow_list.rs +17 -8
  48. data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_api_key.rs +47 -18
  49. data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_basic.rs +13 -9
  50. data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_jwt.rs +50 -29
  51. data/crates/itsi_server/src/server/middleware_stack/middlewares/cache_control.rs +5 -2
  52. data/crates/itsi_server/src/server/middleware_stack/middlewares/compression.rs +37 -48
  53. data/crates/itsi_server/src/server/middleware_stack/middlewares/cors.rs +25 -20
  54. data/crates/itsi_server/src/server/middleware_stack/middlewares/deny_list.rs +14 -7
  55. data/crates/itsi_server/src/server/middleware_stack/middlewares/error_response/default_responses.rs +190 -0
  56. data/crates/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +125 -95
  57. data/crates/itsi_server/src/server/middleware_stack/middlewares/etag.rs +9 -5
  58. data/crates/itsi_server/src/server/middleware_stack/middlewares/header_interpretation.rs +1 -4
  59. data/crates/itsi_server/src/server/middleware_stack/middlewares/intrusion_protection.rs +25 -19
  60. data/crates/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +4 -4
  61. data/crates/itsi_server/src/server/middleware_stack/middlewares/max_body.rs +47 -0
  62. data/crates/itsi_server/src/server/middleware_stack/middlewares/mod.rs +9 -4
  63. data/crates/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +260 -62
  64. data/crates/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +29 -22
  65. data/crates/itsi_server/src/server/middleware_stack/middlewares/redirect.rs +6 -6
  66. data/crates/itsi_server/src/server/middleware_stack/middlewares/request_headers.rs +6 -5
  67. data/crates/itsi_server/src/server/middleware_stack/middlewares/response_headers.rs +4 -2
  68. data/crates/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +51 -18
  69. data/crates/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +31 -13
  70. data/crates/itsi_server/src/server/middleware_stack/middlewares/static_response.rs +55 -0
  71. data/crates/itsi_server/src/server/middleware_stack/middlewares/string_rewrite.rs +13 -8
  72. data/crates/itsi_server/src/server/middleware_stack/mod.rs +101 -69
  73. data/crates/itsi_server/src/server/mod.rs +3 -9
  74. data/crates/itsi_server/src/server/process_worker.rs +21 -3
  75. data/crates/itsi_server/src/server/request_job.rs +2 -2
  76. data/crates/itsi_server/src/server/serve_strategy/cluster_mode.rs +8 -3
  77. data/crates/itsi_server/src/server/serve_strategy/single_mode.rs +26 -26
  78. data/crates/itsi_server/src/server/signal.rs +24 -41
  79. data/crates/itsi_server/src/server/size_limited_incoming.rs +101 -0
  80. data/crates/itsi_server/src/server/thread_worker.rs +59 -28
  81. data/crates/itsi_server/src/services/itsi_http_service.rs +239 -0
  82. data/crates/itsi_server/src/services/mime_types.rs +1416 -0
  83. data/crates/itsi_server/src/services/mod.rs +6 -0
  84. data/crates/itsi_server/src/services/password_hasher.rs +83 -0
  85. data/crates/itsi_server/src/{server → services}/rate_limiter.rs +35 -31
  86. data/crates/itsi_server/src/{server → services}/static_file_server.rs +521 -181
  87. data/crates/itsi_tracing/src/lib.rs +145 -55
  88. data/{Itsi.rb → foo/Itsi.rb} +6 -9
  89. data/gems/scheduler/Cargo.lock +7 -0
  90. data/gems/scheduler/lib/itsi/scheduler/version.rb +1 -1
  91. data/gems/scheduler/test/helpers/test_helper.rb +0 -1
  92. data/gems/scheduler/test/test_address_resolve.rb +0 -1
  93. data/gems/scheduler/test/test_network_io.rb +1 -1
  94. data/gems/scheduler/test/test_process_wait.rb +0 -1
  95. data/gems/server/Cargo.lock +124 -109
  96. data/gems/server/exe/itsi +65 -19
  97. data/gems/server/itsi-server.gemspec +4 -3
  98. data/gems/server/lib/itsi/http_request/response_status_shortcodes.rb +74 -0
  99. data/gems/server/lib/itsi/http_request.rb +116 -17
  100. data/gems/server/lib/itsi/http_response.rb +2 -0
  101. data/gems/server/lib/itsi/passfile.rb +109 -0
  102. data/gems/server/lib/itsi/server/config/dsl.rb +160 -101
  103. data/gems/server/lib/itsi/server/config.rb +58 -23
  104. data/gems/server/lib/itsi/server/default_app/default_app.rb +25 -29
  105. data/gems/server/lib/itsi/server/default_app/index.html +113 -89
  106. data/gems/server/lib/itsi/server/{Itsi.rb → default_config/Itsi-rackup.rb} +1 -1
  107. data/gems/server/lib/itsi/server/default_config/Itsi.rb +107 -0
  108. data/gems/server/lib/itsi/server/grpc/grpc_call.rb +246 -0
  109. data/gems/server/lib/itsi/server/grpc/grpc_interface.rb +100 -0
  110. data/gems/server/lib/itsi/server/grpc/reflection/v1/reflection_pb.rb +26 -0
  111. data/gems/server/lib/itsi/server/grpc/reflection/v1/reflection_services_pb.rb +122 -0
  112. data/gems/server/lib/itsi/server/route_tester.rb +107 -0
  113. data/gems/server/lib/itsi/server/typed_handlers/param_parser.rb +200 -0
  114. data/gems/server/lib/itsi/server/typed_handlers/source_parser.rb +55 -0
  115. data/gems/server/lib/itsi/server/typed_handlers.rb +17 -0
  116. data/gems/server/lib/itsi/server/version.rb +1 -1
  117. data/gems/server/lib/itsi/server.rb +82 -12
  118. data/gems/server/lib/ruby_lsp/itsi/addon.rb +111 -0
  119. data/gems/server/lib/shell_completions/completions.rb +26 -0
  120. data/gems/server/test/helpers/test_helper.rb +2 -1
  121. data/lib/itsi/version.rb +1 -1
  122. data/sandbox/README.md +5 -0
  123. data/sandbox/itsi_file/Gemfile +4 -2
  124. data/sandbox/itsi_file/Gemfile.lock +48 -6
  125. data/sandbox/itsi_file/Itsi.rb +326 -129
  126. data/sandbox/itsi_file/call.json +1 -0
  127. data/sandbox/itsi_file/echo_client/Gemfile +10 -0
  128. data/sandbox/itsi_file/echo_client/Gemfile.lock +27 -0
  129. data/sandbox/itsi_file/echo_client/README.md +95 -0
  130. data/sandbox/itsi_file/echo_client/echo_client.rb +164 -0
  131. data/sandbox/itsi_file/echo_client/gen_proto.sh +17 -0
  132. data/sandbox/itsi_file/echo_client/lib/echo_pb.rb +16 -0
  133. data/sandbox/itsi_file/echo_client/lib/echo_services_pb.rb +29 -0
  134. data/sandbox/itsi_file/echo_client/run_client.rb +64 -0
  135. data/sandbox/itsi_file/echo_client/test_compressions.sh +20 -0
  136. data/sandbox/itsi_file/echo_service_nonitsi/Gemfile +10 -0
  137. data/sandbox/itsi_file/echo_service_nonitsi/Gemfile.lock +79 -0
  138. data/sandbox/itsi_file/echo_service_nonitsi/echo.proto +26 -0
  139. data/sandbox/itsi_file/echo_service_nonitsi/echo_pb.rb +16 -0
  140. data/sandbox/itsi_file/echo_service_nonitsi/echo_services_pb.rb +29 -0
  141. data/sandbox/itsi_file/echo_service_nonitsi/server.rb +52 -0
  142. data/sandbox/itsi_sandbox_async/config.ru +0 -1
  143. data/sandbox/itsi_sandbox_rack/Gemfile.lock +2 -2
  144. data/sandbox/itsi_sandbox_rails/Gemfile +2 -2
  145. data/sandbox/itsi_sandbox_rails/Gemfile.lock +76 -2
  146. data/sandbox/itsi_sandbox_rails/app/controllers/home_controller.rb +15 -0
  147. data/sandbox/itsi_sandbox_rails/config/environments/development.rb +1 -0
  148. data/sandbox/itsi_sandbox_rails/config/environments/production.rb +1 -0
  149. data/sandbox/itsi_sandbox_rails/config/routes.rb +2 -0
  150. data/sandbox/itsi_sinatra/app.rb +0 -1
  151. data/sandbox/static_files/.env +1 -0
  152. data/sandbox/static_files/404.html +25 -0
  153. data/sandbox/static_files/_DSC0102.NEF.jpg +0 -0
  154. data/sandbox/static_files/about.html +68 -0
  155. data/sandbox/static_files/tiny.html +1 -0
  156. data/sandbox/static_files/writebook.zip +0 -0
  157. data/tasks.txt +28 -33
  158. metadata +87 -26
  159. data/crates/itsi_error/src/from.rs +0 -68
  160. data/crates/itsi_server/src/ruby_types/itsi_grpc_request.rs +0 -147
  161. data/crates/itsi_server/src/ruby_types/itsi_grpc_response.rs +0 -19
  162. data/crates/itsi_server/src/server/itsi_service.rs +0 -172
  163. data/crates/itsi_server/src/server/middleware_stack/middlewares/grpc_service.rs +0 -72
  164. data/crates/itsi_server/src/server/types.rs +0 -43
  165. data/gems/server/lib/itsi/server/grpc_interface.rb +0 -213
  166. data/sandbox/itsi_file/public/assets/index.html +0 -1
  167. /data/crates/itsi_server/src/server/{bind_protocol.rs → binds/bind_protocol.rs} +0 -0
  168. /data/crates/itsi_server/src/server/{tls → binds/tls}/locked_dir_cache.rs +0 -0
  169. /data/crates/itsi_server/src/{server → services}/cache_store.rs +0 -0
@@ -1,72 +0,0 @@
1
- use super::MiddlewareLayer;
2
- use crate::{
3
- ruby_types::itsi_grpc_request::ItsiGrpcRequest,
4
- server::{
5
- itsi_service::RequestContext,
6
- types::{HttpRequest, HttpResponse},
7
- },
8
- };
9
- use async_trait::async_trait;
10
- use derive_more::Debug;
11
- use either::Either;
12
- use http::StatusCode;
13
- use itsi_rb_helpers::{HeapVal, HeapValue};
14
- use magnus::{block::Proc, error::Result, value::ReprValue, Symbol, Value};
15
- use std::sync::Arc;
16
-
17
- #[derive(Debug)]
18
- pub struct GrpcService {
19
- service: Arc<HeapValue<Proc>>,
20
- adapter: Value, // Ruby CustomGrpcAdapter object
21
- }
22
-
23
- impl GrpcService {
24
- pub fn from_value(params: HeapVal) -> magnus::error::Result<Self> {
25
- let service = params.funcall::<_, _, Proc>(Symbol::new("[]"), ("service_proc",))?;
26
- let adapter = params.funcall::<_, _, Value>(Symbol::new("[]"), ("adapter",))?;
27
- Ok(GrpcService {
28
- service: Arc::new(service.into()),
29
- adapter,
30
- })
31
- }
32
- }
33
-
34
- #[async_trait]
35
- impl MiddlewareLayer for GrpcService {
36
- async fn before(
37
- &self,
38
- req: HttpRequest,
39
- context: &mut RequestContext,
40
- ) -> Result<Either<HttpRequest, HttpResponse>> {
41
- // Extract gRPC method and service names from the path
42
- let path = req.uri().path();
43
- let parts: Vec<&str> = path.split('/').filter(|s| !s.is_empty()).collect();
44
-
45
- if parts.len() < 2 {
46
- return Ok(Either::Right(HttpResponse::new(StatusCode::BAD_REQUEST)));
47
- }
48
-
49
- let service_name = parts[0].to_string();
50
- let method_name = parts[1].to_string();
51
-
52
- // Get RPC descriptor from the adapter
53
- let rpc_desc = self.adapter.funcall::<_, _, Option<Value>>(
54
- "get_rpc_desc",
55
- (service_name.clone(), method_name.clone()),
56
- )?;
57
-
58
- // Create gRPC request and process it
59
- let (grpc_req, _) = ItsiGrpcRequest::new(
60
- req,
61
- context,
62
- method_name,
63
- service_name,
64
- rpc_desc,
65
- ).await;
66
-
67
- grpc_req
68
- .process(context.ruby(), self.service.clone())
69
- .map_err(|e| e.into())
70
- .map(|_| Either::Right(HttpResponse::new(StatusCode::OK)))
71
- }
72
- }
@@ -1,43 +0,0 @@
1
- use std::convert::Infallible;
2
-
3
- use bytes::Bytes;
4
- use http::{Request, Response};
5
- use http_body_util::combinators::BoxBody;
6
- use hyper::body::Incoming;
7
-
8
- pub type HttpResponse = Response<BoxBody<Bytes, Infallible>>;
9
- pub type HttpRequest = Request<Incoming>;
10
-
11
- pub trait RequestExt {
12
- fn content_type(&self) -> Option<&str>;
13
- fn accept(&self) -> Option<&str>;
14
- fn header(&self, header_name: &str) -> Option<&str>;
15
- fn query_param(&self, query_name: &str) -> Option<&str>;
16
- }
17
-
18
- impl RequestExt for HttpRequest {
19
- fn content_type(&self) -> Option<&str> {
20
- self.headers()
21
- .get("content-type")
22
- .map(|hv| hv.to_str().unwrap_or(""))
23
- }
24
-
25
- fn accept(&self) -> Option<&str> {
26
- self.headers()
27
- .get("accept")
28
- .map(|hv| hv.to_str().unwrap_or(""))
29
- }
30
-
31
- fn header(&self, header_name: &str) -> Option<&str> {
32
- self.headers()
33
- .get(header_name)
34
- .map(|hv| hv.to_str().unwrap_or(""))
35
- }
36
-
37
- fn query_param(&self, query_name: &str) -> Option<&str> {
38
- self.uri()
39
- .query()
40
- .and_then(|query| query.split('&').find(|param| param.starts_with(query_name)))
41
- .map(|param| param.split('=').nth(1).unwrap_or(""))
42
- }
43
- }
@@ -1,213 +0,0 @@
1
- module Itsi
2
- class Server
3
- class GrpcActiveCall
4
- attr_reader :stream, :method_rpc, :output_metadata, :method_name
5
-
6
- def initialize(stream, method_rpc, service_class, method_name)
7
- @stream = stream
8
- @method_rpc = method_rpc
9
- @service_class = service_class
10
- @output_metadata = {}
11
- @method_name = method_name
12
- end
13
- end
14
-
15
- class GrpcInterface
16
- def self.for(services)
17
- interface = new(services)
18
- lambda do |request|
19
- interface.handle_request(request)
20
- end
21
- end
22
-
23
- def initialize(services = [])
24
- @services = {}
25
- register_services(services)
26
- end
27
-
28
- def register_services(services)
29
- services.each do |service|
30
- service_class = service.class
31
- @services[service_class.service_name] = {
32
- implementation: service,
33
- class: service_class
34
- }
35
- end
36
- end
37
-
38
- def handle_request(request)
39
- service_info = @services[request.service_name]
40
- raise "Unknown service: #{request.service_name}" unless service_info
41
-
42
- service_impl = service_info[:implementation]
43
- service_class = service_info[:class]
44
-
45
- method_rpc = RpcDescWrapper.new(service_class, request.content_type, request.method_name)
46
-
47
- active_call = GrpcActiveCall.new(request.stream, method_rpc, service_class, request.method_name)
48
-
49
- if method_rpc.bidi_streamer?
50
- puts "Calling bidirectional streaming handler"
51
- handle_bidi_streaming(active_call, service_impl)
52
- elsif method_rpc.client_streamer?
53
- puts "Calling client streaming handler"
54
- handle_client_streaming(active_call, service_impl)
55
- elsif method_rpc.server_streamer?
56
- puts "Calling server streaming handler"
57
- handle_server_streaming(active_call, service_impl)
58
- elsif method_rpc.request_response?
59
- handle_unary(active_call, service_impl)
60
- end
61
- active_call.stream.send_trailers({ "grpc-status" => "0" })
62
- rescue StandardError => e
63
- active_call.stream.send_trailers({ "grpc-status" => "13", "grpc-message" => e.message })
64
- end
65
-
66
- private
67
-
68
- # Read a framed message from the stream
69
- def read_message(stream)
70
- # Read the gRPC frame header (5 bytes)
71
- header = stream.read(5)
72
- return nil if header.nil? || header.bytesize < 5
73
-
74
- compressed = header.bytes[0] == 1
75
- length = header[1..4].unpack1("N")
76
-
77
- # Read the message body
78
- stream.read(length)
79
- end
80
-
81
- # Send a response
82
- def send_response(active_call, response)
83
- response_data = active_call.method_rpc.marshal_response(response)
84
- send_framed_message(active_call.stream, response_data)
85
- end
86
-
87
- # Send a framed message
88
- def send_framed_message(stream, message_data, compressed = false)
89
- compressed_flag = compressed ? 1 : 0
90
- header = [compressed_flag, message_data.bytesize].pack("CN")
91
-
92
- stream.write(header)
93
- stream.write(message_data)
94
- stream.flush
95
- end
96
-
97
- # Create an enumerator for client streaming requests
98
- def create_request_enum(active_call)
99
- Enumerator.new do |yielder|
100
- loop do
101
- message_data = read_message(active_call.stream)
102
- break if message_data.nil?
103
-
104
- request = active_call.method_rpc.unmarshal_request(message_data)
105
- yielder << request
106
- end
107
- end
108
- end
109
-
110
- # Handlers for different RPC types
111
-
112
- def handle_unary(active_call, service)
113
- # Read the request message
114
- message_data = read_message(active_call.stream)
115
- request = active_call.method_rpc.unmarshal_request(message_data)
116
-
117
- # Call the service implementation
118
- underscore_method = GRPC::GenericService.underscore(active_call.method_name)
119
- response = service.send(underscore_method, request, active_call)
120
-
121
- # Send response
122
- send_response(active_call, response)
123
- end
124
-
125
- def handle_client_streaming(active_call, service)
126
- # Create an enumerable to read the incoming stream
127
- request_enum = create_request_enum(active_call)
128
-
129
- # Call the service implementation
130
- underscore_method = GRPC::GenericService.underscore(active_call.method_name)
131
- response = service.send(underscore_method, request_enum, active_call)
132
-
133
- # Send response
134
- send_response(active_call, response)
135
- end
136
-
137
- def handle_server_streaming(active_call, service)
138
- # Read the request message
139
- message_data = read_message(active_call.stream)
140
- request = active_call.method_rpc.unmarshal_request(message_data)
141
-
142
- # Call the service implementation with a block to handle streaming
143
- underscore_method = GRPC::GenericService.underscore(active_call.method_name)
144
- service.send(underscore_method, request, active_call) do |response|
145
- send_response(active_call, response)
146
- end
147
- end
148
-
149
- def handle_bidi_streaming(active_call, service)
150
- # Create an enumerable to read the incoming stream
151
- request_enum = create_request_enum(active_call)
152
-
153
- # Call the service implementation with a block
154
- underscore_method = GRPC::GenericService.underscore(active_call.method_name)
155
- service.send(underscore_method, request_enum, active_call) do |response|
156
- send_response(active_call, response)
157
- end
158
- end
159
- end
160
-
161
- class RpcDescWrapper
162
- def initialize(service_class, content_type, method_name)
163
- rpc_descs = service_class.rpc_descs
164
- @rpc_desc = rpc_descs[method_name.to_sym]
165
- raise "Method not found: #{method_name}" unless @rpc_desc
166
-
167
- @input_type = @rpc_desc.input
168
- @content_type = content_type
169
- @input_is_stream = @input_type.is_a?(GRPC::RpcDesc::Stream)
170
- @input_type = @input_type.type if @input_is_stream
171
-
172
- @output_type = @rpc_desc.output
173
- @output_is_stream = @output_type.is_a?(GRPC::RpcDesc::Stream)
174
- @output_type = @output_type.type if @output_is_stream
175
-
176
- @client_streamer = @input_is_stream
177
- @server_streamer = @output_is_stream
178
- end
179
-
180
- def client_streamer?
181
- @client_streamer
182
- end
183
-
184
- def server_streamer?
185
- @server_streamer
186
- end
187
-
188
- def bidi_streamer?
189
- @client_streamer && @server_streamer
190
- end
191
-
192
- def request_response?
193
- !@client_streamer && !@server_streamer
194
- end
195
-
196
- def unmarshal_request(data)
197
- if @content_type == "application/json"
198
- @input_type.decode_json(data)
199
- else
200
- @input_type.decode(data)
201
- end
202
- end
203
-
204
- def marshal_response(response)
205
- if @content_type == "application/json"
206
- response.to_json
207
- else
208
- response.to_proto
209
- end
210
- end
211
- end
212
- end
213
- end
@@ -1 +0,0 @@
1
- <h1>Hello World!</h1>