Correctly timing out XHR Requests in React-Native on Android - xmlhttprequest

We're facing an issue with handling unexpected behaviours when performing xmlHttpRequests on Android devices using React-Native. We've experienced behaviour where the app becomes unavailable to complete API calls, even though the device is connected to the internet perfectly well (browser can access non-cached sites just fine). The only way to resolve this issue for our users has been to completely restart the app.
To understand the issue and its severity, we wrapped all our API calls to a timer function in production and sent reports to Sentry whenever a request took longer than 30 seconds to finish. Now we've been receiving these kind of reports in the hundreds per day with the duration sometimes being in the hours or even days.
First, instead of using whatwg-fetch, we moved to using axios so that we can manually set the timeout of each request, but this ended up not helping at all.
Second, we dove deeper into understanding how React-Native actually implements timing out XHR requests on Android, and found that it uses OkHttp3 under the hood. OkHttp has a default value for connect, read and write timeouts and react-native allows developers to change the value of connect timeout here. However, OkHttp also has a method for setting a call timeout (everything from connect to reading the response body), but this has a default value of 0 (no timeout) and React-Native doesn't allow users to change that. More on okhttp timeouts here
My question is whether this can be the cause of our worries and whether it should be reported to React-Native as a bug. Lets assume the following case:
app makes an API call to a resource
okhttp is able to connect to the resource within specified timeout limit (default 10s)
okhttp is able to write the request body to the server within timeout limit (10s)
server processes request but for some reason it fails to start sending a response to the client. I guess there could be many reasons for this like server being disconnected, server crashing or server simply losing the connection to the client without the client noticing it. As there is no timeout here, okhttp will happily wait for days on end for the server to start responding to the request.
Am I missing something here or misunderstanding how timeouts work in okhttp? Is there another, perhaps better solution than implementing the ability for developers to set callTimeout on API calls performed on android? And also, isn't it a bit stupid that developers cant set their own write and read timeouts? Cant this lead to unexpected behaviour when you want to send large amounts of data in either direction on a slow connection? 10s is quite long, but perhaps not long enough for all use-cases.
Thanks for your help in advance!

Related

Blazor server disconnect when chrome mobile is in background

I developed a blazor server app which works fine on a desktop, and now i test her on the mobile platforms.
I met problem with the signalR connection when i put the browser in the background.
When i go back, if its enough fast, i have the message
"Attempting to reconnect to the server" x/8, and after it reconnect after maybe 15 seconds (which is too much), and if its like 5 minutes later im totally disconnected and i have to relaunch the app.
i found some documentation about that but nothing consistent. Because of blazor, the client configuration and event (in js) seem different than the classic signalr client, and for the server im beeing lost between the different timeout.
I try find a way to configure both server and client to manage a "sleeping" connection (ok if im disconnect after 20 minutes but i want at least be able to reconnect until 20 minutes of inactivity), but its really hard to test because im unable tu reproduce this behavior in development in my laptop.
I see some solution on internet who suggested make document.location.reload()
Blazor.defaultReconnectionHandler._reconnectCallback = function(d) {
document.location.reload();
}
But its not a solution for me as i don't want to lost everything in session.
thanks for your suggestion and help !
for those stuck into this same kind of problems, i was able to manage this by play with the signalr options described here : https://learn.microsoft.com/en-us/aspnet/core/blazor/fundamentals/signalr?view=aspnetcore-5.0&pivots=server
actually it was not really a mobile problems because i had the same kind of behavior by putting a laptop on sleep more than 3 minutes.
The 3 minutes expiration period was coming from this parameter
DisconnectedCircuitRetentionPeriod 3 minutes Maximum amount of time a disconnected circuit is held in memory before being torn down.
i just increase the time of this parameter and when the mobile/laptop go out of sleep it able to reconnect.
the blazor documentation is not really clear about that

Disable retrying of POST request via AJAX if connection was dropped

Problem
Sometimes important HTTP POST requests sent with AJAX got duplicated so several entries of the same data got created in the production database, that is of course not supposed by users.
What is important is that users have a poor internet connection and this request is taking a long time (9-20 seconds). We can't reduce this time because it is the requirements of business logic.
Requests are sent with http, not https.
Details
We have Apache/2.4.18 (Ubuntu) with PHP module loaded and two frontends: one for desktop (AngularJS) and one for mobile (React) devices. AngularJS is sending requests with the $http service, and React is using whatwg-fetch (tried whatwg-fetch-timeout also).
We know from Apache access.log and PHP logs that the same request is coming from the client several times and PHP processes them without the errors. But! These requests have response with 200 status code, %b > 0, and %O = 0, that means request is aborted before a response is sent (Apache logging format docs).
Reproduce
So we tried to reproduce and the same happens sometimes. The following case is just a reproduced case, but this happens on mobile devices (iPhones and Android phones) with different browsers installed. Also, we have repeated it in the Firefox under Windows.
Environment: Windows; both Chrome and Firefox; React frontend version; no proxy used.
That's what we found out: Google Chrome identifies the request as "Stalled", but is internally trying to send the request multiple times (and it is received and processed on the server actually), because it got the network error (ERR_CONNECTION_CLOSED). Only when the browser succeeded to fetch the response, it stops sending the repeating requests.
Gathered info
URL_REQUEST event log from chrome://net-internals/help.html#events (headers are also available there)
Google Chrome dev tools request screenshots:
Headers tab
Timeline tab
I personally can't reproduce this even once and I suppose a good internet connection is a reason for this.
I have googled a lot and even found some similar Chromium bugs, but nothing exactly about this problem.
Thank you in advance for any useful information.
I am also not pretty sure which tags should I set for this question, so if I should add or remove some, please tell me.

how do I get libnice to stop candidate checking

I am using libnice on a C++ native server which is trying to make a WebRTC peer connection to a web browser client app. Using libnice, the candidate gathering is successful and the Offer/Answer exchange is successful. It then proceeds with the checking stage which is also successful. I can see in Wireshark that the STUN request/response exchanges are also successful.
However, the candidate checking keeps going on and on, constantly sending/receiving the successful STUN requests/responses.
It is not obvious to me, and the example code does not show, how to actually stop the candidate checks when they have succeeded. I have called the API routine: nice_agent_attach_recv() and registered the callback but it does not seem to fire. And even if it did, the callback signature does not give me any clue as to how to process any of the data.
Question: what processing should be done in the ice_agent_attach_recv() callback?
Thanks,
-Andres
No processing in the callback should need to be done. You would need to call nice_agent_get_local_candidates() and then continue with credentials and so on. There is a decent example here in the reference manual.

GCM chrome notifications not being received

I am developing a chrome extension to which I was pushing notifications so far successfully from my server. However, the notifications suddenly stopped working. I can see that my POST to https://www.googleapis.com/gcm_for_chrome/v1/messages is answered with a 204 so its not my server code.
I am sure I have not hit the 10k per day limit because I would be seeing a completely different code otherwise.
I have a few questions:
Is there a rate limit that I may be hitting?
Is it possible that I have spammed the google server too much and am being blocked?

OnDisconnected method in singalr

I'm using singalr library to develop a real time notification web site using MVC 4.
My web app will run on several web servers so I need to manage connections using a db.
Every thing goes Ok exept that the OnDisconnected method is not fireing in all web browser.
It seems to work fine with firefox but using IE9 and all mobile browsers it nevers fires.
So here's my question, I don't won't to rely on this method and end up with lots of unused connections in my db. Besides, even if the Ondisconnected method will work find there is a chance that the server will go down and these unused connection will remain in the db.
I was thinking of a background method that will run every 1 minute let's say and compare the db's connections against the current connections.
The problem is that I don't know how to implement that or is it the best way to do so.
Is there a way to get all valid connection so I can compare with the db?
Thanks in advance
The OnDisconnected method should ALWAYS fire for every browser. However, when the OnDisconnected method fires may vary.
Here is the process that SignalR goes through when triggering the OnDisconnected method:
SignalR binds to the unload event of the browser and attempts to send an AJAX request to the server to notify it that the client is going away (disconnecting). IF that AJAX request successfully reaches the server the OnDisconnected method will be triggered immediately. IF that AJAX request fails to reach the server due to network conditions or other unseen conditions then the OnDisconnected will not fire UNTIL the ConnectionTimeout (configuration) has elapsed.
Soooo long story short, OnDisconnected should always eventually fire for every client and every browser. If it does not you should absolutely file an issue on GitHub.
Hope this helps!