How to handle urlfetch error? I'am trying muteHttpExceptions: true, but it doesn't work and the script breaks.
function myFunction() {
var result = UrlFetchApp.fetch("http://www.soccer-wallpapers.net/soccer_wallpaper/barcelona_fc_barcelona_360.jpg ", {
muteHttpExceptions: true });
Logger.log("code: " + result.getResponseCode());
Logger.log("text: " + result.getContentText());
}
But I'm trying another error url to work fine.
http://img8.uploadhouse.com/fileuploads/2058/20586362b34151eb10a4001e1c44305fe41bff6.jpg
Solved handle using the try and catch method.
try
{
var page = UrlFetchApp.fetch("http://www.soccer-wallpapers.net/soccer_wallpaper/barcelona_fc_barcelona_360.jpg");
}
catch(err)
{
Browser.msgBox("error");
}
}
This seems to be working as designed. The muteHttpExeptions is for doing just that. It tells the script to carry on as normal if it received an HTTP error status. In your first example code, the error is not an HTTP error. There is no web server to return an HTTP code of any type. The URL does not exist. The service that reaches out to the internet cannot continue, and there is no HTTP exception to be had.
When I visit http://www.soccer-wallpapers.net/soccer_wallpaper/barcelona_fc_barcelona_360.jpg, I get a timeout message. There was nothing to respond to my request. It appears that soccer-wallpapers.net is no longer responding to requests. It does have a DNS entry, but does not respond to ping from my location.
If you must handle bad URLs, potentially down servers and other server errors, then you will need to use a try{}catch(){} block. How you handle those errors is up you. The muteHttpExceptions flag is meant more for handling HTTP errors as part of your application instead of throwing errors at the script level.
That's still remains an issue in functions that are called in cells where the try-catch in this case is just ignored
Related
I tried to login my account by using UrlFetchApp, when I ran script manually, everything worked well. But when I set trigger to run automatically, it returned "error_need_ivs". I have no idea what it is and how to fix. please help me. Below is my code
function login() {
var data = {
'username':'username',
'password_hash':'password',
}
var option = {
muteHttpExceptions: true,
"method" : "POST",
"payload" : data,
}
var url = 'my url'
var res = JSON.parse(UrlFetchApp.fetch(url,option).getContentText());
Logger.log(res) //returned error_need_ivs when I set trigger but worked well when I ran script manually
}
UPDATE : This picture show the result after scripting executed by trigger
From the new screenshot shared I can see no Exceptions were thrown, which means the error logged error_need_ivs certainly comes from the response of the HTTP request rather than an issue with Apps Scripts.
Regarding why it works when calling the affected function manually and why it doesn't worked when invoking it via timed-trigger, I believe what #Tanaike suggested to make sense, maybe the affected endpoint is not prepared to receive IPv6 requests or require more data when doing so.
I'd suggest checking the documentation for the endpoint you are making the request for to help identify what might be causing this behavior.
Alternatively, I'd also suggest to report it as an Issue on IssueTracker using this template. Make sure to include a full reproducible scenario when reporting it (including a working endpoint).
I've created a service worker enabled application that is intended to cache the response from an AJAX call so it's viewable offline. The issue I'm running into is that the service worker caches the page, but not the AJAX response the first time it's loaded.
If you visit http://ivesjames.github.io/pwa and switch to airplane mode after the SW toast it shows no API content. If you go back online and load the page and do it again it will load the API content offline on the second load.
This is what I'm using to cache the API response (Taken via the Polymer docs):
(function(global) {
global.untappdFetchHandler = function(request) {
// Attempt to fetch(request). This will always make a network request, and will include the
// full request URL, including the search parameters.
return global.fetch(request).then(function(response) {
if (response.ok) {
// If we got back a successful response, great!
return global.caches.open(global.toolbox.options.cacheName).then(function(cache) {
// First, store the response in the cache, stripping away the search parameters to
// normalize the URL key.
return cache.put(stripSearchParameters(request.url), response.clone()).then(function() {
// Once that entry is written to the cache, return the response to the controlled page.
return response;
});
});
}
// If we got back an error response, raise a new Error, which will trigger the catch().
throw new Error('A response with an error status code was returned.');
}).catch(function(error) {
// This code is executed when there's either a network error or a response with an error
// status code was returned.
return global.caches.open(global.toolbox.options.cacheName).then(function(cache) {
// Normalize the request URL by stripping the search parameters, and then return a
// previously cached response as a fallback.
return cache.match(stripSearchParameters(request.url));
});
});
}
})(self);
And then I define the handler in the sw-import:
<platinum-sw-import-script href="scripts/untappd-fetch-handler.js">
<platinum-sw-fetch handler="untappdFetchHandler"
path="/v4/user/checkins/jimouk?client_id=(apikey)&client_secret=(clientsecret)"
origin="https://api.untappd.com">
</platinum-sw-fetch>
<paper-toast id="caching-complete"
duration="6000"
text="Caching complete! This app will work offline.">
</paper-toast>
<platinum-sw-register auto-register
clients-claim
skip-waiting
base-uri="bower_components/platinum-sw/bootstrap"
on-service-worker-installed="displayInstalledToast">
<platinum-sw-cache default-cache-strategy="fastest"
cache-config-file="cache-config.json">
</platinum-sw-cache>
</platinum-sw-register>
Is there somewhere I'm going wrong? I'm not quite sure why it works on load #2 instead of load #1.
Any help would be appreciated.
While the skip-waiting + clients-claim attributes should cause your service worker to take control as soon as possible, it's still an asynchronous process that might not kick in until after your AJAX request is made. If you want to guarantee that the service worker will be in control of the page, then you'd need to either delay your AJAX request until the service worker has taken control (following, e.g., this technique), or alternatively, you can use the reload-on-install attribute.
Equally important, though, make sure that your <platinum-sw-import-script> and <platinum-sw-fetch> elements are children of your <platinum-sw-register> element, or else they won't have the intended effect. This is called out in the documentation, but unfortunately it's just a silent failure at runtime.
I've been researching this and cannot find or understand some of the solutions so i'm hoping to get some help here. I'm using Asp.net and building an application that needs to use a bible api. I like the two listed in the question. Every time I call esvapi it comes back successful, but I cannot view the data. I get an error in the console.
XMLHttpRequest cannot load http://www.esvapi.org/v2/rest`/passageQuery?key=8834092f0c58fcda&passage=James2. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:59324' is therefore not allowed access.`
I've seen other with this error and I have questions.
If I'm understanding this correct I get this because the server is preventing me from seeing the data for security purposes. Maybe even the browser( this is not just a chrome issue) problem. So if I need to add a info to the response header from Angularjs to stop this how is that done. Anyone with experience?
Would I need to contact anyone to be able to prevent the server from responding this way...I doubt this, but thought I would ask. I already have valid api key.
the bible.org website api key is confusing to apply to my code. on esvapi i just add a header with key: "keypass" and I only have the CORS issue. But with bible.org I can't figure out how to implement the api key and password. see below... Do I say token:key: username. If i put the api in the browser I get a popup to add username and password. the username is my key and the password is ignored. I tried putting in username as key, but that didn't cut it. Regardless I need to fix the CORS issue and add info to response headers to see response data.
$scope.search = function() {
return $http.get("http://www.esvapi.org/v2/rest/passageQuery?&passage=" + $scope.bo + $scope.chap, {
headers: {
"key?token?orusername?": "",
///thought i saw someone do this...don't know if this is right
"Access-Control-Expose-Headers": "Content-Disposition",
}
}).success(function (data, status, headers, config) {
$scope.book = data.Book;
$scope.chapter = data.Chapter;
$scope.output = data.Output;
}).error(function (data, status, headers, config) {
$scope.message = "Oops... something went wrong";
});
Any input would be helpful. Thanks!
I actually have a bible api working...just a version that I don't like and there is not another version on that webites api.
Change the get $http.get call to $http.jsonp and hope it works. You're using cross-site scripting. Sometimes you can get away with a JSONP call in these cases and sometimes you can't.
I am using the 2.3.1.min version of the jquery-jsonp library found here: https://github.com/jaubourg/jquery-jsonp and it works as expected, namely the error function fires when an error occurs. However, I cannot to seem to display the error encountered. I checked the docs on github project but could not find an answer.
Is this a limitation? Or am I not calling the right object?
My implementation..
The url parameter below is set to return a 404 page on purpose. Chrome dev tools shows a 404 response, but I cannot seem to capture that result..
<script type="text/javascript">
$.jsonp({
url: 'http://apps.mydomain.com/Service/NonExistant?&max=4&format=json',
callbackParameter: "callback",
error: function(xOptions, textStatus){
// this lines returns "error"
console.log(textStatus);
// this returns the Object (but expanding it reveals no indication of error code / message)
console.log(xOptions);
},
success: function(json, textStatus) {
Populate(json); // this works fine
}
});
</script>
Sadly, you can't. Johnny Wey explains it far better than I could - but essentially, it's relying on a "script" tag to get the JSON response, rather than a request executed via javascript.
You could wrap the type of error within the JSONP response per Parsing JSONP Response in Javascript when 4xx or 5xx Http Error Code is Present, but that still won't help you with a 404 error.
Unfortunately, though JSONP error handling is effectively non-existent. The "Cautionary Note" from IBM specifically mentions that "First and foremost, there is no error handling for JSONP calls".
Is possible to intercept 404 error without using web server (browsing html file in the filesystem) ?
I tried with some javascript, using an hidden iframe that preload the destination page and check for the result and then trigger a custom error or redirect to the correct page.
This work fine but is not good on perfomance.
A 404 error is an HTTP status response. So unless you are trying to retrieve this file using an HTTP request/response, you can't have a genuine 404 error. You can only mimic one in something like the way you suggest. Any "standard" way of handling a 404 error is dependent on your flavour of web server anyway...
404 is a HTTP response code, and as such only delivered through the HTTP protocol by servers that speak it. The file:// extension isn't a real protocol response as such, it's a hack built into clients (like browsers) that enable local file support, however it's up to browsers / clients themselves whether they expose any response codes from their file:// implementation. In theory they could report them in the DOM, for example, but they would be response codes exposed to themselves, and as such rarely implemented. Most don't, and there isn't a standard way for it. You may look into browser extensions, like Firefox, and see if they support it, but then, this is highly unstandard and will likely break if you pop it on the web.
Why don't you want to use the server?
I don't believe that it's possible to handle a 404 error client-side, because a 404 error is server-side.
Whenever you load a webpage, you make a request to the server. Thus, when you ask for a file that's not there, it's the server that handles the error. Regular HTML/CSS/JavaScript only come into the picture when the server sends back a response to tell you that it can't find the file.
Steve
Because I was looking for this today. You can now do this without a server by using a Service Worker to cache the custom 404 page, and then serve it when a fetch request status is 404. Following the instructions on the google cache lab, the worker files looks as follows:
const filesToCache = [
'/',
'404.html'
];
const staticCacheName = 'pages-cache-v1';
self.addEventListener('install', event => {
console.log('Attempting to install service worker and cache static assets');
event.waitUntil(
caches.open(staticCacheName).then(cache => {
return cache.addAll(filesToCache);
});
);
});
self.addEventListener('fetch', event => {
console.log('Fetch event for ', event.request.url);
event.respondWith(
caches.match(event.request).then(response => {
if (response) {
console.log('Found ', event.request.url, ' in cache');
return response;
}
console.log('Network request for ', event.request.url);
return fetch(event.request).then(response => {
console.log('response.status:', response.status);
// fetch request returned 404, serve custom 404 page
if (response.status === 404) {
return caches.match('404.html');
}
});
});
);
});