|
| 1 | +# FetchApp |
| 2 | + |
| 3 | +FetchApp extends the functionality of the built-in UrlFetchApp in Google Apps Script with advanced features like: |
| 4 | + |
| 5 | +1. **Optional Retries:** Depending on the response code received. |
| 6 | +2. **Delay Strategies:** Choose between linear or exponential delay between retries. |
| 7 | +3. **Custom Callbacks:** Implement callbacks on failed attempts for tailored actions and logic. |
| 8 | +4. **Enhanced Type Hints:** Improved hints for UrlFetchApp's `params` argument. |
| 9 | +5. **Automatic Logging:** Logs failed attempts automatically. |
| 10 | + |
| 11 | +FetchApp is a [Dataful.Tech](https://dataful.tech) project. |
| 12 | + |
| 13 | +## Setup |
| 14 | + |
| 15 | +You can set up FetchApp in two ways: |
| 16 | + |
| 17 | +1. **Copy the code** from `src/FetchApp.js` to your project. In addition to having control over the code and being able to modify it, you will also get better type hints (see section Type Hints and Autocomplete below). |
| 18 | +2. **Connect as a library**: use the library id `1-U70HU_cxKSdTe4U6leREd4wlA7Wey5zOPE5eDF38WgBPrOoi-cztxlb`. |
| 19 | + |
| 20 | +## Usage |
| 21 | + |
| 22 | +There are two ways to use FetchApp. |
| 23 | + |
| 24 | +### Drop-in Replacement for UrlFetchApp |
| 25 | + |
| 26 | +Replace `UrlFetchApp` with `FetchApp` directly. **Note:** By default, FetchApp sets `muteHttpExceptions: true` in `params` unless explicitly specified otherwise. |
| 27 | + |
| 28 | +```js |
| 29 | +// `url` and `params` are defined elsewhere |
| 30 | + |
| 31 | +// regular UrlFetchApp |
| 32 | +const response1 = UrlFetchApp.fetch(url, params); |
| 33 | + |
| 34 | +// FetchApp without configuration is a pass-through to UrlFetchApp |
| 35 | +const response2 = FetchApp.fetch(url, params); |
| 36 | + |
| 37 | +// FetchApp with retries and delay enabled |
| 38 | +const config = { |
| 39 | + maxRetries: 5, |
| 40 | + successCodes: [200], |
| 41 | + delay: 500, |
| 42 | +}; |
| 43 | +const response3 = FetchApp.fetch(url, params, config); |
| 44 | + |
| 45 | +// If there are no `params`, pass an empty object |
| 46 | +const response4 = FetchApp.fetch(url, {}, config); |
| 47 | +``` |
| 48 | + |
| 49 | +### Configurable Client |
| 50 | + |
| 51 | +If you need to use FetchApp multiple times, you can initiate a client to reuse the configuration: |
| 52 | + |
| 53 | +```js |
| 54 | +// FetchApp with retries and delay enabled |
| 55 | +const config = { |
| 56 | + maxRetries: 5, |
| 57 | + retryCodes: [500, 502, 503, 504], |
| 58 | + delay: 500, |
| 59 | +}; |
| 60 | + |
| 61 | +const client = FetchApp.getClient(config); |
| 62 | + |
| 63 | +// All client's fetch calls will use this config |
| 64 | +const response1 = client.fetch(url, params); |
| 65 | + |
| 66 | +// Partially modify the config for a specific request |
| 67 | +const response2 = client.fetch(url, params, { successCodes: [200] }); |
| 68 | +``` |
| 69 | + |
| 70 | +## Configuration |
| 71 | + |
| 72 | +FetchApp offers a variety of customizable configuration options to fine-tune its behavior: |
| 73 | + |
| 74 | +1. Retries: |
| 75 | + - `maxRetries`: Defines the maximum number of retry attempts. Type: Number. Default: `0`. The total number of requests can be up to `maxRetries` + 1, including the original request. |
| 76 | + - `successCodes`: Specifies response codes that indicate a successful response, halting further retries. Type: Array of numbers. Default: `[]`. _Note:_ When set, `retryCodes` are disregarded. |
| 77 | + - `retryCodes`: Lists response codes that trigger a retry, suggesting the initial request failed. Type: Array of numbers. Default: `[]`. |
| 78 | +2. Delays between retries: |
| 79 | + - `delay`: Sets the waiting period between retries in milliseconds. Type: Number. Default: `0` (immediate retry). |
| 80 | + - `delayFactor`: Determines the exponential increase in delay. Type: Number. Default: `1` (constant delay). Delay is calculated as delay multiplied by delayFactor raised to the power of the retry attempt number. _Example:_ With a delay of 1000ms and delayFactor of 2, delays would be 1, 2, 4, 8, 16 seconds, and so on. |
| 81 | + - `maxDelay`: Caps the maximum delay in milliseconds. Type: Number. Default: `Infinity`. This cap prevents excessively long delays. |
| 82 | +3. Callbacks: |
| 83 | + - `onRequestFailure`: Invoked upon a request failure. Type: Function. Default: No action. This function receives an object containing the FetchApp context, including the request's **url** and **params**, the **response**, the FetchApp **config** for the request, and the number of **retries**. |
| 84 | + - `onAllRequestsFailure`: Triggered when all attempts to make a request fail. Type: Function. Default: No action. It receives the same context as `onRequestFailure`, with the **response** being the last failed attempt. |
| 85 | + |
| 86 | +## Limitations |
| 87 | + |
| 88 | +FetchApp sets `params.muteHttpExceptions: true` unless it is explicitly specified otherwise. If you need to throw an exception, for example, on certain response codes, you can do it via callbacks: |
| 89 | + |
| 90 | +```js |
| 91 | +// Throw an exception on 401 or 403 response codes |
| 92 | +const stopRequests = ({ url, response }) => { |
| 93 | + const responseCode = response.getResponseCode(); |
| 94 | + if ([401, 403].includes(responseCode)) { |
| 95 | + throw new Error(`Received ${responseCode} when accessing ${url}`); |
| 96 | + } |
| 97 | +}; |
| 98 | + |
| 99 | +const config = { |
| 100 | + successCodes: [200], |
| 101 | + maxRetries: 5, |
| 102 | + delay: 500, |
| 103 | + onRequestFailure: stopRequests, |
| 104 | +}; |
| 105 | + |
| 106 | +const response = FetchApp.fetch(url, params, config); |
| 107 | +``` |
| 108 | + |
| 109 | +## Type Hints and Autocomplete |
| 110 | + |
| 111 | +FetchApp leverages Google Apps Script IDE's limited JSDoc annotations support. If you copy the full code of the library, you will get complete type hints and autocomplete for all variables, including `params` and `config`. |
| 112 | + |
| 113 | +<div align="center"> |
| 114 | + <img class="logo" src="https://github.com/dataful-tech/fetch-app/raw/master/images/params-options-autocomplete.png" width="600px" alt="FetchApp | Autocomplete for params options"/> |
| 115 | +</div> |
| 116 | + |
| 117 | +Unfortunately, the IDE does not recognize most JSDoc annotations from the libraries, and only text description of the fields is visible. All options are also duplicated in the field descriptions to mitigate this limitation and for easier reference. |
| 118 | + |
| 119 | +<div align="center"> |
| 120 | + <img class="logo" src="https://github.com/dataful-tech/fetch-app/raw/master/images/params-options-autocomplete.png" width="600px" alt="FetchApp | Hint for params options"/> |
| 121 | +</div> |
| 122 | + |
| 123 | +## Versioning |
| 124 | + |
| 125 | +This project follows standard `MAJOR.MINOR.PATCH` semantic versioning. Breaking changes may be introduced in new major versions. |
| 126 | + |
| 127 | +## License |
| 128 | + |
| 129 | +FetchApp is available under the MIT license. |
| 130 | + |
| 131 | +## Contribution |
| 132 | + |
| 133 | +Contributions are welcome. Feel free to submit PRs or issues on GitHub for any suggestions or issues. |
0 commit comments