HTTP failure callback for UrlFetchApp.fetch() in gmail addon - google-apps-script

I would like to write a callback when a HTTP requests fails. How do I chain it to UrlFetchApp.fetch()?
Please refer to the HTTP request below.
// Make a GET request.
UrlFetchApp.fetch('http://www.google.com/');

Please note that the fetch function is synchronous. It does not provide a callback parameter and does not return a promise.
An approach to catching exceptions is possible through the UrlFetchApp.fetch(url, params) function. You can pass the muteHttpExceptions parameter into the params location of the function call. That way you can inspect the response code yourself and respond appropriately. Documentation: https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app#fetchurl-params
UrlFetchApp.fetch('http://www.google.com/', {muteHttpExceptions: true});
muteHttpExceptions (Boolean) if this is set to true, the fetch will not
throw an exception if the response code indicates failure, and will
instead return the HTTPResponse (default: false)
An alternative would be a simple try/catch statement. I imagine you could log the error or respond appropriately.
try {
UrlFetchApp.fetch('http://www.google.com/');
}
catch(e) {
// e contains error response
}

Related

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());
}

Catch return json from POST with Axios when error 400 (Bad Request) occurs

I am making an http request in an api using React Native with Axios, I can get json and parsear it when the callback is 200, however, for example, when I call a method, for example, to register the user and step an email from a user who is already registered, he returns me an error 400 (Bad Request) but he also brings a json with the error message ("user already registered"). I need to get this error message since it is variable in the API and show to the user, but when I try to give it a console.log I get the following error:
json's return is this:
and my call code looks like this:
How to get this json even with return 400 in catch?
Thank you.
inside of your catch Block, the error object also provides you with a response body
//... your request here
.catch(error => {
console.log('response: ', error.response.data);
});
console.log(error) is calling the toString method of the error object which doesn't show you the response body.
error.response.data should give you the right content. Take a look at this part of the axios docs

What does d3js.csv.get() do?

I'm learning d3js. I came across an example for extracting CSV values here. I'm quoting the code:
d3.csv("path/to/file.csv")
.row(function(d) { return {key: d.key, value: +d.value}; })
.get(function(error, rows) { console.log(rows); });
From the description, I get that .row() is the accessor here. But the role of the .get() is not clear to me. When is this function called, and for what purpose ? Thanks.
The .get() is a function of the underlying AJAX request -- it sends the request and establishes the callback. From the documentation:
xhr.get([callback])
Issues this request using the GET method. If a callback is specified, it will be invoked asynchronously when the request is done or errors; the callback is invoked with two arguments: the error, if any, and the response value.

Call to realtime.loadAppDataDocument fails when realtime.load works?

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.

How to catch UrlFetchApp.fetch exception

Is there any way to catch the exception from UrlFetchApp.fetch?
I thought I can use response.getResponseCode() to check the response code, but I'm not able to, for e.g when there is 404 error, the script not continue and just stop at UrlFetchApp.fetch
Edit: This parameter is now documented here.
You can use the undocumented advanced option "muteHttpExceptions" to disable exceptions when a non-200 status code is returned, and then inspect the status code of the response. More information and an example is available on this issue.
The trick is passing the muteHttpExceptions param of UrlFetchApp.fetch().
Here an example (untested):
var payload = {"value": "key"}
var response = UrlFetchApp.fetch(
url,
{
method: "PUT",
contentType: "application/json",
payload: JSON.stringify(payload),
muteHttpExceptions: true,
}
);
var responseCode = response.getResponseCode()
var responseBody = response.getContentText()
if (responseCode === 200) {
var responseJson = JSON.parse(responseBody)
// ...
} else {
Logger.log(Utilities.formatString("Request failed. Expected 200, got %d: %s", responseCode, responseBody))
// ...
}
For some reason if the URL is not available (e.g. the service you're trying to use is down) it still looks like is throwing an error so you may still need to use a try/catch block.
why don't you use try catch and handle the error in catch block
try{
//Your original code, UrlFetch etc
}
catch(e){
// Logger.log(e);
//Handle error e here
// Parse e to get the response code
}
You can manually parse the caught error, but it's not recommended. When catching the exception (that is being thrown in case muteHttpExceptions is turned off), the error object would be in the following format:
{
"message": "Request failed for ___ returned code___. Truncated server response: {___SERVER_RESPONSE_OBJECT___} (use muteHttpExceptions option to examine full response)",
"name": "Exception",
"fileName": "___FILE_NAME___",
"lineNumber": ___LINE_NUMBER___,
"stack": "___STACK_DETAILS___"
}
If you for some reason prefer not using muteHttpExceptions, you could catch the exception e, look at e.message, substring the text between "Truncated server response: " and " (use muteHttpExceptions option to examine full response)", JSON.parse() it, and the returned object would be the error returned from the api call.
I wouldn't suggest it over muteHttpExceptions, just wanted to show the best way to get the error object this way.
Anyways, try-catch your UrlFetchApp.fetch() call to make sure you catch the unhandled exceptions, like 404.