Lower the timeout for urlFetchApp.fetch function - google-apps-script

I need to test an external URL, and if it fails, fail faster than the default (3 minutes, apparently).
Numerous posts on several forums, including an "enhancement request" to Google, that have gone unanswered, so I thought I'd try here again.
Has anyone conjured a way to do this?
In my particular case, I don't care about getting any content back; my task is simply to test the URL and see if the remote server is alive and responds at all. So, maybe is there a way to change the parameters or headers in the request, to make it "reply instantly or fail quickly" ? For me, maybe ~30 seconds would be fast enough for failures.
Cross posted here:
https://www.reddit.com/r/GoogleAppsScript/comments/iqh9dl/how_to_change_lower_the_timeout_for/

Consideration
In Apps Script the UrlFetchApp.fetch method doesn't accept any callback nor custom timeout parameter. Unlike it does for example in Google Cloud.
Due to the synchronous nature of Apps Script is impossible to wrap the function result in a timeout either.
This feature has been requested
The feature of adding a custom timeout parameter has been requested so feel free to star the issue in order to increase its visibility. Here is the link.

Related

GAS-built telegram bot: catching replies to bot

I wrote an bot on GAS to read from / write to a google sheet from telegram. I use the webhook method. I can address the bot with /read <args> and /write <args>. However, the less tech-savvy are not able to understand the principle of arguments...
So I want to make a conversational bot, like botfather. eg, if /read or /write are sent, then the bot ask in pm for the arguments, one by one.
The "reply in PM" part is easy, but I don't see how I can catch replies for arguments?
As far as I understand, the function doPost is called each time a command is sent to the bot which poses issues of interactivity, and requiring a slash-something command to run the script instead of a plain text reply (and as the GAS data is volatile, the ugly work-around of storing a variable to know the bot should do the 2nd action is impossible too).
Is it feasible with webhook method?
Should I switch to polling / getUpdates method? I'm guessing it could work that way, with a time-out to exit the script in case of no reply, but I'm also guessing the PM chat should be set to 'no privacy' mode. or maybe it is intrinsic to the bot?
Any help appreciated!
So, GAS does offer a not-so volatile storage: CacheService.getScriptCache() (see also https://developers.google.com/apps-script/reference/cache/cache)
The principle is simple: store the variable you want persistent in the cache (optionally, set a time out too - the default is 10min), and get the values when the script is called again. I found out that project that helped me understand how to use it: https://github.com/Milleus/tessara/blob/master/Code.gs
In a few words: the syntax is cache.put(key, value) to store the value, and value=cache.get(key) to fetch it back.
The beauty of it is that all required variables (if more than one) can be stored in an object, the key can be a unique identifier for the "user", and the value is the stringified object.
In my case, I was able to build a fully conversational telegram bot (exactly like BotFather, but for my usage). Using the id from the person sending messages to the bot as the key, the script can run in "parallel" for multiple users at once.
The doGet and doPost are the functions that get called when you follow a web app url. You can use them as an api if you use something like UrlFetchApp to access them or even an Http Request if you can handle the oauth.

google maps requests are forbidden with a status of 403 after working very well for at least a day

I am using the Google Maps Javscript Api, v3 and everything is working well up to a point where the requests for the map images are forbidden with a status of 403. Usually the map stops loading after a period of time in which the page/session is open: it may be 24 hours, it may be more than 48h, I couldn't actually find a more accurate period.
Given the fact that we want to have a live website and a testing one – different domains, I generated 2 different keys, and I am loading them conditionally, but the html rendered is the one expected.
var mapKey = VanillaRate.Domain.Settings.AppSettings.GoogleMapsApiKey;
and the script tag is:
script src="https://maps.googleapis.com/maps/api/js?key=#(mapKey)&libraries=places" async defer
The usage limits were not exceeded, the referrer is well set.
The error appears when the map is zoomed and it's:
Failed to load resource: the server responded with a status of 403 () - maps.googleapis.com/maps/api/js/StaticMapService.GetMapImage?....
Since I couldn’t find any exact posted situation nor documentation about it, it is possible to be a timeout on google servers for security reasons and this is why the requests are forbidden for a session longer than a day?
EDIT: I forgot to mention that after refreshing the tab, everything works well. If it was indeed the usage limit, would the server respond with success after refresh? I've read that in this case, the map wouldn't work all day. Is that right?
If the response is still a HTTP 403 (Forbidden) error, the signature was not necessarily the problem, it may be related to usage limits instead.
This typically means your access to the web service has been blocked on the grounds that your application has been exceeding usage limits for too long or otherwise abused the web service.
I find this answer on google developer. There is no simply way to resolve this problem. Google recommended two solutions:
Reduce requests to the server;
Or, 'purchasing additional allowance for your Google Maps APIs for Work license.'
You can also try to access to the the Google Cloud Support Portal to signal your problem.
I find this informations in google developer here. You can find on this link some solutions like I detail to you and the explanation of your problem.
"The usage limits were not exceeded"
Are you sure? You're loading the places library, in which case this applies:
Google Places API Web Service
Default 1,000 free requests per day,
increased to 150,000 free requests per day after identity
verification.
https://developers.google.com/maps/pricing-and-plans/
See also:
https://developers.google.com/places/web-service/usage
https://developers.google.com/maps/documentation/javascript/places#UsageLimits

What is Google app script URLFetch service response size limit?

I'm writing a Google App Script for a Google spreadsheet and I'm facing a problem with the URLFetch service.
I'm requesting an external service and I sometimes receive an empty response. The external service is pretty stable and must return something, at least an error message if something wrong happens.
But I sometimes receive an empty response, just nothing.
I can only solve this by modifying the request so the expected response should be less in size, and this always fix the issue. Which makes me think its a response size limitation.
I doubt its a random problem because rerunning the script again to issue the same request always fails, unless, as I said, I modify the request to receive a response less in size.
But on Google's quota page, I can't find a clear answer to my question.
At the time of asking this question, I'm facing a problem of reading a response that is supposed to be around 14.1 KB. I knew the size by running the request manually on my browser.
Does anyone know if there is a limitation and what exactly is it ?
In my experience the limit is 10MB. It is definitely larger than 14.1KB, an application I developed (http://www.blinkreports.com) routinely receives responses in excess of 1MB.
Under the assumption that the same limits apply for UrlFetch in Google Apps script as in App Engine.. these limits apply :
request size 10 megabytes
response size 32 megabytes
see https://cloud.google.com/appengine/docs/java/urlfetch/#Java_Quotas_and_limits

Suddenly receiving UNKNOWN_ERROR on maps/api/geocode server-side requests

Our server uses the Google Maps API probably a few dozen times a day to turn street addresses into lat/lng coordinates, for later use on a client-side google map.
We've been doing this for years, and we're hitting this URL to do it:
http://maps.googleapis.com/maps/api/geocode/json?address=<street address>&sensor=false
We do this from a Perl script, and it runs once every 15 minutes, processing any that have queued up (again, we're talking a couple dozen requests a DAY). If multiple are queued, it hits the API serially in bursts of 5, then pauses 5 seconds before continuing, if any more remain.
This has worked fine for years now.
Today, we have started regularly receiving HTTP 500 response code, with this JSON in the body:
{
"results" : [],
"status" : "UNKNOWN_ERROR"
}
I have taken one of the actual requests, and repeatedly hit it from my local dev box, and it works fine (repeatedly).
Yet on our server (colocated at a major service provider), I repeat the test, and I can regularly duplicate the 500 error in the browser.
Both my dev box and our server are currently resolving maps.googleapis.com to the same IP:
googleapis.l.google.com [74.125.198.95]
So I don't think it's an issue of our server hitting a bad Google server.
I would suspect a quota issue, except our use is very, very minimal. Perhaps they are blocking a large swath of RackSpace customers, but no idea how we could find this out or rectify it if so.
After further testing on other servers we have colocated at the same facility, only a single server is exhibiting this issue, though the other servers are in different network class entirely.
Does Google typically use this kind of error message for quota issues? If not, any other ideas as to what the problem is, so we can fix it? At this point, we may need to switch to Bing Maps or some other provider, if there's no way to know why it's happening, or when it will return to normal.
I checked Google's status page, and "Google Maps" is green with no issues indicated, but I have no idea if this considers their Maps API services or not.

Custom HTML5 Geolocation Prompt

As I am testing out one of the HTML5 features - geolocation for my project,
I realized that users can close the prompt without allowing or denying it,
that defeats the whole purpose of the prompt.
And because in my project I want to dynamically display data to users depending on user's location, this can't be done, simply because without knowing user's response,
it doesn't trigger any of the two callbacks - success / error.
so I started searching to see if there's any solution to this,
and a lot of suggestions to this is to set timeout,
I tried and everything works perfectly.
However, one small flaw here is tho, by the time it hits the timeout expiration,
all the data are already displayed, and when i say all, i mean EVERYTHING,
because there's no location detected.
So I came up with two solutions that might work,
1) create a custom geolocation prompt that forces users to allow/deny location to be shared,
and pass the response to browser to set the location preference
2) pause page-load (stop stuff from being rendered) and wait till it hits the timeout expiration or it gets response from users
Does anyone have any idea how to implement one of these two solutions?
PS: sorry if this isn't unclear to you, i know my english sucks, but I can explain in more details.
Thanks guys!
You shouldn't be able to use a custom Geolocation prompt if your project is browser based, because malicious developers could use the method to trick the user. Also, since the Geolocation API is an asynchronous event, it's going to continue loading the rest of the page while it waits.
What I recommend is to use a conditional statement instead with an else clause. This way, your script functions should only execute after location has been shared, and you have a fall back on what should happen if no geolocation information is provided (which I highly recommend as situations will occur when the data isn't provided).
Example of the conditional statement to check for geolocation information using JS:
if (navigator.geolocation) {
// code to run if there is geolocation information
}
else{
// code to run if no geolocation info is given to the browser
}