Using electron to access cross-origin-resources - sharepoint-2010

I have a list on sharepoint where I am tracking tasks.
I am trying to create an electron app that will ping (http get request) this list every minute or so and display a little window with all the tasks the current user has assigned and highlight new tasks.
I am using the fetch API to access the list as follows:
const _COLLAB_ROOT = "http://company.com/projects/team-site/_vti_bin/listdata.svc/"
export function read(list, callback) {
const myHeaders = new Headers({
"Accept": "application/json",
'Authorization': 'Basic '+btoa('username:password'),
'Access-Control-Allow-Origin': '*'
});
const myInit = {
method: 'GET',
headers: myHeaders,
mode: 'no-cors'
}
fetch(_COLLAB_ROOT+list,myInit)
.then(response => {
if (response.ok) {
response.json().then(data => {
callback(data.d);
});
}
return Promise.reject(Error('error'))
}).catch(error => {
return Promise.reject(Error(error.message))
})
}
Other module:
read('listname',data => {
console.log(data);
})
However when I send this request with a list name filled in, I get the following:
Now I assume this has something to do with CORS. What I would like to know is, is there a way to get this working?
It seems like something very obvious to be required in electron.
Also I have set the we-preferences property to
mainWindow = new BrowserWindow({
width: 800,
height: 600,
frame: true,
'web-preferences': {'web-security': false}
});
Any help is appreciated here.
I will be really surprised if this is not possible so hopefully I am being dumb!
Edit: Response when querying from Restlet client on chrome

You're using the old webPreferences syntax, your constructor should look something this :)
mainWindow = new BrowserWindow({
width: 800,
height: 600,
frame: true,
webPreferences: {
webSecurity: false
}
});

It seems that it is not possible right now, since webSecurity no longer controls CORS. (for v9+)
The webSecurity option controls the web security inside blink, but
recently the control of CORS has been moved out of blink and thus the
option no longer controls CORS.
See https://github.com/electron/electron/issues/23664#issuecomment-692422997

only suitable for development
mainWindow = new BrowserWindow({width: 900, height: 680,webPreferences: {
nodeIntegration: true,
webSecurity: false
}});

Related

Vuejs axios get request always fetch new values [duplicate]

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&timestamp=${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);
}
);

Cypress timeout when response size is too large

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.

Axios CORS issue Consuming API

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.

handle network request failed in react native

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

How to set custom header for PouchDB ajax requests?

I'm using PouchDB 3.2.1.
I'm trying to set Authorization header for all ajax requests:
db.local = new $window.PouchDB(POUCHDB_NAME);
db.remote = new $window.PouchDB(COUCHDB_URI, {
skipSetup: true,
ajax: {
headers: {
'Authorization': 'Basic ' + $window.btoa('admin:admin')
}
}
});
// Replication
db.local.sync(db.remote, {
live : true,
retry: true
});
But it doesn't works. See the screenshot:
In the latest PouchDB this is the preferred way (click here for the docu):
var db = new PouchDB('http://example.com/dbname', {
fetch: function (url, opts) {
opts.headers.set('Authorization', 'token-here');
opts.headers.set('X-Some-Special-Header', 'foo');
return PouchDB.fetch(url, opts);
}
});
I think as described here, you also need to set:
{skipSetup: true}
In your constructor options.