Created
October 30, 2024 13:30
-
-
Save andrewroberts/4b26c127a67777aa784d34c49ada9d28 to your computer and use it in GitHub Desktop.
Google Apps Script Object for accessing a RESTFul API
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 34567890123456789012345678901234567890123456789012345678901234567890123456789 | |
// JSHint - todo | |
/* jshint asi: true */ | |
/* jshint esversion: 6 */ | |
(function() {"use strict"})() | |
// API_.gs | |
// ======= | |
// | |
const DEFAULT_ROOT_URL_ = '' | |
const DEFAULT_API_TOKEN_ = '' | |
const NUMBER_OF_FETCH_RETRIES_ = 5 | |
var API_ = (function(ns) { | |
let token = null | |
let rootUrl = null | |
ns.init = function(config) { | |
if (!config) config = {} | |
token = config.token ? config.token : DEFAULT_API_TOKEN_ | |
rootUrl = config.rootUrl ? config.rootUrl : DEFAULT_ROOT_URL_ | |
return this | |
} | |
ns.get = function(endpoint) {return get(endpoint)} | |
ns.post = function(endpoint, payload) {return post(endpoint, payload)} | |
ns.put = function(endpoint, payload) {return put(endpoint, payload)} | |
ns.hsDelete = function(endpoint) {return hsDelete(endpoint)} | |
return ns | |
// Private Functions | |
// ----------------- | |
function get(endpoint) { | |
return fetch({rootUrl: rootUrl, endpoint: endpoint}) | |
} | |
function post(endpoint, payload) { | |
return fetch({rootUrl: rootUrl, endpoint: endpoint, payload: payload, method: 'post'}) | |
} | |
function put(endpoint, payload) { | |
return fetch({rootUrl: rootUrl, endpoint: endpoint, payload: payload, method: 'put'}) | |
} | |
function hsDelete(endpoint) { | |
return fetch({rootUrl: rootUrl, endpoint: endpoint, method: 'delete'}) | |
} | |
function fetch(config) { | |
if (config.endpoint === undefined) { | |
throw new Error('No endpoint') | |
} | |
let options = { | |
headers: getHeaders(), | |
muteHttpExceptions: true, | |
contentType: 'application/json', | |
method: config.method | |
} | |
if ((config.method === 'post' || config.method === 'put') && config.payload !== undefined) { | |
options.payload = JSON.stringify(config.payload) | |
console.log(options.payload) | |
} | |
if (!rootUrl) rootUrl = DEFAULT_ROOT_URL_ | |
const url = rootUrl + encodeURI(config.endpoint) | |
const response = UrlFetchApp.fetch(url, options) | |
const code = response.getResponseCode() | |
const content = response.getContentText() | |
for (let n = 1; n < NUMBER_OF_FETCH_RETRIES_; n++) { | |
if (n > 1) { | |
console.log ("fetch try number " + n) | |
} | |
switch(code) { | |
case 200: | |
case 201: | |
return JSON.parse(content) | |
case 204: | |
// Some methods return 204 with empty content | |
if (content) { | |
console.log('Bulk change complete') | |
return JSON.parse(content) | |
} else { | |
console.log('Received code 204 with no content.') | |
return | |
} | |
break | |
case 400: | |
throw new Error('User error: ' + content) | |
case 401: | |
throw new Error('Not authorised') | |
case 404: | |
throw new Error('Resource not found. Config: ' + JSON.stringify(config)) | |
case 409: | |
throw new Error('This resource already exists') | |
// case 429: | |
// console.warn('429 error: ' + content) | |
// policyName = JSON.parse(content).policyName | |
// if (policyName === 'BURST') { | |
// // Too many calls in one second, fall through al try in a bit | |
// break | |
// } else if (policyName === 'DAILY') { | |
// throw new Error('Too many calls for today, try again tomorrow') | |
// } else { | |
// throw new Error('Unexpected 429 policyName') | |
// } | |
case 500: | |
console.warn('500 error on try ' + n + ': ' + content) | |
// Try again. | |
break | |
case 503: | |
console.warn('503 error on try ' + n + ': ' + content) | |
// Try again. | |
break | |
default: | |
var message = 'Error: ' + code + ' on try ' + n + ', "' + content + '"' | |
console.error(message) | |
throw new Error(message) | |
} | |
Utilities.sleep((Math.pow(2, n) * 2000) + (Math.round(Math.random() * 1000))) | |
response = UrlFetchApp.fetch(config.rootUrl + config.endpoint, options) | |
code = response.getResponseCode() | |
content = response.getContentText() | |
} | |
throw new Error("Gave up after " + n + " tries: " + JSON.stringify(config)) | |
return | |
// Private Functions | |
// ----------------- | |
function getHeaders() { | |
if (!token) token = DEFAULT_API_TOKEN_ | |
return { | |
Authorization: `Bearer ${token}`, | |
} | |
} | |
} // UrlFetch_.fetch() | |
})(API_ || {}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment