anycable-rails 0.6.5 → 1.0.0.rc3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +28 -110
- data/MIT-LICENSE +1 -1
- data/README.md +34 -37
- data/lib/action_cable/subscription_adapter/any_cable.rb +2 -1
- data/lib/anycable/rails.rb +37 -2
- data/lib/anycable/rails/actioncable/channel.rb +4 -0
- data/lib/anycable/rails/actioncable/connection.rb +72 -50
- data/lib/anycable/rails/actioncable/connection/persistent_session.rb +34 -0
- data/lib/anycable/rails/actioncable/connection/serializable_identification.rb +42 -0
- data/lib/anycable/rails/actioncable/remote_connections.rb +11 -0
- data/lib/anycable/rails/actioncable/testing.rb +35 -0
- data/lib/anycable/rails/channel_state.rb +46 -0
- data/lib/anycable/rails/compatibility.rb +7 -10
- data/lib/anycable/rails/compatibility/rubocop.rb +0 -1
- data/lib/anycable/rails/compatibility/rubocop/config/default.yml +3 -1
- data/lib/anycable/rails/compatibility/rubocop/cops/anycable/instance_vars.rb +1 -1
- data/lib/anycable/rails/compatibility/rubocop/cops/anycable/stream_from.rb +4 -4
- data/lib/anycable/rails/config.rb +8 -4
- data/lib/anycable/rails/rack.rb +56 -0
- data/lib/anycable/rails/railtie.rb +28 -13
- data/lib/anycable/rails/refinements/subscriptions.rb +1 -1
- data/lib/anycable/rails/session_proxy.rb +79 -0
- data/lib/anycable/rails/version.rb +1 -1
- data/lib/generators/anycable/download/USAGE +14 -0
- data/lib/generators/anycable/download/download_generator.rb +83 -0
- data/lib/generators/anycable/setup/USAGE +2 -0
- data/lib/generators/anycable/setup/setup_generator.rb +266 -0
- data/lib/generators/anycable/setup/templates/Procfile.dev +3 -0
- data/lib/generators/anycable/setup/templates/config/anycable.yml.tt +43 -0
- data/lib/generators/anycable/setup/templates/config/cable.yml.tt +11 -0
- data/lib/generators/anycable/setup/templates/config/initializers/anycable.rb.tt +9 -0
- data/lib/generators/anycable/with_os_helpers.rb +55 -0
- metadata +45 -30
- data/lib/anycable/rails/compatibility/rubocop/cops/anycable/remote_disconnect.rb +0 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3ebb4dc7b8483998770f7168cc8884d8a56a0e5376e04550b2f98b1d11046cdf
|
4
|
+
data.tar.gz: 29a21773378af2c3bcc6cd3265d58d028a7bef7b8fc2be13bafda3f54677d8b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cde255681a0348c2edc41fc3130d632f8f17ea02937691b62a388f8a73a699b9e1669e9c7ea55f1dad3a74b6e0d289a3a07feda97adbcbbfcc5d1e316213a704
|
7
|
+
data.tar.gz: 88c80148d66a610472bf8a129a381198d044c89884a800f4209c19f67a6cf527763620bfd804b03cbddb0f6752b6e69c8065e4bfbf1c33da11e66cb7def49688
|
data/CHANGELOG.md
CHANGED
@@ -2,141 +2,59 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
-
## 0.
|
5
|
+
## 1.0.0.rc3 (2020-06-24)
|
6
6
|
|
7
|
-
- Make
|
7
|
+
- Make AnyCable patches compatible with Action Cable testing. ([@palkan][])
|
8
8
|
|
9
|
-
|
10
|
-
couldn't resolve the channel class. Now we return `Channel not found: <name>`.
|
9
|
+
- Do not add localhost `redis_url` to `anycable.yml` when Docker development method is chosen in `anycable:setup`. ([@palkan][])
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
- Add ability to develop the gem with Docker. ([@bibendi][])
|
15
|
-
|
16
|
-
## 0.6.4 (2019-06-26) 👶
|
17
|
-
|
18
|
-
- Fix Compatibility bug when using with AnyCable. ([@palkan][])
|
19
|
-
|
20
|
-
Compatibility patching (with `prepend` + `super`) conflicted with
|
21
|
-
the `ActionCable::Channel::Base` patching in the core functionality (which uses `alias`).
|
22
|
-
|
23
|
-
See [#95](https://github.com/anycable/anycable-rails/issues/95).
|
24
|
-
|
25
|
-
## 0.6.3 (2019-03-26)
|
26
|
-
|
27
|
-
- Fix connection factory reloading for development sake. ([@sponomarev][])
|
28
|
-
|
29
|
-
- Add `:anycable` subscription adapter alias. ([@sponomarev][])
|
30
|
-
|
31
|
-
- Don't set AnyCable connection factory for incompatible adapter ([@sponomarev][])
|
32
|
-
|
33
|
-
`anycable` server won't start with unpatched vanilla `ApplicationCable::Connection`.
|
34
|
-
|
35
|
-
Motivation in [#74](https://github.com/anycable/anycable-rails/issues/74).
|
36
|
-
|
37
|
-
- Fix instance detection inside complex cases in compatibility cops ([@sponomarev][])
|
38
|
-
|
39
|
-
## 0.6.2 (2019-01-10)
|
40
|
-
|
41
|
-
- Fixed `anycable` 0.6.1 compatibility. ([@palkan][])
|
42
|
-
|
43
|
-
- Broadcast logs to STDOUT in development only when server is running. ([@palkan][])
|
44
|
-
|
45
|
-
Fixes #59.
|
46
|
-
|
47
|
-
## 0.6.1 (2018-11-15)
|
48
|
-
|
49
|
-
- Fix regression introduced in [e64a366e](https://github.com/anycable/anycable-rails/commit/e64a366ea21293925e0c5c0b8e6595d65d5d0981#diff-fd0e56a6e825002eac978507c3581af7R14) ([@palkan][])
|
50
|
-
|
51
|
-
`Connection` patch could be loaded after `identify_by` is called, thus breaking
|
52
|
-
identifiers.
|
53
|
-
|
54
|
-
## 0.6.0 (2018-11-15)
|
11
|
+
## 1.0.0.rc2 (2020-06-16)
|
55
12
|
|
56
|
-
|
13
|
+
- Fix connection identifiers deserialization regression. ([@palkan][])
|
57
14
|
|
58
|
-
-
|
15
|
+
Using non-strings or non-GlobalId-encoded objects was broken.
|
59
16
|
|
60
|
-
-
|
17
|
+
- Improve `anycable:setup` generator. ([@palkan][])
|
61
18
|
|
62
|
-
|
19
|
+
Update Docker snippet, do not enable persistent sessions automatically,
|
20
|
+
fix setting `config.action_cable.url` in environment configuration.
|
63
21
|
|
64
|
-
|
22
|
+
## 1.0.0.rc1 (2020-06-10)
|
65
23
|
|
66
|
-
|
24
|
+
- Add `state_attr_accessor` for channels. ([@palkan][])
|
67
25
|
|
68
|
-
|
26
|
+
Just like `attr_accessor` but "persists" the state between RPC calls.
|
69
27
|
|
70
|
-
|
28
|
+
- Add `Channel#stop_stream_from` support. ([@palkan][])
|
71
29
|
|
72
|
-
|
30
|
+
- Add `RemoteConnections` support. ([@palkan][])
|
73
31
|
|
74
|
-
-
|
32
|
+
- Add `AnyCable::Rails.enabled?` method which returns true if Action Cable uses AnyCable adapter. ([@palkan][])
|
75
33
|
|
76
|
-
-
|
34
|
+
- Add `anycable:download` generator to download `anycable-go` binary. ([@palkan][])
|
77
35
|
|
78
|
-
|
79
|
-
the CLI.
|
36
|
+
- **Ruby 2.5+ is required**. ([@palkan][])
|
80
37
|
|
81
|
-
-
|
38
|
+
- Support `disconnect` messages. ([@palkan][])
|
82
39
|
|
83
|
-
|
40
|
+
Added in Rails 6 (see [PR#34194](https://github.com/rails/rails/pull/34194)).
|
84
41
|
|
85
|
-
|
42
|
+
- Add ability to persist _dirty_ `request.session` between RPC calls. ([@palkan][])
|
86
43
|
|
87
|
-
|
44
|
+
This feature emulates the Action Cable behaviour where it's possible to use `request.session` as a shared Hash-like store.
|
45
|
+
This could be used by some applications (e.g., [StimulusReflex](https://github.com/hopsoft/stimulus_reflex)-based).
|
88
46
|
|
89
|
-
|
47
|
+
You must turn this feature on by setting `persistent_session_enabled: true` in the AnyCable configuration.
|
90
48
|
|
91
|
-
|
49
|
+
- Add ability to use Rack middlewares when build a request for a connection. ([@bibendi][])
|
92
50
|
|
93
|
-
|
51
|
+
- Add set up generator to configure a Rails application by running `bin/rails g anycable:setup`. ([@bibendi][])
|
94
52
|
|
95
|
-
-
|
96
|
-
|
97
|
-
Should always be `true`, we do not expect a failure here.
|
98
|
-
|
99
|
-
## 0.5.2
|
100
|
-
|
101
|
-
- Add config/anycable.yml to Rails generator. ([@alekseyl][])
|
102
|
-
|
103
|
-
## 0.5.1
|
104
|
-
|
105
|
-
- Improve Rails integration. ([@palkan][])
|
106
|
-
|
107
|
-
Log to STDOUT in development.
|
108
|
-
Make order of initializers more deterministic.
|
109
|
-
Show warning if AnyCable is loaded after application initialization.
|
110
|
-
|
111
|
-
## 0.5.0
|
112
|
-
|
113
|
-
- [#17](https://github.com/anycable/anycable-rails/issues/17) Refactor logging. ([@palkan][])
|
114
|
-
|
115
|
-
Use Rails logger everywhere.
|
116
|
-
|
117
|
-
Add access logs ([anycable/anycable#20](https://github.com/anycable/anycable/issues/20)).
|
118
|
-
|
119
|
-
## 0.4.7
|
120
|
-
|
121
|
-
- Minor fixes. ([@palkan][])
|
122
|
-
|
123
|
-
## 0.4.6
|
124
|
-
|
125
|
-
- Disable mounting default Action Cable server when AnyCable is loaded. ([@palkan][])
|
126
|
-
|
127
|
-
## 0.4.5
|
128
|
-
|
129
|
-
- Handle tagged logger. ([@palkan][])
|
130
|
-
|
131
|
-
Ignore tagged logger features ('cause we do not have _persistent_ logger).
|
132
|
-
|
133
|
-
## 0.4.4
|
134
|
-
|
135
|
-
- Fix bug with ActiveRecord connections (https://github.com/anycable/anycable/issues/9). ([@palkan][])
|
53
|
+
- Require a minimum version of Ruby when installing the gem. ([@bibendi][])
|
136
54
|
|
137
|
-
|
55
|
+
- Add ability to develop the gem with Docker. ([@bibendi][])
|
138
56
|
|
139
|
-
-
|
57
|
+
See [Changelog](https://github.com/anycable/anycable-rails/blob/0-6-stable/CHANGELOG.md) for versions <1.0.0.
|
140
58
|
|
141
59
|
[@palkan]: https://github.com/palkan
|
142
60
|
[@alekseyl]: https://github.com/alekseyl
|
data/MIT-LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
-
[![GitPitch](https://gitpitch.com/assets/badge.svg)](https://gitpitch.com/anycable/anycable/master?grs=github)
|
1
|
+
[![GitPitch](https://gitpitch.com/assets/badge.svg)](https://gitpitch.com/anycable/anycable/master?grs=github)
|
2
|
+
[![Gem Version](https://badge.fury.io/rb/anycable-rails.svg)](https://rubygems.org/gems/anycable-rails)
|
3
|
+
[![Build](https://github.com/anycable/anycable-rails/workflows/Build/badge.svg)](https://github.com/anycable/anycable-rails/actions)
|
2
4
|
[![Gitter](https://img.shields.io/badge/gitter-join%20chat%20%E2%86%92-brightgreen.svg)](https://gitter.im/anycable/Lobby)
|
3
|
-
[![Documentation](https://img.shields.io/badge/docs-link-brightgreen.svg)](https://docs.anycable.io/#/ruby/rails)
|
5
|
+
[![Documentation](https://img.shields.io/badge/docs-link-brightgreen.svg)](https://docs.anycable.io/v1/#/ruby/rails)
|
4
6
|
|
5
7
|
# AnyCable Rails
|
6
8
|
|
@@ -10,27 +12,23 @@ With AnyCable you can use channels, client-side JS, broadcasting - (almost) all
|
|
10
12
|
|
11
13
|
You can even use Action Cable in development and not be afraid of [compatibility issues](#compatibility).
|
12
14
|
|
13
|
-
|
15
|
+
**Important** This is a readme for the upcoming v1.0 release. For v0.6.x see the readme from the [0-6-stable](https://github.com/anycable/anycable-rails/tree/0-6-stable) branch.
|
14
16
|
|
15
|
-
|
17
|
+
<!-- 💾 [Example Application](https://github.com/anycable/anycable_demo) -->
|
16
18
|
|
19
|
+
📑 [Documentation](https://docs.anycable.io/v1/#/ruby/rails).
|
17
20
|
|
18
21
|
<a href="https://evilmartians.com/">
|
19
22
|
<img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54"></a>
|
20
23
|
|
21
24
|
## Requirements
|
22
25
|
|
23
|
-
- Ruby >= 2.
|
24
|
-
- Rails >= 5.
|
25
|
-
- Redis (see [other options]() for broadcasting)
|
26
|
-
|
27
|
-
## How It Works?
|
28
|
-
|
29
|
-
<img src="https://trello-attachments.s3.amazonaws.com/5781e0ed48e4679e302833d3/820x987/5b6a305417b04e20e75f49c5816e027c/Anycable_vs_ActionCable_copy.jpg" width="400" />
|
26
|
+
- Ruby >= 2.5
|
27
|
+
- Rails >= 5.2
|
28
|
+
- Redis (see [other options](https://github.com/anycable/anycable/issues/2) for broadcasting)
|
30
29
|
|
31
30
|
## Usage
|
32
31
|
|
33
|
-
|
34
32
|
Add `anycable-rails` gem to your Gemfile:
|
35
33
|
|
36
34
|
```ruby
|
@@ -40,14 +38,25 @@ gem "anycable-rails"
|
|
40
38
|
gem "redis", ">= 4.0"
|
41
39
|
```
|
42
40
|
|
43
|
-
|
41
|
+
### Interactive set up
|
42
|
+
|
43
|
+
After the gem was installed, you can run an interactive wizard to configure your Rails application for using with AnyCable by running a generator:
|
44
|
+
|
45
|
+
```sh
|
46
|
+
bundle exec rails g anycable:setup
|
47
|
+
```
|
48
|
+
|
49
|
+
### Manual set up
|
44
50
|
|
45
|
-
|
51
|
+
Specify AnyCable subscription adapter for Action Cable:
|
46
52
|
|
47
53
|
```yml
|
48
54
|
# config/cable.yml
|
49
|
-
|
55
|
+
development:
|
50
56
|
adapter: any_cable # or anycable
|
57
|
+
|
58
|
+
production:
|
59
|
+
adapter: any_cable
|
51
60
|
```
|
52
61
|
|
53
62
|
and specify AnyCable WebSocket server URL:
|
@@ -66,7 +75,7 @@ config.action_cable.url = "wss://ws.example.com/cable"
|
|
66
75
|
|
67
76
|
Then, run AnyCable RPC server:
|
68
77
|
|
69
|
-
```
|
78
|
+
```sh
|
70
79
|
$ bundle exec anycable
|
71
80
|
|
72
81
|
# don't forget to provide Rails env
|
@@ -74,42 +83,30 @@ $ bundle exec anycable
|
|
74
83
|
$ RAILS_ENV=production bundle exec anycable
|
75
84
|
```
|
76
85
|
|
77
|
-
And, finally, run AnyCable WebSocket server, e.g. [anycable-go](https://docs.anycable.io/#/anycable-go/getting_started):
|
86
|
+
And, finally, run AnyCable WebSocket server, e.g. [anycable-go](https://docs.anycable.io/v1/#/anycable-go/getting_started):
|
78
87
|
|
79
88
|
```sh
|
80
89
|
anycable-go --host=localhost --port=3334
|
81
90
|
```
|
82
91
|
|
83
|
-
See [documentation](https://docs.anycable.io/#/ruby/rails) for more information on AnyCable + Rails usage.
|
92
|
+
See [documentation](https://docs.anycable.io/v1/#/ruby/rails) for more information on AnyCable + Rails usage.
|
84
93
|
|
85
94
|
## Action Cable Compatibility
|
86
95
|
|
87
|
-
See [documentation](https://docs.anycable.io/#/ruby/compatibility).
|
88
|
-
|
89
|
-
## Links
|
90
|
-
|
91
|
-
- [AnyCable: Action Cable on steroids!](https://evilmartians.com/chronicles/anycable-actioncable-on-steroids)
|
92
|
-
|
93
|
-
- [From Action to Any](https://medium.com/@leshchuk/from-action-to-any-1e8d863dd4cf) by [@alekseyl](https://github.com/alekseyl)
|
94
|
-
|
95
|
-
## Talks
|
96
|
-
|
97
|
-
- One cable to rule them all, RubyKaigi 2018, [slides](https://speakerdeck.com/palkan/rubykaigi-2018-anycable-one-cable-to-rule-them-all) and [video](https://www.youtube.com/watch?v=jXCPuNICT8s) (EN)
|
98
|
-
|
99
|
-
- Wroc_Love.rb 2018 [slides](https://speakerdeck.com/palkan/wroc-love-dot-rb-2018-cables-cables-cables) and [video](https://www.youtube.com/watch?v=AUxFFOehiy0) (EN)
|
100
|
-
|
101
|
-
## Compatible WebSocket servers
|
102
|
-
|
103
|
-
- [AnyCable Go](https://github.com/anycable/anycable-go)
|
104
|
-
- [ErlyCable](https://github.com/anycable/erlycable)
|
96
|
+
See [documentation](https://docs.anycable.io/v1/#/ruby/compatibility).
|
105
97
|
|
106
98
|
## Contributing
|
107
99
|
|
108
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/anycable/anycable-rails.
|
100
|
+
Bug reports and pull requests are welcome on GitHub at [https://github.com/anycable/anycable-rails](https://github.com/anycable/anycable-rails).
|
109
101
|
|
110
102
|
## Development
|
111
103
|
|
112
104
|
If you are familiar with Docker, you can use [DIP](https://github.com/bibendi/dip) to start developing the gem quickly.
|
113
105
|
|
114
106
|
## License
|
107
|
+
|
115
108
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
109
|
+
|
110
|
+
## Security Contact
|
111
|
+
|
112
|
+
To report a security vulnerability, please contact us at `anycable@evilmartians.com`. We will coordinate the fix and disclosure.
|
data/lib/anycable/rails.rb
CHANGED
@@ -3,6 +3,9 @@
|
|
3
3
|
require "anycable"
|
4
4
|
require "anycable/rails/version"
|
5
5
|
require "anycable/rails/config"
|
6
|
+
require "anycable/rails/rack"
|
7
|
+
|
8
|
+
require "globalid"
|
6
9
|
|
7
10
|
module AnyCable
|
8
11
|
# Rails handler for AnyCable
|
@@ -11,8 +14,40 @@ module AnyCable
|
|
11
14
|
|
12
15
|
ADAPTER_ALIASES = %w[any_cable anycable].freeze
|
13
16
|
|
14
|
-
|
15
|
-
|
17
|
+
class << self
|
18
|
+
def enabled?
|
19
|
+
adapter = ::ActionCable.server.config.cable&.fetch("adapter", nil)
|
20
|
+
compatible_adapter?(adapter)
|
21
|
+
end
|
22
|
+
|
23
|
+
def compatible_adapter?(adapter)
|
24
|
+
ADAPTER_ALIASES.include?(adapter)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Serialize connection/channel state variable to string
|
28
|
+
# using GlobalID where possible or JSON (if json: true)
|
29
|
+
def serialize(obj, json: false)
|
30
|
+
obj.try(:to_gid_param) || (json ? obj.to_json : obj)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Deserialize previously serialized value from string to
|
34
|
+
# Ruby object.
|
35
|
+
# If the resulting object is a Hash, make it indifferent
|
36
|
+
def deserialize(str, json: false)
|
37
|
+
str.yield_self do |val|
|
38
|
+
next val unless val.is_a?(String)
|
39
|
+
|
40
|
+
gval = GlobalID::Locator.locate(val)
|
41
|
+
return gval if gval
|
42
|
+
|
43
|
+
next val unless json
|
44
|
+
|
45
|
+
JSON.parse(val)
|
46
|
+
end.yield_self do |val|
|
47
|
+
next val.with_indifferent_access if val.is_a?(Hash)
|
48
|
+
val
|
49
|
+
end
|
50
|
+
end
|
16
51
|
end
|
17
52
|
end
|
18
53
|
end
|
@@ -28,6 +28,10 @@ module ActionCable
|
|
28
28
|
connection.socket.subscribe identifier, broadcasting
|
29
29
|
end
|
30
30
|
|
31
|
+
def stop_stream_from(broadcasting)
|
32
|
+
connection.socket.unsubscribe identifier, broadcasting
|
33
|
+
end
|
34
|
+
|
31
35
|
def stop_all_streams
|
32
36
|
connection.socket.unsubscribe_from_all identifier
|
33
37
|
end
|
@@ -1,43 +1,52 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "action_cable/connection"
|
4
|
+
require "anycable/rails/actioncable/connection/serializable_identification"
|
4
5
|
require "anycable/rails/refinements/subscriptions"
|
5
6
|
require "anycable/rails/actioncable/channel"
|
7
|
+
require "anycable/rails/actioncable/remote_connections"
|
8
|
+
require "anycable/rails/session_proxy"
|
6
9
|
|
7
10
|
module ActionCable
|
8
11
|
module Connection
|
9
12
|
# rubocop: disable Metrics/ClassLength
|
10
13
|
class Base # :nodoc:
|
11
|
-
# We store logger tags in
|
14
|
+
# We store logger tags in the connection state to be able
|
12
15
|
# to re-use them in the subsequent calls
|
13
16
|
LOG_TAGS_IDENTIFIER = "__ltags__"
|
14
17
|
|
15
18
|
using AnyCable::Refinements::Subscriptions
|
16
19
|
|
20
|
+
include SerializableIdentification
|
21
|
+
|
17
22
|
attr_reader :socket
|
18
23
|
|
24
|
+
alias anycable_socket socket
|
25
|
+
|
26
|
+
delegate :env, :session, to: :request
|
27
|
+
|
19
28
|
class << self
|
20
29
|
def call(socket, **options)
|
21
|
-
new(socket, options)
|
30
|
+
new(socket, nil, options)
|
22
31
|
end
|
32
|
+
end
|
23
33
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
end
|
34
|
+
def initialize(socket, env, identifiers: "{}", subscriptions: [])
|
35
|
+
if env
|
36
|
+
# If env is set, then somehow we're in the context of Action Cable
|
37
|
+
# Return and print a warning in #process
|
38
|
+
@request = ActionDispatch::Request.new(env)
|
39
|
+
return
|
31
40
|
end
|
32
|
-
end
|
33
41
|
|
34
|
-
def initialize(socket, identifiers: "{}", subscriptions: [])
|
35
42
|
@ids = ActiveSupport::JSON.decode(identifiers)
|
36
43
|
|
37
|
-
@ltags =
|
44
|
+
@ltags = socket.cstate.read(LOG_TAGS_IDENTIFIER).yield_self do |raw_tags|
|
45
|
+
next unless raw_tags
|
46
|
+
ActiveSupport::JSON.decode(raw_tags)
|
47
|
+
end
|
38
48
|
|
39
49
|
@cached_ids = {}
|
40
|
-
@env = socket.env
|
41
50
|
@coder = ActiveSupport::JSON
|
42
51
|
@socket = socket
|
43
52
|
@subscriptions = ActionCable::Connection::Subscriptions.new(self)
|
@@ -46,15 +55,32 @@ module ActionCable
|
|
46
55
|
subscriptions.each { |id| @subscriptions.fetch(id) }
|
47
56
|
end
|
48
57
|
|
58
|
+
def process
|
59
|
+
# Use Rails logger here to print to stdout in development
|
60
|
+
logger.error invalid_request_message
|
61
|
+
logger.info finished_request_message
|
62
|
+
[404, {"Content-Type" => "text/plain"}, ["Page not found"]]
|
63
|
+
end
|
64
|
+
|
65
|
+
def invalid_request_message
|
66
|
+
"You're trying to connect to Action Cable server while using AnyCable. " \
|
67
|
+
"See https://docs.anycable.io/v1/#/troubleshooting?id=server-raises-an-argumenterror-exception-when-client-tries-to-connect"
|
68
|
+
end
|
69
|
+
|
49
70
|
def handle_open
|
50
71
|
logger.info started_request_message if access_logs?
|
51
72
|
|
52
|
-
verify_origin!
|
73
|
+
verify_origin! || return
|
53
74
|
|
54
75
|
connect if respond_to?(:connect)
|
76
|
+
|
77
|
+
socket.cstate.write(LOG_TAGS_IDENTIFIER, fetch_ltags.to_json)
|
78
|
+
|
55
79
|
send_welcome_message
|
56
80
|
rescue ActionCable::Connection::Authorization::UnauthorizedError
|
57
|
-
reject_request
|
81
|
+
reject_request(
|
82
|
+
ActionCable::INTERNAL[:disconnect_reasons]&.[](:unauthorized) || "unauthorized"
|
83
|
+
)
|
58
84
|
end
|
59
85
|
|
60
86
|
def handle_close
|
@@ -84,7 +110,12 @@ module ActionCable
|
|
84
110
|
end
|
85
111
|
# rubocop:enable Metrics/MethodLength
|
86
112
|
|
87
|
-
def close
|
113
|
+
def close(reason: nil, reconnect: nil)
|
114
|
+
transmit(
|
115
|
+
type: ActionCable::INTERNAL[:message_types].fetch(:disconnect, "disconnect"),
|
116
|
+
reason: reason,
|
117
|
+
reconnect: reconnect
|
118
|
+
)
|
88
119
|
socket.close
|
89
120
|
end
|
90
121
|
|
@@ -92,37 +123,14 @@ module ActionCable
|
|
92
123
|
socket.transmit encode(cable_message)
|
93
124
|
end
|
94
125
|
|
95
|
-
# Generate identifiers info.
|
96
|
-
# Converts GlobalID compatible vars to corresponding global IDs params.
|
97
|
-
def identifiers_hash
|
98
|
-
obj = { LOG_TAGS_IDENTIFIER => fetch_ltags }
|
99
|
-
|
100
|
-
identifiers.each_with_object(obj) do |id, acc|
|
101
|
-
obj = instance_variable_get("@#{id}")
|
102
|
-
next unless obj
|
103
|
-
|
104
|
-
acc[id] = obj.try(:to_gid_param) || obj
|
105
|
-
end.compact
|
106
|
-
end
|
107
|
-
|
108
|
-
def identifiers_json
|
109
|
-
identifiers_hash.to_json
|
110
|
-
end
|
111
|
-
|
112
|
-
# Fetch identifier and deserialize if neccessary
|
113
|
-
def fetch_identifier(name)
|
114
|
-
@cached_ids[name] ||= @cached_ids.fetch(name) do
|
115
|
-
val = ids[name.to_s]
|
116
|
-
next val unless val.is_a?(String)
|
117
|
-
|
118
|
-
GlobalID::Locator.locate(val) || val
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
126
|
def logger
|
123
127
|
@logger ||= TaggedLoggerProxy.new(AnyCable.logger, tags: ltags || [])
|
124
128
|
end
|
125
129
|
|
130
|
+
def request
|
131
|
+
@request ||= build_rack_request
|
132
|
+
end
|
133
|
+
|
126
134
|
private
|
127
135
|
|
128
136
|
attr_reader :ids, :ltags
|
@@ -158,19 +166,33 @@ module ActionCable
|
|
158
166
|
end
|
159
167
|
|
160
168
|
def verify_origin!
|
161
|
-
return unless socket.env.key?("HTTP_ORIGIN")
|
169
|
+
return true unless socket.env.key?("HTTP_ORIGIN")
|
162
170
|
|
163
|
-
return if allow_request_origin?
|
171
|
+
return true if allow_request_origin?
|
164
172
|
|
165
|
-
|
166
|
-
ActionCable::
|
167
|
-
"Origin is not allowed"
|
173
|
+
reject_request(
|
174
|
+
ActionCable::INTERNAL[:disconnect_reasons]&.[](:invalid_request) || "invalid_request"
|
168
175
|
)
|
176
|
+
false
|
169
177
|
end
|
170
178
|
|
171
|
-
def reject_request
|
179
|
+
def reject_request(reason, reconnect = false)
|
172
180
|
logger.info finished_request_message("Rejected") if access_logs?
|
173
|
-
close
|
181
|
+
close(
|
182
|
+
reason: reason,
|
183
|
+
reconnect: reconnect
|
184
|
+
)
|
185
|
+
end
|
186
|
+
|
187
|
+
def build_rack_request
|
188
|
+
environment = Rails.application.env_config.merge(socket.env)
|
189
|
+
AnyCable::Rails::Rack.app.call(environment)
|
190
|
+
|
191
|
+
ActionDispatch::Request.new(environment)
|
192
|
+
end
|
193
|
+
|
194
|
+
def request_loaded?
|
195
|
+
instance_variable_defined?(:@request)
|
174
196
|
end
|
175
197
|
end
|
176
198
|
# rubocop:enable Metrics/ClassLength
|