Problem
Cypress returns timeout while the GET request is complete.
Description
GET request using Cypress.io
I should receive large (over 15Mb) response body from the API, but i have this:
"CypressError: cy.request() timed out waiting 300000ms for a response from your server."
Increasing the "responseTimeout" didn't help...
I also checked the same request in POSTMAN and it ending up with success, always in maximum 50 seconds.
Logs shows us that the request which is timed out in cypress is actually finished, so I suppose this is the cypress issue
EDIT: there are examples of my code, I already tried to do something with "async" but timeouts are still occurring. Usually every second test is failing with timeout but it is not the rule.
commands.js:
Cypress.Commands.add('getRequestLimit', (token, limit) => {
cy.request({
failOnStatusCode: false,
url: '/endpoint',
headers: {
'Authorization': 'Bearer '+token
},
qs: {
'limit' : limit,
}
})
});
cypress.json:
{
"baseUrl": "url",
"chromeWebSecurity": false,
"video": false,
"numTestsKeptInMemory": 0,
"responseTimeout": 500000,
"pageLoadTimeout": 500000
}
test file:
it('Check query param "limit"', () => {
const limit = 3;
cy.getRequestLimit(token, limit)
.then((response) => {
expect(response.status).to.eq(200);
});
});
it('Check query param "offset"', () => {
const offset = 3;
cy.getRequestOffset(token, offset)
.then((response) => {
expect(response.status).to.eq(200);
});
});
This is the cypress issue, https://github.com/cypress-io/cypress/issues/6385
right now it is working fine in version 3.3.1
Try to use async/await for your api calls this can be a solution for your problem.
Doc here: async function MDN web docs
Hard to say for sure without looking on your code.
Related
I was testing get and post requests in jsfiddle to better understand cors and csrf.
const data = { name: 'example', password: 'password'};
fetch('http://localhost:3001', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then((response) => response.json())
.then((data) => {
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
const express = require('express')
const app = express()
app.get('/', (req, res) => {
res.send('Hi')
})
app.post('/', (req, res) => {
console.log('received')
res.send('Received')
})
app.listen(3001, () => {
console.log('Listening on port', 3001)
})
Is it normal that the first preflight request fails when doing a post request?
Also, shouldn't the successful preflight request happen before the post request? (On the server side, the code handling the post request isn't executed (nothing logged in console), which means that the browser cancelled the post request. How would the browser know not to follow through with the post request without waiting for the preflight request to complete first?)
Update:
Tried it using a simple html page instead of jsfiddle and the preflight request doesn't fail, but it still happens after the fetch request
Edit:
Only one options request is received on the server
// debugging middleware, should be first router handler of any kind
let requestCntr = 0
app.use((req, res, next) => {
let thisRequest = requestCntr++
console.log(
`${thisRequest}: ${req.method}, ${req.originalUrl}, `,
req.headers
)
// watch for end of theresponse
res.on('close', () => {
console.log(
`${thisRequest}: close response, res.statusCode = ${res.statusCode}, outbound headers: `,
res.getHeaders()
)
})
next()
})
Edit 2: from console
For a get request, no network error is shown in the Network tab, but the same error appears in the console except with a status code
It seems that Chrome simply displays the preflight request with a network error in the Network tab if it's related to csrf. Since opaque GET requests are fine, this doesn't happen for GET requests. So in the case of a post request, even if "preflight" shows up twice, it's the same preflight request.
I am trying to query a quote API for a freeCodeCamp project I'm updating to React.js. I am now trying to use Fetch or Axios to query the API but it's caching the response in the browser. I know in $ajax there is a { cache: false } that would force the browser to do a new request.
Is there some way I will be able to do the same with Fetch or Axios?
The cache-control setting seems to be already set to max-age: 0 by Axios.
This is my code I have that is querying the API.
generateQuote = () => {
axios.get('https://quotesondesign.com/wp-json/posts?filter[orderby]=rand&filter[posts_per_page]=1')
.then(response => {
const { title, content, link } = response.data[0];
console.log(title, content, link)
this.setState(() => ({ title, content, link }));
})
.catch(err => {
console.log(`${err} whilst contacting the quote API.`)
})
}
Okay so I found a solution. I had to set a timestamp on the API url to get it to make a new call. There doesn't seem to be a way to force axios or fetch to disable cache.
This is how my code now looks
axios.get(`https://quotesondesign.com/wp-json/posts?filter[orderby]=rand&filter[posts_per_page]=1×tamp=${new Date().getTime()}`)
.then(response => {
const { title, content, link } = response.data[0];
console.log(title, content, link)
this.setState(() => ({ title, content, link }));
})
.catch(err => {
console.log(`${err} whilst contacting the quote API.`)
})
I added these headers to all axios requests and it's working well.
axiosInstance.defaults.headers = {
'Cache-Control': 'no-cache',
'Pragma': 'no-cache',
'Expires': '0',
};
If you do not want to disable caching for all axios requests, you can disable caching for only one request by using the following parameters in the axios call:
axios.get(
'https://YOUR-URL.com',
{
// query URL without using browser cache
headers: {
'Cache-Control': 'no-cache',
'Pragma': 'no-cache',
'Expires': '0',
},
}
)
It seems, adding timestamp is the only always working way.
If you're using Vue, for example:
const api = axios.create({
baseURL: 'https://example.com/api',
params: {
t: new Date().getTime()
}
})
Vue.prototype.$api = api
So you can use it with:
this.$api.get('items')
And it will always add different timestamp to the url, depending on current request time.
I think you just need to make the url different each time you make the axios call. Timestamp is just one way to do so. Also consider disabling or filtering service workers caching method if you are developing a PWA.
Create an instance of axios and then add timestamp to every request.
const axiosInstance = axios.create({})
axiosInstance.interceptors.request.use(
function (config) {
// Do something before request is sent
config.params = { ...config.params, timestamp: Date.now() };
return config;
},
function (error) {
// Do something with request error
return Promise.reject(error);
}
);
I'm having a problem with cors. I don't have access to the server, providing the 3rd party API, but it does use the right headers to provide me access. I know, because a native XHR request works, with just putting the authorization and client_id headers, which are required from the api to be set.
I couldn't anyhow make it work with Axios, spent 3 days on this. I'll be really glad if someone helps me out! Please look at the code I made some comments there.
This is the native XHR request, which works:
var data = "{\"birthday\":\"1981-07-07\",\"email\":\"asdiiii#mail.com\",\"phone\":\"1234578901\"}";
var xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
console.log(this.response);
}
});
xhr.open("POST", "cross-url/api/detail");
xhr.setRequestHeader("authorization", "fake");
xhr.setRequestHeader("client_id", "fake");
xhr.setRequestHeader("content-type", "application/json");
xhr.send(data);
Axios code, which doesn't work:
axios.defaults.headers.common['Accept'] = 'application/json, text/plain'
const instance = axios.create({
baseURL: 'cross-url',
// crossdomain:true, // this doesn't help
//mode:'cors', // this doesn't help too
/*
headers: {
'content-type':'application/json',
'client_id':'client_id_here',
'access-control-allow-origin':'*', // if I put this I get an error it's denied by 'access-control-allow-headers'
'Access-Control-Allow-Headers':
'Accept,Origin,Authorization,client_id,content-type,x-requested-with', // If I put this I get still an error that the header doesn't allow origin'
'Access-Control-Allow-Credentials': 'true',
},
*/
headers: {
'client_id':'fake',
},
transformRequest: [
(data,headers) => {
delete headers.common['X-CSRF-TOKEN']
console.log(data)
// return JSON.stringify(data) // this also doesn't work'
return data
},
],
});
instance.defaults.headers.common['authorization'] = 'fake';
const postData3 = {
email:'fake',
phone:'123123123',
birthday:'1981-07-07',
}
instance.post('/api/detail', postData3).then((response) => {
console.log(response)
}).catch((e) => {
console.log(e)
console.log(e.request)
})
The server determines what headers are allowed, what methods are allowed, and what hosts are allowed.
access-control-allow-xxx are a server-to-client headers, and for all practical purposes, no servers will accept them.
Concerning CORS
Remove your access-control.xxx headers and then look at the response. If denied, the server will let you know why.
If you do not have access to the server, and your host, method, and/or client-headers are denied, all you can do is use a proxy (forward your calls from the browser to an intermediate server). You will need access to some server for that however.
I am using request() in a for loop to post data to a server. Will it fail to post all data. Is there any limit of data posting rate in electron js. Here, request() mathod is of request npm module.
const request = require('request);
sendData(reqBody){
request({
url: config.dataDumpUrl,
method: "POST",
json: true, // <--Very important!!!
body: reqBody
}, async (error, response, body) =>{
if (error) {
console.log('error in data post');
}
})
}
then I call the sendData mathod in a for loop like below:
for(let i=0;i<1000;i++){
sendData(reqBody);
}
the 1000 request is done asynchronously in for loop. Will it be blocked by any maximum simultaneous request limit?.
I'm facing an issue while using react native fetch api. many times request got failure . I have a high speed connection. but many times it got failed.
that issue is happening In android,ios both.
const shoppingApi = 'myserverlink';
async function Sendshoppinapi(data) {
try {
let response = await fetch(shoppingApi, {
method: 'POST',
headers: {
'Accept': 'application/json',
'content-type':'multipart/form-data'
},
body: data
});
let responseJson = await response.json();
return responseJson;
}
catch (error) {
Alert.alert(error.toString())
}
}
export {Sendshoppinapi};
data that I sending server as post request
add_to_wishlist = (item,index) => {
{
let data = new FormData();
data.append('methodName', 'add_to_wishlist');
data.append('user_id', global.userid)
data.append('item_id', this.props.navigation.state.params.itemid.toString())
Sendshoppinapi(data).then((responseJson)=>{
console.warn(responseJson);
if(responseJson.responseCode == '200'){
this.setState({fav:false})
Alert.alert('SHOPPING','Item added to wishlist successfully.',[{text: 'OK',},],{ cancelable: false })
}
else{
this.setState({fav:false})
Alert.alert('SHOPPING','Item already .',[{text: 'OK',},],{ cancelable: false })
}
})}
}
Error that when request got failed
I've quoted an answer I used for another post - however I have added await.
You can check the status of the call, to determine perhaps why the network call failed. Try using fetch's ok to check whether the response was valid, for example:
.then(function(response) {
if (!response.ok) {
//throw error
} else {
//valid response
}
})
Using await:
let response = await fetch(url)
if (response.ok) return await response.json()
You can also access the response's status like:
response.status;
or also, statusText such as:
response.statusText;
checkout the below:
https://developer.mozilla.org/en-US/docs/Web/API/Response/statusText
https://developer.mozilla.org/en-US/docs/Web/API/Response/status
https://www.tjvantoll.com/2015/09/13/fetch-and-errors/
Use then() function with promises. (Requested code snippet)
fetch(shoppingApi, {
method: 'POST',
headers: {
'Accept': 'application/json',
'content-type':'multipart/form-data'
},
body: data
})
.then((resp) => {
return resp.json()
})
.then((resp) => {
//resp contains your json data
});
You also can make your function returns a Promise, and use it with then():
function sendShoppingApi(data) {
return new Promise((resolve, reject) => {
fetch(shoppingApi, {
method: 'POST',
headers: {
'Accept': 'application/json',
'content-type':'multipart/form-data'
},
body: data
})
.then((resp) => {
return resp.json();
})
.then((resp) => {
resolve(resp);
/*
you should also check if data is valid, if something went wrong
you can reject the promise:
if(!dataOK)
reject("error message");
*/
});
});
}
So now you can do something like this:
sendShoppingApi(data)
.then((resp) => {
//do stuff with your data
})
.catch((err) => {
//handle error
});
UPDATE
could be a duplicate of this: React Native fetch() Network Request Failed
For the case when you are running the app on the android device, the API is on a computer and both of them are on the same network I have added some possible things to check. I haven't detailed specific solutions since there are many answers on each topic.
Do a quick check with ngrok https://ngrok.com/ on the free plan to see if that works. If yes:
Make sure the API is accessible by trying to access it on the device browser (most important is to check if you allow the port at inbound rules, firewall).
If you are using HTTPS, you might get an error if your react native env is not properly configured to accept not trusted certificates, assuming you are using a non trusted one. Do a check without HTTPS, only with HTTP, to see if it's the case. https://github.com/facebook/react-native/issues/20488