I've recently deployed a Rails app, and have heard back from a few users that it doesn't work in their work environments. It's clear that Websockets are blocked for them.
I've hunted through the Rails documentation on this but can't find any information on how to go about detecting if this has happened. My best guess would be to send an AJAX request out for an ActionCable broadcast, and when that broadcast is not received after a certain timeout, to conclude that Websockets must be blocked.
Are there any easy answers here, perhaps already part of the Rails API, to determine Websocket connectivity?
I have a workaround that isn't great, but is better than anything else I've seen. Rails provides no interface, but you can get down to the native WebSocket and handle the error.
consumer.subscriptions.create("ChatChannel", { ... });
consumer.connection.webSocket.onerror = function () {
console.log('Websocket connection error!');
// Error handling goes here. Fallback to polling, perhaps.
};
ActionCable will keep trying to reconnect, and this only grabs the first failure, but that's enough to cover many cases.
There is a rejected handler you can use. This should fire when the subscription is rejected by the server.
The below coffeescript example is from the official rails docs.
App.cable.subscriptions.create "AppearanceChannel",
# Called when the subscription is ready for use on the server.
connected: ->
// Do something
# Called when the subscription is rejected by the server.
rejected: ->
// Do something
Whenever an action cable connection fails it writes to the browser console failed: WebSocket is closed before the connection is established
You can leverage this to know if there was a connection error:
def action_cable_connection_errored?
page.driver.browser.manage.logs.get(:browser)
.map(&:message)
.join
.match('failed: WebSocket is closed before the connection is established')
end
Related
I am new to QuickFIX/J.
Creating initiator using websocket(frontend-angular, backend-Springboot websocket). Using w.3.
I would like to handle session expired issue. When the FIX server session is expired, it is sending Logout with reason session deactivated. That works fine for already connected connection/session.
Now, after this, trying to initiate connection, it keeps calling back logout and toAdmin with repeating event/error on screen log (as event) "Disconnecting, End Of Stream encountered".
I would like to handle this scenario and want to capture this in my code so that proper message to UI will be sent.
I don't know which QuickFIX/J version you are using, but on versions up to 2.2.0 you could implement the quickfix.SessionStateListener in your application and utilize its onDisconnect() callback.
If you are even using version 2.3.0 you could also use onConnectException() which will handle some additional scenarios that the first callback does not cover.
I'm working on embedding a soft phone into a web page that will go into Odoo (web based ERP system). It will allow inbound and outbound calls for employees.
The token expires every hour. So this means the user will have to refresh the page every hour. I could do an http refresh but if the user is on a call when it does the refresh it will knock them off the call.
How do we get around this so we can build a fully working dialer?
Twilio evangelist here.
I'd suggest using JavaScript to do an asynchronous HTTP request to get a new token from your server and then updating the instance of client with it.
Hope that helps.
Another Twilio evangelist here!
You can actually listen for the offline event on the Twilio.Device object. From the documentation:
.offline( handler(device) )
Register a handler function to be called when the offline event is
fired. This is triggered when the connection to Twilio drops or the
device's capability token is invalid/expired. In either of these
scenarios, the device cannot receive incoming connections or make
outgoing connections. If the token expires during an active connection
the offline event handler will be called, but the connection will not
be terminated. In this situation you will have to call
Twilio.Device.setup() with a valid token before attempting or
receiving the next connection.
So you want something like:
Twilio.Device.offline(function(device) {
fetchTokenFromServer(function(token) {
device.setup(token);
});
});
where fetchTokenFromServer makes the HTTP request that Devin suggested in his answer.
Let me know if this helps.
I just ran into this issue so hopefully my solution can help you and others.
I was using twilio.js v1.3 and tried implementing my offline callback like #philnash recommended, but kept getting the error device.setup is not a function. I then tried using Twilio.Device.setup(newToken) and was able to get the capability token refreshed but also ended up getting a new error: Cannot read property 'setToken' of undefined.
I ended up having to use twilio.js v1.4 to make the error go away. My working solution looks like this:
Twilio.Device.offline(function(device) {
$.ajax(urlToGetNewToken, type: 'get').done(function(newToken) {
Twilio.Device.setup(newToken)
})
})
I added a chat functionality in my existing RoR app with the websocket-rails (https://github.com/websocket-rails/websocket-rails) gem and I'm testing it in production mode on Heroku.
It works fine in localhost, but when I sent it to Heroku it is not receiving any further messages from the Server after the connection.
The connection works:
var WEBSOCKET_URL = 'myapponheroku.herokuapp.com/websocket'
var dispatcher = new WebSocketRails(WEBSOCKET_URL);
dispatcher.on_open = function(data) {
console.log('Connection has been established: ', data);
};
And I see the feedback message.
But the first task is to ask the server for active rooms in my chat. I noticed nothing is returning. I put some feedback messages in the server's action that should do the first tasks and none of them are reached. The feedback I implemented is a simple pair of functions that just returns a object and prints it to the console:
Javascript
dispatcher.bind('feedback',function(data){
console.log(data);
});
Ruby
def feedback data
send_message :feedback, {data: data}
end
It is never triggered. Any ideas? Is the a special configuration I must do on Heroku to allow it to work?
#update
Same error on my live server hosted on AWS.
Connection is established, but nothing is returned from server to client.
#update2
I wrote some code so the app would write some files when connection is established and when it asks for open rooms, right at the beginning, and the files were not created. The actions are not even being called.
We use Twilio SDK in our iOS app. It works fine but sometimes didStopListeningForIncomingConnections callback is called with error=31000 ("General error"). After that, the device turns to a strange state: it seems to be online but it's impossible to call it. And it shows "unconnected" state on the device.
So the questions are:
1. What does this 31000 error means?
2. What should we do in such a case? How to reconnect device to Twilio?
Megan from Twilio here.
You can see what an error for Twilio Client means here: https://www.twilio.com/docs/api/client/errors
However, 31000 is a rather vague and less than ideal error message as you describe. In this case, it is likely that the Twilio capability token has probably expired while the application is in the background, and if you merely call the listen method whenever they are receiving the 31000 generic error, it might cause the client SDK to result in a error-retry loop and crash the application eventually.
At the time of your writing with TwilioClient iOS SDK v1.2.5, it is suggested to use the following sample code in your did-stop-listening callback:
- (void)device:(TCDevice*)device didStopListeningForIncomingConnections:(NSError*)error {
if ( [self checkCapabilityTokenStillValid] ) {
// if the token has not yet expired, use the `listen` method of `TCDevice` to resume the listening state
[self.device listen];
}
else {
// restart all over by requesting a new capability token and initialize/update the `TCDevice` instance again
[self login];
}
}
The TwilioClient iOS SDK takes care of dispatching the listen and updateCapabilitiyToken: methods to the current thread for execution, therefore it's safe to call them directly in the didStopListeningForIncomingConnections. The did-stop-listening delegate method is always triggered with dispatch_get_main_queue() of Grand Central Dispatch.
Hope this may help others if they run into the same generic error.
This may or may not be the issue, we have encountered 31000 errors two times in our development and both were a result of generating the JWT on our server api. To be clear the error was a 31000 on the client, but the reason for this was in the construction of the JWT, and the params we wanted twilio to send back to our application.
When passing in an object to allow_client_outgoing or allow_client_incoming the twilio sdk concats this all in their scope attribute in their JWT. It added it to the scope:client:outgoing?appSid= which looks like a query string. That means it has a size limit of 2048. So exceeding this length generates a 31000 error.
In addition adding the objects doesn't seem to always implicitly serialize the object correctly, it introduces characters that can generate errors in their corresponding mobile sdks (but not their web sdk ... weird) so we took care of this by explicitly serializing objects to JSON before they are inserted into the JWT.
I hope both of these examples help you track down the issue.
I am developing an iPhone app which is using CocoaHTTPServer for making remote server communication.
The app will send the request details to the CocoaHTTPServer which will store the request locally. Once the internet connectivity is available, CocoaHTTPServer will send the request to remote server & will get the server response now CocoaHTTPServer has to send this response back to the app,
But I am confused how to implement it. Is there any inter app communication api for the same?
Any suggestions are greatly appreciated.
Well , I haven't workaround CocoaHTTP server classes so can't explain you verywell but I found there are couple of tutorials will surly guide you.
Thanks to Matt Gallagher for such a detailed article.
You can listen for a connection using NSFileHandle class
listeningHandle = [[NSFileHandle alloc]
initWithFileDescriptor:fileDescriptor
closeOnDealloc:YES];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(receiveIncomingConnectionNotification:)
name:NSFileHandleConnectionAcceptedNotification
object:nil];
[listeningHandle acceptConnectionInBackgroundAndNotify];
When receiveIncomingConnectionNotification: is invoked, each new incoming connection will get its own NSFileHandle. If you're keeping track, you can handle received message
if(CFHTTPMessageIsHeaderComplete(incomingRequest))
{
HTTPResponseHandler *handler =
[HTTPResponseHandler
handlerForRequest:incomingRequest
fileHandle:incomingFileHandle
server:self];
[responseHandlers addObject:handler];
[self stopReceivingForFileHandle:incomingFileHandle close:NO];
[handler startResponse];
return;
}
Note : please go through the full article, it has nice explanation.
Apart from this you may have look on this as well.
Hope this will give you some idea.
You question is focussing on background proces.
When an App goes into background, it get very limited time to finish things up. After that the App freezes in background. That is not a good situation to start communication.
Apple states clearly that the priority is always on the running foreground tasks.
The Notification mechanism (as listed by RDC above) is created to handle external events. During such a wake up you can send/receive a little bit of data, however you'll get minimal priority. Since timing is important in communication, I would not go for that either.
I suggest checking communication during the wakeup call and start activities then. And use the Notification mechanism to wakeup the user, that network is up again.
URL scheme can be used to send the response back to the app. The response from the remote server can be set as a parameter in the URL. The CocoaHTTPServer can invoke the other app which will be the handler of this unique URL. The below link provides more information on the same.
Inter-AppCommunication using URL scheme