I am using Google Drive javascript api V2 to download files. This has been working just fine for some time but today it is failing, returning status 0 with a blank response text. Looking at the network calls, I can see that I am authenticating successfully and navigating to the correct folders and retrieving a list of files but it will no longer download those files.
Looking deeper, I can see the initial response to each file download returns a status 307 (temporary redirect) and a redirect location in the response header. The browser automatically processes the location with a new request header but I do not get a response with any content, rather just an error with the status 0.
Is there a specific reason for the status 307 and is there a special way in which they should be handled?
This is the code used to download:
// Download file contents
downloadFile: function ( fileItem, callback ) {
var me = this,
accessToken,
xhr;
if ( fileItem.downloadUrl ) {
accessToken = gapi.auth.getToken().access_token;
xhr = new XMLHttpRequest();
xhr.onerror = function () {
callback( { error: { code: xhr.status, message: xhr.statusText } } );
};
xhr.open( 'GET', fileItem.downloadUrl, true );
xhr.setRequestHeader( 'Authorization', 'Bearer ' + accessToken );
xhr.overrideMimeType( "application/json" );
xhr.onreadystatechange = function () {
var DONE = this.DONE || 4;
if ( xhr.readyState === DONE ) {
if ( xhr.status === 200 ) {
callback( xhr.responseText );
} else {
callback( { error: { code: xhr.status, message: xhr.statusText } } );
};
};
};
xhr.send();
} else {
callback( { error: { code: "?", message: "Downloaded URL not specified" } } );
};
},
I am closing this question despite not getting a resolution. I have updated my code to use v3 of the Google Drive api and have got it working using that.
Strangely, if I used the HTTP request Url 'https://www.googleapis.com/drive/v3/files/<fileId>' it still didn't work but if I used the command:
gapi.client.drive.files.get( {
'fileId': fileItem.id,
'alt': 'media',
'mimeType': fileItem.mimeType
});
it works okay.
Not sure what Google have done as my previous code had been working for a couple of years without any change my end but at least I am back up and running again.
Related
I'm having trouble getting a response from a callback uri and I would really appreciate any help you could give me.
I am trying to use the Fitbit API which requires you to use a callback url to get an Auth Code.
Workflow:
1. Go to Fitbit url to get user to allow the app access to their personal data.
2. User agrees to the conditions
3. User gets redirected to my API
4. The API returns the code from (Code is located in URL and I can access it)
5. I console.log the code out to verify it
6. API returns the code
7. I work with code then exchanging it for an access token.
The problem is that I don't return the code (Or anything )when I return to the app even though I can console.log it on the API. The response I get is NULL
Here is the URL:
url = "https://www.fitbit.com/oauth2/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=https://REDIRECT_URL&scope=activity%20heartrate%20location%20nutrition%20profile%20settings%20sleep%20social%20weight&expires_in=604800";
I then open the URL in the InAPPBrowser successfully:
if (url !== "") {
const canOpen = await Linking.canOpenURL(url)
if (canOpen) {
try {
const isAvailable = await InAppBrowser.isAvailable()
if (isAvailable) {
const result =InAppBrowser.open(url, {
// iOS Properties
dismissButtonStyle: 'done',
preferredBarTintColor: 'gray',
preferredControlTintColor: 'white',
// Android Properties
showTitle: true,
toolbarColor: '#6200EE',
secondaryToolbarColor: 'black',
enableDefaultShare: true,
}).then((result) => {
console.log("Response:",JSON.stringify(result))
Linking.getInitialURL().then(url => {
console.log("Tests: ",url)
this._setTracker(url as string);
});
})
} else Linking.openURL(url)
} catch (error) {
console.log("Error: ",error)
}
}
}
From here the URL opens successfully.
Here is the API now which is done in Typescript on AWS serverless and Lambda
export const handler: APIGatewayProxyHandler = async (event, _context, callback) =>{
let provider = event.path
//prints code
let x = event.queryStringParameters
console.log("Code: ",x)
const response = {
statusCode: 200,
body: "Success"
};
return response;
}
Please let me know if further detail is required?
Thank you!
Right so it turns out what I was doing was correct apart from the response should have been 301 which is a redirect response.
const response= {
statusCode: 301,
headers: {
"location": `app://CALLBACK RESPONSE ADDRESS?type=${provider}`
},
body: "Boom"
}
I'm trying to make an ajax request to a resource on the same domain. Under certain circumstances the request gets redirected(303) to an external resource. The external resource supports CORS.
In browsers like Chrome, Firefox or Safari the request succeeds.
In IE11 the request fails with error:
SCRIPT 7002: XMLHttpRequest: Network Error 0x4c7, The operation was canceled by the user
The ajax request is made with jQuery:
$.ajax({
url: "/data",
type: "POST",
dataType: "json",
contentType: "application/json;charset=UTF-8",
data: JSON.stringify({name: 'John Doe'})
}).done(function () {
console.log('succeeded');
}).fail(function () {
console.log('failed');
});
I've build a little example which demonstrates the problem. You could see the code here.
w/o redirect
w/ redirect
Is there a way to solve this problem? What am I missing?
In the initial definition of the CORS-standard, redirects after a successful CORS-preflight request were not allowed.
IE11 implements this (now outdated) standard.
Since August 2016, this has changed, and all major browsers now support it (Here's the actual pull request).
I'm afraid to support <=IE11 you'll have to modify your server-side code as well to not issue a redirect (at least for <=IE11).
Part 1) Server-side (I'm using node.js express here):
function _isIE (request) {
let userAgent = request.headers['user-agent']
return userAgent.indexOf("MSIE ") > 0 || userAgent.indexOf("Trident/") > 0
}
router.post('data', function (request, response) {
if (_isIE(request)) {
// perform action
res.set('Content-Type', 'text/plain')
return res.status(200).send(`${redirectionTarget}`)
} else {
// perform action
response.redirect(redirectionTarget)
}
})
Part 2 Client-side
Note: This is pure Javascript, but you can easily adapt it to your jQuery/ajax implementation.
var isInternetExplorer = (function () {
var ua = window.navigator.userAgent
return ua.indexOf("MSIE ") > 0 || ua.indexOf("Trident/") > 0
})()
function requestResource (link, successFn, forcedRedirect) {
var http
if (window.XMLHttpRequest) {
http = new XMLHttpRequest()
} else if (window.XDomainRequest) {
http = new XDomainRequest()
} else {
http = new ActiveXObject("Microsoft.XMLHTTP")
}
http.onreadystatechange = function () {
var OK = 200
if (http.readyState === XMLHttpRequest.DONE) {
if (http.status === OK && successFn) {
if (isInternetExplorer && !forcedRedirect) {
return requestResource(http.responseText, successFn, true)
} else {
successFn(http.responseText)
}
}
}
}
http.onerror = http.ontimeout = function () {
console.error('An error occured requesting '+link+' (code: '+http.status+'): '+http.responseText)
}
http.open('GET', link)
http.send(null)
}
its already answered - have a look - https://blogs.msdn.microsoft.com/webdev/2013/10/28/sending-a-cors-request-in-ie/
Newbie to this - This code is works - in that the call to the script does what it is supposed to but returns the condition 500 and I can not see why. I am looking for any suggestions or changes that I should be making to make this work.
Thanks to all who respond.
function get_update_odometer(vehicle_key,odometer_value){
var url = "[%Catalyst.uri_for('/invoice/dispatch_util/get_update_odometer')%]";
new Ajax.Request(url, {
method: 'get',
parameters: {
key: vehicle_key,
ovalue: odometer_value
},
asynchronous:false,
onSuccess: successFunc,
onFailure: failureFunc
});
var return_v = $('rcontainer').innerHTML;
document.getElementById('odometer').value = return_v;
return true;
}
function successFunc(response){
if (200 == response.status){
var container = $('rcontainer');
var content = response.responseText;
container.update(content);
}
}
function failureFunc(response){
alert("Call has failed " + response.status );
}
Error code is coming from server side, and you provided the client part.
So have a look if your server script get_update_odometer is working, is callable by your web server and etc ...
Here is my code.
I know it's pointing to localhost. However, it should 404 for you. If you can get it to 404, you're ahead of me.
I have used IE9's debugging console and I can get upto right before the "xdr.open()" call.
I do not see anything in the net panel. Please help.
$('body').on('click','.click',function() {
if (window.XDomainRequest) {
xdr = new XDomainRequest();
xdr.onload = function() {
xdr.contentType = "text/plain";
alert('load');
};
xdr.onerror = function() {
alert('error');
};
xdr.onprogress = function() {
alert('progress');
};
xdr.ontimeout = function() {
alert('timeout');
};
xdr.timeout = 10000;
alert('Preparing to open connection...');
xdr.open( 'GET', host + '/bookmarklet/saveData/' );
alert('If you see this message, the connection is opened');
xdr.send( ( s.hasContent && s.data ) || null );
alert('If you see this message, the data has been sent!');
}
});
EDIT: corrected a typo from copy/paste around xdr.setTimeout -- still doesn't work?
I was sending the access-control-allow-origin: * header twice (once in .htaccess, once in php script)
Check "Raw Headers" not just "headers" using chromebug ;)
I've got a piece of code that look like this.
app.get('/auth/facebook', function( request, response ) {
if( request.session.user ){
response.render( 'index.jade' );
} else {
request.authenticate(['facebook'], function(error, authenticated) {
if( authenticated ) {
request.session.user = request.getAuthDetails().user;
response.writeHead(303, { 'Location': "/auth/facebook" });
}
});
}
});
If there is a user in session it will render the page, if not it will get a user from Facebook and store that in a session variable and reload the page... and render it. It works perfectly fine. But I want to trigger that piece of code via AJAX and do something like this:
app.get('/auth/facebook', function( request, response ) {
response.contentType('application/json');
if( request.session.user ){
response.send(JSON.stringify({'authenticated':true}));
} else {
request.authenticate(['facebook'], function(error, authenticated) {
if( authenticated ) {
request.session.user = request.getAuthDetails().user;
response.writeHead(303, { 'Location': "/auth/facebook" });
} else {
response.send(JSON.stringify({'authenticated':false}));
}
});
}
});
But that doesn't work. It says "Can't use mutable header APIs after sent" and puts it self in an endless loop saying "Can't render headers after they are sent to the client." over and over again.
Am I going about this the wrong way? I want my server code to connect with Facebook without the need of a page reload.