anycable-core 1.4.0.rc.1 → 1.4.0.rc.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 694b7faf93867160692c90662d8fd65af0e5f7303688ae1fe387b3bae534bb00
4
- data.tar.gz: 92f687a99d704322486551e9d29d82e97a2f15e63c3e8e0a2c592e5ebc58cae2
3
+ metadata.gz: 25b7f4021fa0e158fbd28f5213545756750ab8222ed43c25e770bb4031083f9e
4
+ data.tar.gz: a2f5760a88c80ed483d1de2b953558f2ac4f66b71d55a2e1745b52f1ce359f3d
5
5
  SHA512:
6
- metadata.gz: aea5bfe49b5d0d0a818536cde34cc9620eb8b39bf07b526a81b62e3dad45a304f00127c1158f741487efe309004b5ae13fdade338533416c7cbbfe0b275f4fda
7
- data.tar.gz: 408901c32e70e72d3b69f183dea2475c3b8b0a02b7c355a453f0d46d4d698cb9b2b772d106ddfa3f6f50aa1f6f367f48f6e8987c4df1c3c6abc2670d104561e9
6
+ metadata.gz: f18b8269a526c7cebedcd0146f12a3dc43e1aa3c0af23e3bbe147f632758bfc1b3102e972f6416b1a1b7228cfcc9a9c8f90ba1b22a0d173a8f46ce392777d93f
7
+ data.tar.gz: 36a767ee9034deefbecc0696843e65c1c1773ce8e58cf5898a4a4fd4bd44784fbf7cd8a4a7ba5d6bcb84767b1466df465d8c26b2ac634aaa55aa311f2e84734b
data/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.4.0.rc.2 (2023-07-03)
6
+
7
+ - Add HTTP RPC support. ([@palkan][])
8
+
5
9
  ## 1.4.0.rc.1 (2023-06-01)
6
10
 
7
11
  - Add `redisx` broadcast adapter. ([@palkan][])
@@ -53,6 +53,9 @@ module AnyCable
53
53
  http_health_port: nil,
54
54
  http_health_path: "/health",
55
55
 
56
+ ### HTTP RPC options
57
+ http_rpc_secret: nil,
58
+
56
59
  ### Misc options
57
60
  version_check_enabled: true,
58
61
  sid_header_enabled: true
@@ -110,6 +113,9 @@ module AnyCable
110
113
  HTTP PUB/SUB
111
114
  --http-broadcast-url HTTP pub/sub endpoint URL, default: "http://localhost:8090/_broadcast"
112
115
  --http-broadcast-secret HTTP pub/sub authorization secret, default: <none> (disabled)
116
+
117
+ HTTP RPC
118
+ --http-rpc-secret HTTP RPC authorization secret, default: <none> (disabled)
113
119
  TXT
114
120
 
115
121
  # Build Redis parameters
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AnyCable
4
+ module HTTRPC
5
+ class Server
6
+ def initialize(token: AnyCable.config.http_rpc_secret)
7
+ @token = token
8
+ end
9
+
10
+ def call(env)
11
+ if env["REQUEST_METHOD"] != "POST"
12
+ return [404, {}, ["Not found"]]
13
+ end
14
+
15
+ if token && env["HTTP_AUTHORIZATION"] != "Bearer #{token}"
16
+ return [401, {}, ["Unauthorized"]]
17
+ end
18
+
19
+ rpc_command = env["PATH_INFO"].sub(%r{^/}, "").to_sym
20
+
21
+ # check if command is supported and return 404 if not
22
+ return [404, {}, ["Not found"]] unless AnyCable.rpc_handler.supported?(rpc_command)
23
+
24
+ # read request body and it's empty, return 422
25
+ request_body = env["rack.input"].read
26
+ return [422, {}, ["Empty request body"]] if request_body.empty?
27
+
28
+ payload =
29
+ case rpc_command
30
+ when :connect then AnyCable::ConnectionRequest.decode_json(request_body)
31
+ when :disconnect then AnyCable::DisconnectRequest.decode_json(request_body)
32
+ when :command then AnyCable::CommandMessage.decode_json(request_body)
33
+ end
34
+
35
+ return [422, {}, ["Invalid request body"]] if payload.nil?
36
+
37
+ response = AnyCable.rpc_handler.handle(rpc_command, payload, build_meta(env))
38
+
39
+ [200, {}, [response.to_json({format_enums_as_integers: true})]]
40
+ rescue JSON::ParserError, ArgumentError => e
41
+ [422, {}, ["Invalid request body: #{e.message}"]]
42
+ end
43
+
44
+ private
45
+
46
+ attr_reader :token
47
+
48
+ def build_meta(env)
49
+ # `x-anycable-meta-var` -> `meta["var"]`
50
+ env.each_with_object({}) do |(k, v), meta|
51
+ next unless k.start_with?("HTTP_X_ANYCABLE_META_")
52
+ meta[k.sub(%r{^HTTP_X_ANYCABLE_META_}, "").downcase] = v
53
+ meta
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -23,6 +23,10 @@ module AnyCable
23
23
  end
24
24
  end
25
25
 
26
+ def supported?(cmd)
27
+ %i[connect disconnect command].include?(cmd)
28
+ end
29
+
26
30
  private
27
31
 
28
32
  attr_reader :commands, :middleware
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AnyCable
4
- VERSION = "1.4.0.rc.1"
4
+ VERSION = "1.4.0.rc.2"
5
5
  end
data/lib/anycable.rb CHANGED
@@ -16,6 +16,8 @@ require "anycable/socket"
16
16
  require "anycable/rpc"
17
17
  require "anycable/health_server"
18
18
 
19
+ require "anycable/httrpc/server"
20
+
19
21
  # AnyCable allows to use any websocket service (written in any language) as a replacement
20
22
  # for ActionCable server.
21
23
  #
@@ -41,6 +41,8 @@ module AnyCable
41
41
  def http_health_port=: (Integer) -> void
42
42
  def http_health_path: () -> String
43
43
  def http_health_path=: (String) -> void
44
+ def http_rpc_secret: () -> String
45
+ def http_rpc_secret=: (String) -> void
44
46
  def version_check_enabled: () -> bool
45
47
  def version_check_enabled=: (bool) -> void
46
48
  def version_check_enabled?: () -> bool
@@ -0,0 +1,11 @@
1
+ module AnyCable
2
+ module HTTRPC
3
+ class Server
4
+ def initialize: (?token: String?) -> void
5
+ def call: (Hash[String, untyped] env) -> [Integer, Hash[String, String], Array[String]]
6
+ private
7
+ attr_reader token: String?
8
+ def build_meta: (Hash[String, untyped] env) -> Hash[String, String]
9
+ end
10
+ end
11
+ end
@@ -15,6 +15,7 @@ module AnyCable
15
15
 
16
16
  def initialize: (?middleware: MiddlewareChain) -> void
17
17
  def handle: (Symbol cmd, rpcRequest data, ?rpcMetadata meta) -> rpcResponse
18
+ def supported?: (Symbol cmd) -> bool
18
19
 
19
20
  private
20
21
 
data/sig/anycable/rpc.rbs CHANGED
@@ -73,6 +73,7 @@ module AnyCable
73
73
  class ConnectionRequest
74
74
  include _WithEnv
75
75
 
76
+ def self.decode_json: (String) -> instance
76
77
  %a{rbs:test:skip} def initialize: (?env: Env) -> void
77
78
  def to_h: () -> Hash[Symbol, untyped]
78
79
  end
@@ -95,11 +96,14 @@ module AnyCable
95
96
  ) -> void
96
97
 
97
98
  def to_h: () -> Hash[Symbol, untyped]
99
+ def to_json: (?Hash[Symbol, untyped] options) -> String
98
100
  end
99
101
 
100
102
  class CommandMessage
101
103
  include _WithEnv
102
104
 
105
+ def self.decode_json: (String) -> instance
106
+
103
107
  attr_accessor command: String
104
108
  attr_accessor identifier: String
105
109
  attr_accessor connection_identifiers: String
@@ -139,11 +143,14 @@ module AnyCable
139
143
  ) -> void
140
144
 
141
145
  def to_h: () -> Hash[Symbol, untyped]
146
+ def to_json: (?Hash[Symbol, untyped] options) -> String
142
147
  end
143
148
 
144
149
  class DisconnectRequest
145
150
  include _WithEnv
146
151
 
152
+ def self.decode_json: (String) -> instance
153
+
147
154
  attr_accessor identifiers: String
148
155
  attr_accessor subscriptions: Array[String]
149
156
 
@@ -159,6 +166,7 @@ module AnyCable
159
166
 
160
167
  %a{rbs:test:skip} def initialize: (status: rpcStatus, ?error_msg: String) -> void
161
168
  def to_h: () -> Hash[Symbol, untyped]
169
+ def to_json: (?Hash[Symbol, untyped] options) -> String
162
170
  end
163
171
 
164
172
  type rpcRequest = ConnectionRequest | DisconnectRequest | CommandMessage
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: anycable-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0.rc.1
4
+ version: 1.4.0.rc.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - palkan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-01 00:00:00.000000000 Z
11
+ date: 2023-07-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: anyway_config
@@ -216,6 +216,7 @@ files:
216
216
  - lib/anycable/grpc_kit/health_services_pb.rb
217
217
  - lib/anycable/grpc_kit/server.rb
218
218
  - lib/anycable/health_server.rb
219
+ - lib/anycable/httrpc/server.rb
219
220
  - lib/anycable/middleware.rb
220
221
  - lib/anycable/middleware_chain.rb
221
222
  - lib/anycable/middlewares/check_version.rb
@@ -246,6 +247,7 @@ files:
246
247
  - sig/anycable/grpc/rpc_services_pb.rbs
247
248
  - sig/anycable/grpc/server.rbs
248
249
  - sig/anycable/health_server.rbs
250
+ - sig/anycable/httrpc/server.rbs
249
251
  - sig/anycable/middleware.rbs
250
252
  - sig/anycable/middleware_chain.rbs
251
253
  - sig/anycable/middlewares/check_version.rbs