Call to realtime.loadAppDataDocument fails when realtime.load works? - google-drive-api

After calling realtime.loadAppDataDocument I receive the error:
XMLHttpRequest cannot load https://drive.google.com/load?
access_token=ya29.AHES6ZRoDqY0PmpHlbUjniB8wIl… Kzw
&id=1xAp1SMlamIfjnUGO9pDwfNF5IphdtnZsCw36KalJss27wy00LJ-rCN9MpcHMx408Xg.
Origin http://localhost:4567 is not allowed by Access-Control-Allow-Origin.
However if I call realtime.load with a fileid it works. See code extract below
if (fileId === null) {
// this call fails
gapi.drive.realtime.loadAppDataDocument(onFileLoaded, initializeStorageModel, handleErrors);
} else {
// this call succeeds
gapi.drive.realtime.load(fileId, onFileLoaded, initializeStorageModel, handleErrors);
}
Variables being used before this point (passed to google for the access token):
LOAD_APIS = 'auth:client,drive-realtime,drive-share';
SCOPE = [
'https://www.googleapis.com/auth/drive.appdata',
'https://www.googleapis.com/auth/drive.file'
];
LOAD_CLIENT_APIS = ['drive', 'v2'];
Does anyone know how to get the method realtime.loadAppDataDocument to work?
Update: I think the request may be actually receiving a 401 response (but because the CORS header isn't sent with the 401 response the Access-Control-Allow-Origin error is called)

Google pushed some changes to the Realtime API which has fixed the problem.

Related

Why am I getting an empty response back from UrlFetchApp in Google Apps Script?

I am trying to make a GET request to an external API from a Google Apps Script using UrlFetchApp. When I make this request with Postman or curl, I get back the expected response. However, when I try it with UrlFetchApp, I get back an empty response, {}.
I have tried using Basic Auth and OAuth 2, as well as explicitly setting the oauthScopes property in the manifest as described here.
I have confirmed with the API team that they are indeed sending back a full response when I hit the endpoint, but all I receive is {}. My problem seems similar to this StackOverflow question which went unanswered.
var headers = {
"X-Client-Key": "KEY",
"Authorization": "Bearer TOKEN"
};
var options = {
method: "get",
headers: headers,
}
var response = UrlFetchApp.fetch(ENDPOINT, options);
console.log(JSON.stringify(response)); // returns {}
Do not take what you see in logs at face value. fetch method of the UrlFetchApp service always returns an instance of HTTPResponse which is an object first and foremost. This is what the logs show you (I am assuming you are logging the response because this is the only context I am aware of where {} is displayed).
To extract useful information from the response, use the appropriate methods exposed on HTTPResponse instances, like getResponseCode or getContentText.

getResponseCode() method doesn't return expected response code

I have 2 questions about Google App Script Services getResponseCode() method.
1) "Unexpected Error"
When I run the getResponseCode() method, I got "Unexpected Error...".
https://developers.google.com/apps-script/reference/url-fetch/http-response#getResponseCode()
var response = UrlFetchApp.fetch(url, {muteHttpExceptions: true});
responseCode = response.getResponseCode();
Unexpected error: https://www.example.com/
※I can't tell the url for business reasons.
HTTP response status codes don't include "Unexpected Error".
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
Please tell me what response codes actually return, when this error occurs?
2) getResponseCode() method didn't work as expected
When I run the code below, I got "200".
I expected "301" in response to the "http://google.com/" request.
function myFunction() {
var response = UrlFetchApp.fetch("http://google.com/");
 Logger.log(response.getResponseCode());
}
I think getResponseCode() method doesn't return actual http status codes.
Please tell me why I got "200" instead of "301".
get 301 response in browser
get 200 response instead of 301
This happens because the request is following the redirect. Take a look at the available parameters in the UrlFetchApp.fetch() method. You'll see followRedirects, which defaults to true.
Make this small change and you'll get the expected 301.
function myFunction() {
var response = UrlFetchApp.fetch("http://google.com/", { followRedirects: false });
 Logger.log(response.getResponseCode());
}

StackExchange API authentication in Google Apps Script

I'm trying to use the V2.2 of StackExchange API in Google Apps Script.
The problem comes in the last step of the explicit OAuth 2.0 flow, when I try to send the POST request to obtain the access token. I receive a 404 error, but making the same request manually (using postman extension) everything is ok.
To simplify the problem, if I send this POST request with no payload I receive the same 404
var response = UrlFetchApp.fetch("https://stackexchange.com/oauth/access_token", {
method: 'post',
muteHttpExceptions: true
});
Logger.log(response);
while in postman I receive this 400:
{
"error": {
"type": "invalid_request",
"message": "client_id not provided"
}
}
I guess this will be a problem with UrlFetchApp, but does anyone know how to solve it? Thanks!
The problem is related with the Origin header.
You cannot remove from the header directly but you can perform the call via a proxy :)
You need to provide the data for the post by adding an 'option' object to the call.
For example:
var options = { "method" : "post", "payload" : payload };
UrlFetchApp.fetch("https://stackexchange.com/oauth/access_token", options);
Btw, have you tried you use the OAuth that UrlFetch got: https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app#addOAuthService(String) - It might be better way.

Im getting unexpectected token : for a valid JSON

I am working with ArcGIS, Esri request and I am trying to get a data from a webserver, but everytime I got the same "unexpected token : " error even when my response is correct.
Thanks in advance.
Here's my code:
require(["dojo/dom", "dojo/on", "dojo/dom-class", "dojo/_base/json", "esri/urlUtils", "esri/config", "esri/request", "dojo/domReady!"], function(dom, on, domClass, dojoJson, urlUtils, esriConfig, esriRequest) {
// fallback to proxy for non-CORS capable browsers
// esri.config.defaults.io.proxyUrl = "/arcgisserver/apis/javascript/proxy/proxy.ashx";
esriConfig.defaults.io.proxyUrl = "/proxy/proxy.ashx";
dom.byId("url").value = "http://api.citybik.es/v2/networks/dublinbikes";
dom.byId("content").value = "";
//handle the Go button's click event
on(dom.byId("submitRequest"), "click", getContent);
function getContent(){
var contentDiv = dom.byId("content");
contentDiv.value = "";
domClass.remove(contentDiv, "failure");
dom.byId("status").innerHTML = "Downloading...";
// //get the url
// var url = urlUtils.urlToObject(dom.byId("url").value);
// console.log("EL URL path",url.path)
// console.log("EL URL query",url.query)
// var requestHandle = esriRequest({
// "url": url.path,
// "content": url.query
// });
// requestHandle.then(requestSucceeded, requestFailed);
function requestSucceeded(data) {
console.log(data);
}
function requestFailed(error) {
console.log("Error: ", error.message);
}
var request = esriRequest({
url: "http://api.citybik.es/v2/networks/dublinbikes",
content: {
format: "json"
},
handleAs: "json",
callbackParamName: "retrive"
});
request.then(requestSucceeded, requestFailed);
}
}
);
Im getting:
Uncaught SyntaxError: Unexpected token : dublinbikes:2
The root problem is that you're getting esri.request a bit confused with what you're asking for, and what the server is giving back. Because you're making a request on a different domain (api.citybik.es) from where you're running the code (whatever your host is), you need to use either:
CORS
JSONP
a proxy
to get around the browser's security restrictions. There's plenty of detail on SO about these, I won't dribble on further.
Your code has two methods configured - the callbackParamName tells esri.request to use JSONP, and you've also got a proxy set just in case. The callbackParamName tells it to only use JSONP though, so the proxy is ignored.
Now the real problem, as I noted in a comment above, is that v2 of the CityBikes API doesn't actually seem to support JSONP, so your callback parameter is ignored and the server gives you back straight JSON. esri.request is expecting JSONP, and voila - unexpected token :. Requesting
http://api.citybik.es/v2/networks/dublinbikes?callback=stackoverflow
returns:
{
network: {
company: "JCDecaux",
href: "/v2/networks/dublinbikes",
....
See? No mention of our stackoverflow variable. If you look at v1 of the API instead, that DOES support JSONP. Requesting
http://api.citybik.es/dublinbikes.json?callback=stackoverflow
returns:
stackoverflow(
[
{
bikes: 1,
name: "Fenian Street",
idx: 0,
....
...and there is our stackoverflow variable. OR you can remove the callbackParamName from your esriRequest, and see if your proxy will process the JSON from the v2 address.

json response callback load store extjs

I have a JSON store that load data from a PHP script. This script call a Web Service and sometimes it get some errors and I need to capture them and show them in my app.
In my script I print this line when I get an error:
echo '{"success": "false", "error": "'.$res->state->Description.'"}';
In my app I have this code to load the store
targheStore.load({
params: { targa: searchForm.getValues().targa },
callback: function(records, operation, success) {
Ext.getBody().dom.style.cursor = "default";
if(!success){
$("#message2").slideDown('fast');
setTimeout(function() {
$("#message2").slideUp('medium')
}, 2700);
}
}
});
The jQuery code is to show a message "No record found" from the top, but I want to show the error message that I receive from json.
Inside of the operation argument is a request and response object. Use the response object as you would any Ajax response should allow you to handle your messages the way you'd like.
I suggest declaring a globally available handler for processing operation to look for JSON.parse(response.responseText).hasOwnProperty("error") and doing your custom operation in that way.
If you're not using JSONP for communication you can stuff your message in the raw text returned from an HTTP error code (400+) and the {error:} handler in your ajax would be the best way to route errors.