Stop trying to reconnect on unauthorized cable connections

This commit is contained in:
Mick Staugaard 2018-10-11 13:47:16 -07:00
parent b802e08273
commit 58dbc1c2ed
9 changed files with 46 additions and 10 deletions

View File

@ -1,3 +1,8 @@
* The JavaScript WebSocket client will no longer try to reconnect
when you call `reject_unauthorized_connection` on the connection.
*Mick Staugaard*
* `ActionCable.Connection#getState` now references the configurable
`ActionCable.adapters.WebSocket` property rather than the `WebSocket` global
variable, matching the behavior of `ActionCable.Connection#open`.

View File

@ -136,10 +136,16 @@
var INTERNAL = {
message_types: {
welcome: "welcome",
disconnect: "disconnect",
ping: "ping",
confirmation: "confirm_subscription",
rejection: "reject_subscription"
},
disconnect_reasons: {
unauthorized: "unauthorized",
invalid_request: "invalid_request",
server_restart: "server_restart"
},
default_mount_path: "/cable",
protocols: [ "actioncable-v1-json", "actioncable-unsupported" ]
};
@ -251,12 +257,18 @@
if (!this.isProtocolSupported()) {
return;
}
var _JSON$parse = JSON.parse(event.data), identifier = _JSON$parse.identifier, message = _JSON$parse.message, type = _JSON$parse.type;
var _JSON$parse = JSON.parse(event.data), identifier = _JSON$parse.identifier, message = _JSON$parse.message, reason = _JSON$parse.reason, reconnect = _JSON$parse.reconnect, type = _JSON$parse.type;
switch (type) {
case message_types.welcome:
this.monitor.recordConnect();
return this.subscriptions.reload();
case message_types.disconnect:
logger.log("Disconnecting. Reason: " + reason);
return this.close({
allowReconnect: reconnect
});
case message_types.ping:
return this.monitor.recordPing();

View File

@ -117,11 +117,14 @@ Connection.reopenDelay = 500
Connection.prototype.events = {
message(event) {
if (!this.isProtocolSupported()) { return }
const {identifier, message, type} = JSON.parse(event.data)
const {identifier, message, reason, reconnect, type} = JSON.parse(event.data)
switch (type) {
case message_types.welcome:
this.monitor.recordConnect()
return this.subscriptions.reload()
case message_types.disconnect:
logger.log(`Disconnecting. Reason: ${reason}`)
return this.close({allowReconnect: reconnect})
case message_types.ping:
return this.monitor.recordPing()
case message_types.confirmation:

View File

@ -33,10 +33,16 @@ module ActionCable
INTERNAL = {
message_types: {
welcome: "welcome",
disconnect: "disconnect",
ping: "ping",
confirmation: "confirm_subscription",
rejection: "reject_subscription"
},
disconnect_reasons: {
unauthorized: "unauthorized",
invalid_request: "invalid_request",
server_restart: "server_restart"
},
default_mount_path: "/cable",
protocols: ["actioncable-v1-json", "actioncable-unsupported"].freeze
}

View File

@ -95,7 +95,12 @@ module ActionCable
end
# Close the WebSocket connection.
def close
def close(reason: nil, reconnect: true)
transmit(
type: ActionCable::INTERNAL[:message_types][:disconnect],
reason: reason,
reconnect: reconnect
)
websocket.close
end
@ -170,7 +175,7 @@ module ActionCable
message_buffer.process!
server.add_connection(self)
rescue ActionCable::Connection::Authorization::UnauthorizedError
respond_to_invalid_request
close(reason: ActionCable::INTERNAL[:disconnect_reasons][:unauthorized], reconnect: false) if websocket.alive?
end
def handle_close
@ -211,7 +216,7 @@ module ActionCable
end
def respond_to_invalid_request
close if websocket.alive?
close(reason: ActionCable::INTERNAL[:disconnect_reasons][:invalid_request]) if websocket.alive?
logger.error invalid_request_message
logger.info finished_request_message

View File

@ -36,7 +36,9 @@ module ActionCable
end
def restart
connections.each(&:close)
connections.each do |connection|
connection.close(reason: ActionCable::INTERNAL[:disconnect_reasons][:server_restart])
end
@mutex.synchronize do
# Shutdown the worker pool

View File

@ -25,8 +25,11 @@ class ActionCable::Connection::AuthorizationTest < ActionCable::TestCase
"HTTP_HOST" => "localhost", "HTTP_ORIGIN" => "http://rubyonrails.com"
connection = Connection.new(server, env)
assert_called(connection.websocket, :close) do
connection.process
assert_called_with(connection.websocket, :transmit, [{ type: "disconnect", reason: "unauthorized", reconnect: false }.to_json]) do
assert_called(connection.websocket, :close) do
connection.process
end
end
end
end

View File

@ -108,7 +108,7 @@ class ActionCable::Connection::BaseTest < ActionCable::TestCase
connection.process
assert_called(connection.websocket, :close) do
connection.close
connection.close(reason: "testing")
end
end
end

View File

@ -58,7 +58,7 @@ class ActionCable::Connection::ClientSocketTest < ActionCable::TestCase
client.instance_variable_get("@stream")
.instance_variable_get("@rack_hijack_io")
.define_singleton_method(:close) { event.set }
connection.close
connection.close(reason: "testing")
event.wait
end
end