connectrpc-falcon 0.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/LICENSE +21 -0
- data/README.md +352 -0
- data/examples/falcon.rb +31 -0
- data/lib/connectrpc/falcon/completion_join.rb +247 -0
- data/lib/connectrpc/falcon/endpoint.rb +58 -0
- data/lib/connectrpc/falcon/environment.rb +69 -0
- data/lib/connectrpc/falcon/http1.rb +501 -0
- data/lib/connectrpc/falcon/rack_guard.rb +175 -0
- data/lib/connectrpc/falcon/server.rb +121 -0
- data/lib/connectrpc/falcon/version.rb +7 -0
- data/lib/connectrpc/falcon.rb +21 -0
- data/rbs/async_service_0_25/service.rbs +29 -0
- data/sig/connectrpc-falcon.rbs +66 -0
- data/sig/manifest.yaml +2 -0
- metadata +151 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "English"
|
|
4
|
+
|
|
5
|
+
module ConnectRPC
|
|
6
|
+
module Falcon
|
|
7
|
+
class RackGuard
|
|
8
|
+
class Unsupported < StandardError; end
|
|
9
|
+
private_constant :Unsupported
|
|
10
|
+
|
|
11
|
+
class Request < SimpleDelegator
|
|
12
|
+
def initialize(request, reject)
|
|
13
|
+
super(request)
|
|
14
|
+
@reject = reject
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def hijack? = false
|
|
18
|
+
def hijack! = @reject.call
|
|
19
|
+
end
|
|
20
|
+
private_constant :Request
|
|
21
|
+
|
|
22
|
+
def initialize(app)
|
|
23
|
+
raise ArgumentError, "rack_app must be callable" unless app.respond_to?(:call)
|
|
24
|
+
|
|
25
|
+
@app = app
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def call(env)
|
|
29
|
+
attempted = false
|
|
30
|
+
reject = lambda do
|
|
31
|
+
attempted = true
|
|
32
|
+
raise Unsupported, "Socket ownership transfer is unsupported"
|
|
33
|
+
end
|
|
34
|
+
env["rack.hijack?"] = false
|
|
35
|
+
env["rack.hijack"] = reject
|
|
36
|
+
env["protocol.http.request"] = Request.new(env["protocol.http.request"], reject)
|
|
37
|
+
response = @app.call(env)
|
|
38
|
+
status, headers, body = response
|
|
39
|
+
original = guarded_body(body)
|
|
40
|
+
if attempted || status == 101 || headers.keys.any? do |key|
|
|
41
|
+
%w[rack.hijack rack.protocol upgrade].include?(key.downcase)
|
|
42
|
+
end
|
|
43
|
+
return rejected
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
response = [status, headers, completing_body(env, status, headers, original)]
|
|
47
|
+
handed_off = true
|
|
48
|
+
response
|
|
49
|
+
rescue Unsupported
|
|
50
|
+
rejected
|
|
51
|
+
ensure
|
|
52
|
+
original&.close($ERROR_INFO) unless handed_off
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def guarded_body(body)
|
|
58
|
+
if body.is_a?(::Protocol::HTTP::Body::Readable)
|
|
59
|
+
CloseOnce.new(body)
|
|
60
|
+
elsif body
|
|
61
|
+
RackBody.new(body)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def completing_body(env, status, headers, original)
|
|
66
|
+
# Original-body ownership is needed even without callbacks: upstream
|
|
67
|
+
# array conversion retains only the array's contents.
|
|
68
|
+
callbacks = env["rack.response_finished"] || []
|
|
69
|
+
callback = ::Protocol::Rack::Body.completion_callback(callbacks, env, status, headers)
|
|
70
|
+
env["rack.response_finished"] = []
|
|
71
|
+
CompletionBody.new(callback, original) do
|
|
72
|
+
::Protocol::Rack::Body.wrap(env, status, headers.dup, original, env["protocol.http.request"].body)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def rejected
|
|
77
|
+
[501, { "content-type" => "text/plain" }, ["Socket ownership transfer is unsupported"]]
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
private_constant :RackGuard
|
|
81
|
+
|
|
82
|
+
class RackBody < SimpleDelegator
|
|
83
|
+
def close(*)
|
|
84
|
+
return if @closed
|
|
85
|
+
|
|
86
|
+
@closed = true
|
|
87
|
+
__getobj__.close if __getobj__.respond_to?(:close)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
private_constant :RackBody
|
|
91
|
+
|
|
92
|
+
class CompletionBody < ::Protocol::HTTP::Body::Wrapper
|
|
93
|
+
def initialize(callback, original)
|
|
94
|
+
super(::Protocol::HTTP::Body::Buffered.wrap([]))
|
|
95
|
+
@callback = callback
|
|
96
|
+
@original = original
|
|
97
|
+
begin
|
|
98
|
+
@body = yield || @body
|
|
99
|
+
converted = true
|
|
100
|
+
ensure
|
|
101
|
+
close($ERROR_INFO) unless converted
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def rewindable? = false
|
|
106
|
+
def rewind = false
|
|
107
|
+
|
|
108
|
+
# The Rack adapter closes a rejected tuple without passing its exception.
|
|
109
|
+
def close(error = $ERROR_INFO)
|
|
110
|
+
return if @closed
|
|
111
|
+
|
|
112
|
+
@closed = true
|
|
113
|
+
begin
|
|
114
|
+
@callback.call(error)
|
|
115
|
+
ensure
|
|
116
|
+
begin
|
|
117
|
+
super
|
|
118
|
+
ensure
|
|
119
|
+
@original&.close(error)
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
private_constant :CompletionBody
|
|
125
|
+
|
|
126
|
+
class ListenerApplication
|
|
127
|
+
def initialize(application, scheme)
|
|
128
|
+
@application = application
|
|
129
|
+
@scheme = scheme
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def publication?(request) = @application.send(:publication?, request)
|
|
133
|
+
def http1_streaming_route?(request) = @application.send(:http1_streaming_route?, request)
|
|
134
|
+
private :publication?, :http1_streaming_route?
|
|
135
|
+
def admission_response(request) = @application.admission_response(request)
|
|
136
|
+
|
|
137
|
+
def call(request, lifecycle: nil, publication: nil, resource: nil)
|
|
138
|
+
request.scheme ||= @scheme
|
|
139
|
+
if request.method == "CONNECT" || request.protocol || request.headers["upgrade"]
|
|
140
|
+
lifecycle&.host_rejected!
|
|
141
|
+
return ::Protocol::HTTP::Response[501, {}, nil]
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
response = if publication
|
|
145
|
+
publication.on_publish { |head| head.body = CloseOnce.new(head.body) if head&.body }
|
|
146
|
+
@application.call_with_publication(request, lifecycle: lifecycle, publication: publication,
|
|
147
|
+
resource: resource)
|
|
148
|
+
else
|
|
149
|
+
@application.call(request, lifecycle: lifecycle)
|
|
150
|
+
end
|
|
151
|
+
return if publication && response.nil?
|
|
152
|
+
|
|
153
|
+
if response.nil? || response.status == 101 || response.protocol
|
|
154
|
+
response&.close
|
|
155
|
+
return ::Protocol::HTTP::Response[501, {}, nil]
|
|
156
|
+
end
|
|
157
|
+
response.body = CloseOnce.new(response.body) if response.body
|
|
158
|
+
response
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
private_constant :ListenerApplication
|
|
162
|
+
|
|
163
|
+
# Upstream write ensure and cancellation can both close a body. Mark before
|
|
164
|
+
# entering callbacks so a blocked rack.response_finished cannot reenter.
|
|
165
|
+
class CloseOnce < ::Protocol::HTTP::Body::Wrapper
|
|
166
|
+
def close(error = nil)
|
|
167
|
+
return if @closed
|
|
168
|
+
|
|
169
|
+
@closed = true
|
|
170
|
+
super
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
private_constant :CloseOnce
|
|
174
|
+
end
|
|
175
|
+
end
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ConnectRPC
|
|
4
|
+
module Falcon
|
|
5
|
+
class Server < ::Falcon::Server
|
|
6
|
+
def initialize(server:, endpoint:, rack_app: nil, cache: false, tls: nil, tls_provider: nil,
|
|
7
|
+
utilization_registry: nil, max_connections: 128, max_requests: 128,
|
|
8
|
+
handshake_timeout: 10, idle_timeout: 60, refresh_interval: 60,
|
|
9
|
+
refresh_jitter: 0.1, refresh_timeout: 10, on_tls_error: nil)
|
|
10
|
+
raise ArgumentError, "cache must be true or false" unless [true, false].include?(cache)
|
|
11
|
+
|
|
12
|
+
configured = if endpoint.is_a?(::IO::Endpoint::BoundEndpoint)
|
|
13
|
+
endpoint.endpoint
|
|
14
|
+
else
|
|
15
|
+
endpoint
|
|
16
|
+
end
|
|
17
|
+
unless configured.is_a?(Endpoint) && (configured.scheme == "https") == (!tls.nil? || !tls_provider.nil?)
|
|
18
|
+
raise ArgumentError, "Listener scheme and TLS configuration must agree"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
fallback = ::Falcon::Server.rack_middleware(RackGuard.new(rack_app), cache: cache) unless rack_app.nil?
|
|
22
|
+
application = ::ConnectRPC::Async::Application.new(server: server, fallback: fallback)
|
|
23
|
+
listener_application = ListenerApplication.new(application, configured.scheme)
|
|
24
|
+
@listener_application = listener_application
|
|
25
|
+
utilization_registry ||= ::Async::Utilization::Registry.new
|
|
26
|
+
@connection_total = utilization_registry.metric(:connections_total)
|
|
27
|
+
@connection_active = utilization_registry.metric(:connections_active)
|
|
28
|
+
@request_total = utilization_registry.metric(:requests_total)
|
|
29
|
+
@request_active = utilization_registry.metric(:requests_active)
|
|
30
|
+
@session = ::ConnectRPC::Async::ServerSession.new(
|
|
31
|
+
application: self, lifecycle_factory: application.method(:start_call),
|
|
32
|
+
tls: tls, tls_provider: tls_provider,
|
|
33
|
+
max_connections: max_connections, max_requests: max_requests,
|
|
34
|
+
handshake_timeout: handshake_timeout, idle_timeout: idle_timeout,
|
|
35
|
+
refresh_interval: refresh_interval, refresh_jitter: refresh_jitter,
|
|
36
|
+
refresh_timeout: refresh_timeout, on_tls_error: on_tls_error,
|
|
37
|
+
alpn_protocols: %w[h2 http/1.1], http1: HTTP1Resource.method(:new),
|
|
38
|
+
stop_accepting: method(:stop_accepting), on_request_rejected: -> { @request_total.increment }
|
|
39
|
+
)
|
|
40
|
+
# Preserve parent-bound descriptors while installing a worker-local
|
|
41
|
+
# accept wrapper through IO::Endpoint's supported wrapper option.
|
|
42
|
+
@accept_wrapper = AcceptWrapper.new(@session, on_reject: -> { @connection_total.increment })
|
|
43
|
+
endpoint = @owned_bound = endpoint.bound unless endpoint.is_a?(::IO::Endpoint::BoundEndpoint)
|
|
44
|
+
wrapped = endpoint.with(wrapper: @accept_wrapper)
|
|
45
|
+
super(listener_application, wrapped, protocol: configured.protocol, scheme: configured.scheme,
|
|
46
|
+
utilization_registry: utilization_registry)
|
|
47
|
+
rescue StandardError
|
|
48
|
+
@session&.abort
|
|
49
|
+
raise
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def run
|
|
53
|
+
@session.start
|
|
54
|
+
@run_task = super
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def accept(peer, _address, **)
|
|
58
|
+
@connection_total.increment
|
|
59
|
+
@session.schedule { @connection_active.track { peer.wait_closed } }
|
|
60
|
+
peer.serve
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def close(grace: 5)
|
|
64
|
+
@session.close(grace: grace)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def abort = @session.abort
|
|
68
|
+
|
|
69
|
+
def publication?(request) = @listener_application.send(:publication?, request)
|
|
70
|
+
def http1_streaming_route?(request) = @listener_application.send(:http1_streaming_route?, request)
|
|
71
|
+
private :publication?, :http1_streaming_route?
|
|
72
|
+
def admission_response(request) = @listener_application.admission_response(request)
|
|
73
|
+
|
|
74
|
+
def call_with_publication(request, publication:, lifecycle: nil, resource: nil)
|
|
75
|
+
publication.on_publish do |response|
|
|
76
|
+
response.body = ::Falcon::Body::RequestFinished.new(response.body, @request_active) if response&.body
|
|
77
|
+
end
|
|
78
|
+
call_native(request, lifecycle: lifecycle, publication: publication, resource: resource)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def call(request, lifecycle: nil)
|
|
82
|
+
call_native(request, lifecycle: lifecycle)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def call_native(request, lifecycle: nil, publication: nil, resource: nil)
|
|
86
|
+
@request_total.increment
|
|
87
|
+
@request_active.increment
|
|
88
|
+
response = @listener_application.call(request, lifecycle: lifecycle, publication: publication,
|
|
89
|
+
resource: resource)
|
|
90
|
+
if response&.body && !publication
|
|
91
|
+
# Empty bodies can still own completion callbacks. Preserve their
|
|
92
|
+
# wire length while retaining the metric until close finishes.
|
|
93
|
+
response.body = ::Falcon::Body::RequestFinished.new(response.body, @request_active)
|
|
94
|
+
wrapped = true
|
|
95
|
+
end
|
|
96
|
+
response
|
|
97
|
+
ensure
|
|
98
|
+
retained = publication && (publication.published? || response&.body)
|
|
99
|
+
@request_active.decrement unless wrapped || retained
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
private :call_native
|
|
103
|
+
|
|
104
|
+
def reload_tls(**) = @session.reload_tls(**)
|
|
105
|
+
def refresh_tls = @session.refresh_tls
|
|
106
|
+
def drain_tls(**) = @session.drain_tls(**)
|
|
107
|
+
def tls_generation = @session.tls_generation
|
|
108
|
+
def tls_status = @session.tls_status
|
|
109
|
+
def peer_certificate = @session.peer_certificate
|
|
110
|
+
|
|
111
|
+
private
|
|
112
|
+
|
|
113
|
+
def stop_accepting
|
|
114
|
+
# Stop this worker's accept tasks after session validation. Accepted
|
|
115
|
+
# peers have an independent lifetime; parent-bound listeners stay open.
|
|
116
|
+
@accept_wrapper&.stop
|
|
117
|
+
@owned_bound&.close
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "connectrpc/async"
|
|
4
|
+
require_relative "falcon/version"
|
|
5
|
+
require "falcon/server"
|
|
6
|
+
require "falcon/environment/server"
|
|
7
|
+
require "async/http/endpoint"
|
|
8
|
+
require "io/endpoint/wrapper"
|
|
9
|
+
require "delegate"
|
|
10
|
+
|
|
11
|
+
module ConnectRPC
|
|
12
|
+
# Explicit optional listener. Falcon owns process supervision and accepts.
|
|
13
|
+
module Falcon
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
require_relative "falcon/endpoint"
|
|
18
|
+
require_relative "falcon/rack_guard"
|
|
19
|
+
require_relative "falcon/http1"
|
|
20
|
+
require_relative "falcon/server"
|
|
21
|
+
require_relative "falcon/environment"
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Explicit opt-in for Falcon 0.57.0 / async-service 0.25.0 service configuration.
|
|
2
|
+
# These are the documented ConnectRPC DSL forms, not general method_missing.
|
|
3
|
+
module Async
|
|
4
|
+
module Service
|
|
5
|
+
class Loader
|
|
6
|
+
def service: (?String?) { () [self: Environment::Builder] -> void } -> void
|
|
7
|
+
end
|
|
8
|
+
class Environment
|
|
9
|
+
class Builder < BasicObject
|
|
10
|
+
def include: (Module) -> void
|
|
11
|
+
def url: (String) -> void
|
|
12
|
+
| () { () [self: ConnectRPC::Falcon::Environment] -> String } -> void
|
|
13
|
+
def count: (Integer) -> void
|
|
14
|
+
| () { () [self: ConnectRPC::Falcon::Environment] -> Integer } -> void
|
|
15
|
+
def prepare!: () { (Object) [self: ConnectRPC::Falcon::Environment] -> void } -> void
|
|
16
|
+
def connectrpc_server: (ConnectRPC::Server) -> void
|
|
17
|
+
| () { () [self: ConnectRPC::Falcon::Environment] -> ConnectRPC::Server } -> void
|
|
18
|
+
def rack_app: ((ConnectRPC::Falcon::_RackFallback | ^(Hash[String, Object]) -> ConnectRPC::Falcon::rack_response)?) -> void
|
|
19
|
+
| () { () [self: ConnectRPC::Falcon::Environment] -> (ConnectRPC::Falcon::_RackFallback | ^(Hash[String, Object]) -> ConnectRPC::Falcon::rack_response)? } -> void
|
|
20
|
+
def tls: (ConnectRPC::Async::tls?) -> void
|
|
21
|
+
| () { () [self: ConnectRPC::Falcon::Environment] -> ConnectRPC::Async::tls? } -> void
|
|
22
|
+
def tls_provider: ((ConnectRPC::Async::_TLSProvider | ^() -> ConnectRPC::Async::tls_snapshot)?) -> void
|
|
23
|
+
| () { () [self: ConnectRPC::Falcon::Environment] -> (ConnectRPC::Async::_TLSProvider | ^() -> ConnectRPC::Async::tls_snapshot)? } -> void
|
|
24
|
+
def server_options: (ConnectRPC::Falcon::server_options) -> void
|
|
25
|
+
| () { () [self: ConnectRPC::Falcon::Environment] -> ConnectRPC::Falcon::server_options } -> void
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
module ConnectRPC
|
|
2
|
+
module Falcon
|
|
3
|
+
VERSION: String
|
|
4
|
+
# Endpoint and task/socket objects expose only their consumed capabilities.
|
|
5
|
+
interface _BoundEndpoint
|
|
6
|
+
def endpoint: () -> Endpoint
|
|
7
|
+
def close: () -> void
|
|
8
|
+
end
|
|
9
|
+
class Endpoint
|
|
10
|
+
def self.parse: (String, ?Object?, **Object) -> Endpoint
|
|
11
|
+
def initialize: (URI::Generic, ?Object?, **Object) -> void
|
|
12
|
+
def scheme: () -> String
|
|
13
|
+
def bound: () -> _BoundEndpoint
|
|
14
|
+
def with: (**Object) -> Endpoint
|
|
15
|
+
end
|
|
16
|
+
# Keep this small Rack capability local: Falcon does not depend on the
|
|
17
|
+
# connectrpc-rack gem. Its structural shapes also accept Rack::_App values.
|
|
18
|
+
type rack_headers = Hash[String, String | Array[String]]
|
|
19
|
+
type rack_response = [Integer, rack_headers, _RackBody | _RackCallableBody]
|
|
20
|
+
type server_options = { ?cache: bool, ?max_connections: Integer, ?max_requests: Integer, ?handshake_timeout: Numeric, ?idle_timeout: Numeric?, ?refresh_interval: Numeric, ?refresh_jitter: Numeric, ?refresh_timeout: Numeric, ?on_tls_error: (Async::_TLSErrorHandler | ^(Async::tls_event) -> void)? }
|
|
21
|
+
interface _RackBody
|
|
22
|
+
def each: () { (String) -> void } -> void
|
|
23
|
+
end
|
|
24
|
+
interface _RackStream
|
|
25
|
+
def read: (?nil, ?String?) -> String
|
|
26
|
+
| (Integer?, ?String?) -> String?
|
|
27
|
+
def write: (String) -> Integer
|
|
28
|
+
# Protocol::HTTP returns a byte count; ordinary IO returns itself.
|
|
29
|
+
def <<: (String) -> (Integer | self)
|
|
30
|
+
def flush: () -> void
|
|
31
|
+
def close: () -> void
|
|
32
|
+
def close_read: () -> void
|
|
33
|
+
def close_write: () -> void
|
|
34
|
+
def closed?: () -> bool
|
|
35
|
+
end
|
|
36
|
+
interface _RackCallableBody
|
|
37
|
+
def call: (_RackStream) -> void
|
|
38
|
+
end
|
|
39
|
+
interface _RackFallback
|
|
40
|
+
def call: (Hash[String, Object]) -> rack_response
|
|
41
|
+
end
|
|
42
|
+
class Server
|
|
43
|
+
def initialize: (server: ConnectRPC::Server, endpoint: Endpoint | _BoundEndpoint, ?rack_app: (_RackFallback | ^(Hash[String, Object]) -> rack_response)?, ?cache: bool, ?tls: Async::tls?, ?tls_provider: (Async::_TLSProvider | ^() -> Async::tls_snapshot)?, ?utilization_registry: Object?, ?max_connections: Integer, ?max_requests: Integer, ?handshake_timeout: Numeric, ?idle_timeout: Numeric?, ?refresh_interval: Numeric, ?refresh_jitter: Numeric, ?refresh_timeout: Numeric, ?on_tls_error: (Async::_TLSErrorHandler | ^(Async::tls_event) -> void)?) -> void
|
|
44
|
+
def run: () -> Async::_Task
|
|
45
|
+
def call: (Async::_Request, ?lifecycle: Instrumentation::Handle?) -> Async::_Response?
|
|
46
|
+
def close: (?grace: Numeric) -> bool?
|
|
47
|
+
def abort: () -> Async::ServerSession
|
|
48
|
+
def reload_tls: (certificate_chain: Array[String], private_key: String, client_ca: Array[String]?) -> Integer
|
|
49
|
+
def refresh_tls: () -> Integer
|
|
50
|
+
def drain_tls: (?grace: Numeric) -> bool
|
|
51
|
+
def tls_generation: () -> Integer?
|
|
52
|
+
def tls_status: () -> Async::tls_status
|
|
53
|
+
def peer_certificate: () -> OpenSSL::X509::Certificate?
|
|
54
|
+
end
|
|
55
|
+
module Environment
|
|
56
|
+
def service_class: () -> Class
|
|
57
|
+
def endpoint: () -> Endpoint
|
|
58
|
+
def rack_app: () -> (_RackFallback | ^(Hash[String, Object]) -> rack_response)?
|
|
59
|
+
def tls: () -> Async::tls?
|
|
60
|
+
def tls_provider: () -> (Async::_TLSProvider | ^() -> Async::tls_snapshot)?
|
|
61
|
+
def server_options: () -> server_options
|
|
62
|
+
def connectrpc_server: () -> ConnectRPC::Server
|
|
63
|
+
def make_server: (Endpoint | _BoundEndpoint) -> Server
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
data/sig/manifest.yaml
ADDED
metadata
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: connectrpc-falcon
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- jimeh
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 2026-11-15 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: connectrpc-async
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: 0.1.0
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: 0.1.0
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: falcon
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: 0.57.0
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: 0.57.0
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: protocol-rack
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: 0.23.0
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: 0.23.0
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: async-service
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: 0.25.0
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: 0.25.0
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: async-container
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: 0.38.0
|
|
75
|
+
type: :runtime
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: 0.38.0
|
|
82
|
+
- !ruby/object:Gem::Dependency
|
|
83
|
+
name: async-utilization
|
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - "~>"
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: 0.5.0
|
|
89
|
+
type: :runtime
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - "~>"
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: 0.5.0
|
|
96
|
+
- !ruby/object:Gem::Dependency
|
|
97
|
+
name: protocol-http1
|
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - "~>"
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: 0.41.1
|
|
103
|
+
type: :runtime
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - "~>"
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: 0.41.1
|
|
110
|
+
executables: []
|
|
111
|
+
extensions: []
|
|
112
|
+
extra_rdoc_files: []
|
|
113
|
+
files:
|
|
114
|
+
- LICENSE
|
|
115
|
+
- README.md
|
|
116
|
+
- examples/falcon.rb
|
|
117
|
+
- lib/connectrpc/falcon.rb
|
|
118
|
+
- lib/connectrpc/falcon/completion_join.rb
|
|
119
|
+
- lib/connectrpc/falcon/endpoint.rb
|
|
120
|
+
- lib/connectrpc/falcon/environment.rb
|
|
121
|
+
- lib/connectrpc/falcon/http1.rb
|
|
122
|
+
- lib/connectrpc/falcon/rack_guard.rb
|
|
123
|
+
- lib/connectrpc/falcon/server.rb
|
|
124
|
+
- lib/connectrpc/falcon/version.rb
|
|
125
|
+
- rbs/async_service_0_25/service.rbs
|
|
126
|
+
- sig/connectrpc-falcon.rbs
|
|
127
|
+
- sig/manifest.yaml
|
|
128
|
+
homepage: https://github.com/jimeh/connectrpc-ruby
|
|
129
|
+
licenses:
|
|
130
|
+
- MIT
|
|
131
|
+
metadata:
|
|
132
|
+
allowed_push_host: https://rubygems.org
|
|
133
|
+
rubygems_mfa_required: 'true'
|
|
134
|
+
rdoc_options: []
|
|
135
|
+
require_paths:
|
|
136
|
+
- lib
|
|
137
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
138
|
+
requirements:
|
|
139
|
+
- - ">="
|
|
140
|
+
- !ruby/object:Gem::Version
|
|
141
|
+
version: '3.4'
|
|
142
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
143
|
+
requirements:
|
|
144
|
+
- - ">="
|
|
145
|
+
- !ruby/object:Gem::Version
|
|
146
|
+
version: '0'
|
|
147
|
+
requirements: []
|
|
148
|
+
rubygems_version: 3.6.9
|
|
149
|
+
specification_version: 4
|
|
150
|
+
summary: Optional Falcon worker hosting for ConnectRPC unary
|
|
151
|
+
test_files: []
|