Google Url fetch service sudenly start to fail - google-apps-script

I've been using the google code Url fetch service in a script attached to docs spreadsheet, and it had been working for more than a year. But suddenly, upon migration of docs to google drive, the service start to fail.
This is the format:
var url='xyz.com?command=xxx'
var response = UrlFetchApp.fetch(url);
The failure report keeps saying..."unexpected error", while nothing has changed in the code 4 more than a year.
Pls What should I do to put things in order?

Hurray!
I got it!
Google was the problem.
I've been using the url starting with the API server IP, and it worked fine. Now, the fetch service stopped fetching using IP address. When I attempted to use the domain name in place of the IP address, it worked fine again.
Alhamdulillah!
But it would be good if someone here knows google guys and could inform them of this anomaly. This problem started to me around the same time I was migrated to the "DRIVE" service, away from the old "DOCS".
Thanks all, and have a blessed day.

Related

Zoopla API returns <h1>Developer Inactive</h1>

I've been trying to use Zoopla's property search API a few days now. First day I used the API, it was straight forward. I registered for a new key, and could do requests via the documentation. Starting yesterday, all the requests I would do would always return a 403 response with the body <h1>Developer Inactive</h1>.
I tried creating a new API key but the problem is still the same. Is anyone using the API that can share some knowledge about it? Seems to be deprecated, but I cannot understand how I was getting results from it without issues for a single day.
https://developer.zoopla.co.uk/docs/Property_listings
Ive just hit the exact same issue, trying to create an app using the API, worked great on the first day, but since coming back to my project today it no longer works!
It appears the API is dead and no longer maintained - https://medium.com/#mariomenti/how-not-to-run-an-api-looking-at-you-zoopla-bda247e27d15
Very frustrating.
The API is in the process of getting shut down and moved to a new solution.
When signing up to the API, it does not tell you this, which is strange.
When you sign up, the API key will die after 24 hours. However, if you email help#zoopla.co.uk with your email address and API key, they will reinstate the API access.

Error on google function deploy, service account doesn't exist

Please can you help me, I'm receiving this error when I'm trying to deploy a google cloud function:
HTTP Error: 400, Default service account 'project-name#appspot.gserviceaccount.com' doesn't exist. Please recreate this account (for example by disabling and enabling the Cloud Functions API), or specify a different account.
The command used to deploy is:
firebase deploy --only functions
A temporary solution is fine, but if you can help me to solve it permanently is better.
Thanks in advance.
In my case, the App Engine default service account was deleted. It looks like this: {project_id}#appspot.gserviceaccount.com
So I had to restore the service account like this:
You can now recover the deleted service accounts from https://cloud.google.com/iam/reference/rest/v1/projects.serviceAccounts/undelete
you have to get the UniqueID of the service account from https://console.cloud.google.com/home/activity
Source: https://stackoverflow.com/a/55277567/888881
The API explorer is an easy way to use the IAM API: https://developers.google.com/apis-explorer/#p/
I was struggling to resolve this issue, then I raised a case with Google.
here is a detailed article of my learnings :
https://medium.com/#ashirazee/http-error-400-default-service-account-appspot-gserviceaccount-com-accd178ea32a
Firstly navigate to Google Cloud Platform and view your service accounts.
try and find <project_id>#appspot.gserviceaccount.com' in your list of service accounts for the firebase project, it is linked to the App Engine.
if '#appspot.gserviceaccount.com' is missing you can not deploy anything(SEE EMAIL WITH GOOGLE BELOW), if it isn't, check and see if it's enabled, try disabling it and enabling it again.
#appspot.gserviceaccount.com is pre-installed by default, regardless of a paid account or not. try and recall if at any time you may have deleted it after or before deployment.
Now if you have for any reason deleted it over a period of more than 30 days than you can not retrieve it, and you must create a new firebase project. However, if it is within 30 days you can undelete it.
EMAIL FROM GOOGLE:
Email #1
"
Hello Ali
I am checking the logs of your project, unfortunately the service account was deleted on Ma, there is no chance to recover it nor recreate it
The only workaround available is to create a new project and deploy the service desired there. I know this could not be the best option for you nevertheless it is the way this works by design.
Do not hesitate to write back if you have more questions.
Cheers,"
Email #2,
"Hello Ali
I am glad to read that you have been able to deploy your functions successfully, unfortunately that service account cannot be recovered after 30 days of being deleted and that is the only solution. If you have other questions, please let us know by contacting us again through our support channel.
Cheers,"
lastly here is a helpful command line that will help you debug this, however, it won't help if there is no service account, it'll just highlight the obvious:
firebase deploy --only functions --debug
this was my error:
"HTTP Error: 400, Default service account '<project_id>#appspot.gserviceaccount.com' doesn't exist. Please recreate this account (for example by disabling and enabling the Clo
ud Functions API), or specify a different account."
Following the error message, you could enable the API by console accessing this url and enable the api.
Or by gcloud command:
gcloud services --project <project_id> enable cloudfunctions.googleapis.com
As the other stated, sadly, you need to use the default service account.
If within the 30 days period, you can use this tutorial to find and undelete the service acc: Read this guide to get https://cloud.google.com/iam/docs/creating-managing-service-accounts#undeleting_a_service_account
You have to enter the commands through the Google Cloud Console (one of the buttons will open a terminal on the right of the top blue app bar)
try to select Google Cloud Platform (GCP) resource location in Setting of Firebase. enter image description here

Google Drive API oauth2 hangs on live server and returns no error when authenticating with auth_code

I have a huge problem where absolutely no error is returned from google nor php.
I've written a google client oauth2 connect model, which is perfectly working when I'm running it on my dev environment on my mac (I'm not using a simple localhost, it's actually vagrant what I'm using to mirror the production server as much as possible) but it doesn't work when I push it to production.
It's just simply not returning any error. The code reaches the part where I have the auth code from Google and it hangs at the part where I'm trying to exchange it for a token ( $client->authenticate($auth_code) ).
I really don't know what am I doing wrong, since everything is working perfect without errors on dev site (which has a public link by the way, and I tried accessing it from different public IP addresses).
The moment I push the code to a live server, it just stops authenticating. I have the correct oauth credentials set up for every production server, redirect uri is correct. I simply don't know what am I doing wrong...
Here's a part of code (I repeat, it perfectly works on dev server with publicly accessible url):
$this->client = new Google_Client();
$this->credentials_path . '/client_secret.json'
$this->client->setAuthConfigFile($this->credentials_path . '/client_secret.json');
$this->client->setAccessType('offline');
$this->client->setRedirectUri($this->redirect_uri);
$this->client->addScope(Google_Service_Drive::DRIVE_READONLY);
$this->client->authenticate($auth_code); //this is the part where the code hangs on a live server, but works perfectly on dev
$this->token = json_encode($this->client->getAccessToken());
$this->client->setAccessToken($this->token);
$this->writeTokenToFile($this->token);
if ($this->client->isAccessTokenExpired()) {
$this->client->refreshToken($this->token);
}
$google_drive_service = new Google_Service_Drive($this->client);
Any help would be very much appreciated!
AFAIK, you need to revoke the existing token before requesting another.
As mentioned in Offline access, when you set the API client's access type to offline, the client object will refresh the access token as needed.
With that, you need to revoke access given to an application. As mentioned,
part of the removal process can include an API request to ensure the permissions granted to the application are removed.
You may want to try revoking a token by calling revokeToken():
$client->revokeToken();
You may want to also check given solutions in the following SO posts:
Automatically refresh token using google drive api with php script.
Not receiving Google OAuth refresh token
Hope that helps!

Google Drive API says some files do not exist when in fact they do

So, I've gotten to the point in my app where I can retrieve a list of spreadsheet documents from a user's Google Drive account by using the Google Spreadsheet API. I populate the file list in a ui control that users can click on to then retrieve the list of its worksheets. It's working as expected in some cases, but in others it is not. In my request, I use the url that comes back from the file list, and even so, the API responds with:
Sorry, the file you have requested does not exist.
Make sure that you have the correct URL and that the owner of the file hasn't deleted it.
Well, surely the file wasn't deleted. I got it back in the response to my request for the files list. I also can get to the file via a normal web browser. Also, the URL is correct because that's the one the API responded with. My code does not manipulate the url that comes back in that initial files response. In fact, here is the URL that is used to grab the worksheets:
https://spreadsheets.google.com/feeds/worksheets/{long key here}/private/full
So, my question is why does my request for some worksheets come back with a response with the actual list of worksheets, but on others (which I have access to, and I know exists) I get the faulty response.
Thanks,
Arie
My app is using OAuth 2.0 and I ran into the same error with new Google Sheets. What fixed that was making a change in scope param sent during OAuth's authorize call and then reauthorising (reinitiating OAuth flow and obtaining new tokens).
Until now scope in my app was just:
https://spreadsheets.google.com/feeds
Updated scope and solution to the issue in my case:
https://spreadsheets.google.com/feeds https://docs.google.com/feeds
I'm running into this in my own stuff. At least for what I'm running into, it seems to be an issue with New Sheets. I'm sorry to not have more of a solution (I'm still trying to find out what to fix on my end) but this may help you narrow down the issue.

Google App Script: ContentService web app usage

I am stuck for 3 days now trying to get 2 google gadgets to reliably communicate on a google site to exchange anonymous user session information based on UiInstance.getId() value. Since gadget-to-gadget pubsub feature is deprecated, I am trying to use the ContentService in the server gadget to service a doPost request from originating from the client gadget - the idea being, I will store the session information in a server gadget and pull the data into gadgets on other pages in the site - not sure if this is possible.
BUT, I am stuck even trying to tinker with the various examples on the ContentService posted on StackOverflow. I am stuck at a very basic step and unable to proceed beyond the super simple server code below. I am not able to figure out what would the URL of the server gadget I need to use from my client gadget. I seem to be getting confusing results.
Server code:
function doGet(e) {
var output = ContentService.createTextOutput();
output.setContent("Hi from ContentServer!");
return output;
}
Steps I followed:
1) Published the server as a web app and set it up so anyone/anonymous can access it.
2) The publish window popup says the gadget is available at
https://script.google.com/macros/s/AKfycbyIa07kBC-gqG0nJq3Up5GzUntbTaYcM1KmaYF7vQvFIWN_qxA/exec
3) If I use a browser to open the link, I get "Unknown macro doGet".
4) If I click on the link given by "Test web app for your latest code." from the publish window popup, it seems to take me to
https://script.googleusercontent.com/echo?user_content_key=WwuWW_Hhp2wlHpHWsX-qAwu7jtKrwlt1fkkesojKEWeJXKm5AoUOhuRHxu4RIHLrWovOBUsHhOB3No0RYr05RE4tWtliFlXKm5_BxDlH2jW0nuo2oDemN9CCS2h10ox_1xSncGQajx_ryfhECjZEnG5I1NuldcVdfVF6dOROkmljXtr0dWIARhfeRbamxWJIIJeMc5tWnrGPpehwqDtynQ&lib=MfYY3NqJ0IdcpreIfwd3uwgmzn1S_adTp
The above link from step 4 works from a browser BUT its very flaky from my client gadget! It seems to work the very first time I version and publish it but returns raw HTML if I update the version even once.
I believe I am missing some trivial step OR there is a serious version control or deployment bug with web-app gadgets.
I have checked out the following threads on stackoverflow that were pretty useful.
How to use ContentService and doPost to create a REST API
KamilG seems to have overcome the issue here Another doGet() issue with Google Apps Script - "Unknown macro doGet" error
But its very wobbly for me and I am unable to pin down any reliable procedure the get the ContentService working from my server gadget.
Any help and explanation will be much appreciated.
Here is my client gadget code.
function doGet(e) {
// var url = "https://script.google.com/macros/s/AKfycbyIa07kBC-gqG0nJq3Up5GzUntbTaYcM1KmaYF7vQvFIWN_qxA/exec";
//var url = "https://script.googleusercontent.com/echo?user_content_key=9tzQxTSPm8ADsHKl4bCg6ru-49C19kYZCW8IRuWiWi-Xe_lTlQZS4xq8v5aPqjR6Ybj7-xjjJXyQPhOH0T3KFtJUtXc7U-Dkm5_BxDlH2jW0nuo2oDemN9CCS2h10ox_1xSncGQajx_ryfhECjZEnJlCLn2pnKC0O1TYz53ccgjxtVC9ccM8kFegFJ0AJSK_YP_ylqfjfm1EU_BUbZUu-88PMDJ6xpj8&lib=MTLHdJRs3UPYj3bYgbhBNnNGZ7UmftE34";
var url = "https://script.googleusercontent.com/echo?user_content_key=LvlwGkBktQ732xyD1HJbh5OhMsuhkidt_rOovw-olm-wJQF4LlErMDSxsfDaAb4UBYqOeTI3-8soIBj-KaOCDi0WlUav4Nl_m5_BxDlH2jW0nuo2oDemN9CCS2h10ox_1xSncGQajx_ryfhECjZEnG5I1NuldcVdfVF6dOROkmljXtr0dWIARhfeRbamxWJIIJeMc5tWnrGPpehwqDtynQ&lib=MfYY3NqJ0IdcpreIfwd3uwgmzn1S_adTp";
// WELL ONE OF THE URLS WORKS FROM ABOVE!!! BUT ONLY TILL I UPDATE THE SERVER WEB APP VERSION :(
var app = UiApp.createApplication().setTitle("ClientService Client test");
app.setStyleAttribute("background", "azure");
var fetchMethod = 'get';
var response = UrlFetchApp.fetch(url, {method: fetchMethod});
//var lbl = app.createHTML("<b>Response :</b>" + response.getContentText());
var lbl = app.createTextArea().setText(response.getContentText());
var lbl1 = app.createHTML("<b>Response code :</b> "
+ response.getResponseCode());
app.add(lbl);
app.add(lbl1);
return app;
}
Help needed please.
This functioning as intended for the most part, but I think there might be some alternatives.
Regarding your point #3 - That URL above works. There must have been something wrong with the version you tested (perhaps you didn't declare doGet correctly?).
The link from #4 is a one time use redirect that happens when you Content Service. See the redirect section here all the way at the bottom. This link is short lived and you might be fast enough to catch it in a browser but a another separate calling client (the "gadget") might not be so lucky. So you should never call the googlecontentservice.com link directly.
Regarding the overall issue of flakiness of ContentService, I have not seen this. If I properly use the /exec link and then properly increment the version after every appropriate change things work as expected for me.
I built a simple web app accessing your Content Service and things seem to work fine for me consistently. See below. The code looks identical to yours but I am using the first url.
https://script.google.com/macros/s/AKfycbw6nlfv5ME6F3Z2WBdW24YAgfQm_E5gYV0xrMDvDwZLrX7PdMU/exec
As an alternative - is there a reason you are doing a server side UrlFetch from one script to another? If you can fetch the data server side, can you just perform the logic of the content script w/in the UI script?