Axios timeout not working as expected on limited hotspot - android

I am using axios for one of my react native project. Here's my config and executing code:
const config = {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
timeout: 30000
};
var response = await instance.get(route, config);
Here is my testing scenario. I have two phones, A and B. From phone A I open my wifi and also create a hotspot. From phone B I connect to that hotspot. Now I turn of wifi on phone A which has hotspot on. For phone B network is available but it shows as limited.
Now if I place an HTTP using above axios configuration, it never times out after 30 seconds for Android devices. But for iOS devices it works as expected. Why?

It happened with me and i solved it manually by doing the following
let source = axios.CancelToken.source();
setTimeout(() => {
source.cancel();
// Timeout Logic
}, 30000);
const config = {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
timeout: 30000,
//Add this
cancelToken: source.token,
};

The problem I ran into with Hassan's solution is that even though the request did get cancelled, I was using the same token to cancel all requests, so afterwards every request was immediately cancelled, without even attempting. This broke my app.
I solved this using a request interceptor:
const myInstance = axios.create(config);
const myTimeoutLimit = 15000;
const guaranteeTimeout = (config) => {
config.cancelToken = new axios.CancelToken((cancelRequest) => {
setTimeout(() => cancelRequest('Optional message'),
myTimeoutLimit);
});
return config;
};
myInstance.interceptors.request.use(guaranteeTimeout);
So you basically create a new token per request, if the request takes more than your defined limit, we cancel that particular request.
Axios documentation

Related

Fetch DELETE method on Android (React Native)

I make several requests from a React Native app to an API. Every request works fine both on iOS and Android except the DELETE method that does not work on Android. The call is correctly made, it goes through the API and the objects are deleted. But instead of getting the response, the call falls under the catch statement with [TypeError: Network request failed]. This does not happen in iOS.
Some people with the same problem were missing 'Content-Type': 'application/json' on the request headers which is not my case.
This is happening both locally, in testing and production stages (using an ip instead of localhost will do nothing).
The request is also successfully performed in Postman.
What can it be?
React Native 0.63.5
export const deleteApi = async (api: string, body?: any) => {
const userResponse = await getUserCredentials();
const authState = await getAuthState();
let response = await fetch(api, {
method: 'DELETE',
headers: await getHeaders(userResponse, authState),
body: JSON.stringify(body)
});
if (response.status === UNAUTHENTICATED_CODE)
response = await interceptor(response, userResponse, {
api: api,
method: 'DELETE',
body: body
});
return response;
};
leaveClass = async (
uuid: string,
onSuccess: () => void,
onFailure: (error: string) => void,
) => {
this.setLoading(true);
try {
const api = LEAVE_CLASS_API_PREFIX + uuid + LEAVE_CLASS_API_SUFFIX;
const response = await deleteApi(api);
if (response.status === SUCCESS_STATUS_CODE) {
onSuccess();
}
else {
const jsonResponse = await response.json();
if (jsonResponse.detail) onFailure(jsonResponse.detail);
else onFailure(translations.SOMETHING_WENT_WRONG);
}
} catch (error) {
console.log('leaveClass error: ', error);
}
this.setLoading(false);
};
You can use a network plugin for Flipper (https://fbflipper.com/docs/setup/plugins/network/), copy your request from it as a curl, and try to perform it from your terminal or postman. If it has the same error, the problem is not in React Native.

How to pass parameters in url using google cloud functions

I am using http calls to call a cloud function.
I have a URL in the form
url: 'https://api.shipengine.com/v1/labels/rates/rateid,
Now I need to pass values dynamically in rated whenever the function call happens.
How to pass the value into that URL.
I am attaching my cloud function too.
exports.shipmentlabelwithreturnid = functions.https.onRequest((req, res) => {
var request = require("request");
var rateid = req.body.RateId;
console.log(rateid);
var options = { method: 'POST',
url: 'https://api.shipengine.com/v1/labels/rates/'+ rateid,
headers:
{ 'content-type': 'application/json',
accept: 'application/json'
}
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
});
You should use promises, in your Cloud Function, to handle asynchronous tasks. By default request does not return promises, so you need to use an interface wrapper for request, like request-promise which "returns a regular Promises/A+ compliant promise", as follows:
....
const rp = require('request-promise');
exports.shipmentlabelwithreturnid = functions.https.onRequest((req, res) => {
var rateid = req.body.RateId;
console.log(rateid);
var options = { method: 'POST',
uri: 'https://api.shipengine.com/v1/labels/rates/'+ rateid,
headers:
{ 'content-type': 'application/json',
accept: 'application/json'
}
};
rp(options)
.then(response => {
console.log('Get response: ' + response.statusCode);
res.send('Success');
})
.catch(err => {
// API call failed...
res.status(500).send('Error': err);
});
});
Also, it is important to note that you need to be on the "Flame" or "Blaze" pricing plan.
As a matter of fact, the free "Spark" plan "allows outbound network requests only to Google-owned services". See https://firebase.google.com/pricing/ (hover your mouse n the question mark situated after the "Cloud Functions" title)
Since https://api.shipengine.com is not a Google-owned service, you need to switch to the "Flame" or "Blaze" plan.
On the fact that you have to use promises to handle asynchronous tasks, I suggest that you watch these videos from the Firebase team: https://www.youtube.com/watch?v=7IkUgCLr5oA&t=28s and https://www.youtube.com/watch?v=652XeeKNHSk which explain this key concept.

Network request in react native fails after two minutes

I am having some trouble using couchdb in react native. See code below :
const urlcouchdb = 'http://192.168.58.1:5984';
export const login = async (name, password) => {
const response = await fetch(`${urlcouchdb}/_session`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name,
password,
}),
}).catch(function(error) {
console.log("error = " + error);
return error;
});
if (
response.headers &&
response.headers.map['set-cookie'] &&
response.headers.map['set-cookie'][0]
) {
await AsyncStorage.setItem(
'cookiecouchdb',
response.headers.map['set-cookie'][0],
);
}
return response.json();
}
At first, I was using my localhost IP (127.0.0.1), and I was getting this error : TypeError: Network request failed.
After some researches, I've figured out I'd better change it to the IP address of system. I thought my problem was solved, because I was not getting the error anymore, but it turned out that I was still getting the same error, but two minutes (approximatly), after doing the request!
It's very annoying to wait two minutes every single time I try to solve it. Do you have any idea why my request fails?
Just to let you know : The name and password I send to login function are correct. Also, I am testing on my android device, using expo.

Why network call fails after the internet comes back in react native android application?

I am working with react native Android application. I am calling API using fetch and axios lib. There is some issue while the internet goes down and comes back. The API call gets failed but the internet is there.
This how I'm doing the fetch call.
fetch(Url,{
timeout: config.apiFetchTimeOut,
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
tenantName: this.props.config.tenantName,
'tekion-api-token': this.props.config.access_token,
dealerId: this.props.config.dealerId,
clientID: 'console',
}},)
.then(response => {
console.log("response",response)
NativeModules.NativeOTTModule.logger('Ping Api Response=> '+JSON.stringify(response));
let apiSuccess = JSON.parse(response._bodyInit).meta.code;
if(apiSuccess===200){
if(context.state.showIcon){
context.setState({showIcon:false});
context.stopRebootTimer();
}
}
})
.catch(error => {
console.log("ping error",error)
})

axios post request working in React Native ios but not in android

I know there many answers regarding to this question but I can't seem to find one that works for me. I'm sending a post request to my server using axios but it does not work in android although it does in ios. I'm currently using server ip address (not localhost), and I'm also sending headers when request but it is still not going through the network request for android.
import axios from 'axios';
const SERVER_URL = 'http://serverip:3000';
export function signin({ username, password }) {
return function(dispatch) {
axios.post(`${SERVER_URL}/user/authenticate`, { username, password }, { headers: { 'Content-Type': 'application/json' } })
.then((response) => {
console.log('login response', response);
dispatch({
type: USER_AUTH,
});
AsyncStorage.setItem('token', response.data.token || '');
})
.catch((response) => console.log('user sign in err', response));
};
}
Has anyone had similar issue like myself and know how to make this work?
Thank you,
Set header to
headers: {
Accept: 'application/json',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
},

Categories

Resources