Working with Fetch API

Fetch API is used to make HTTP requests. It is based on an open standard that all modern browsers support, including most of the server-side and cloud-based JavaScript runtimes, including ScriptRunner Connect runtime.

At this time, ScriptRunner Connect's Fetch API is not 100% standard compliant. We are missing some features that cannot be supported outside of browser-based environments. However, ScriptRunner Connect supports everything you will probably ever need. ScriptRunner Connect aims to align its Fetch API implementation to match the standard that is being developed for server-side JavaScript runtimes.

ScriptRunner Connect supports two versions of Fetch API:

We recommend using Managed Fetch API in conjunction with connectors for increased security, which removes the need to hardcode authentication credentials directly in the code, and only to use raw Fetch API level when you can't work with the managed version.

Making a Raw Fetch Request

To make a fetch request, call the fetch function and pass in the URL.

For this example, we're using https://jsonplaceholder.typicode.com/ anonymous service, which means we can use the raw Fetch API directly.

js
export default async function(event: any, context: Context): Promise<void> { const response = await fetch('https://jsonplaceholder.typicode.com/posts'); }

You can also pass in the options which accept the method , headers , and body.

Here is an example of how to make a POST  request with JSON body:

js
export default async function(event: any, context: Context): Promise<void> { const response = await fetch('https://jsonplaceholder.typicode.com/posts', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ userId: 1, id: 1, title: 'Test', body: 'Hello World' }) }); }

Making a Managed Fetch Request

If you need to work with services that require authentication and you're working with fixed authentication tokens, we encourage you to use the generic connector. OAuth-based authentication flows cannot be used with the generic connector because tokens need to be rotated and cannot remain static. In this case, OAuth flow needs to be implemented manually using raw Fetch API, whereas Record Storage could be used to store sensitive information without needing to hardcode that information directly into the code.

For this example, jsonplaceholder.typicode.com is still used but through a generic connector. Although this service does not need authentication, the same principles still apply.

The main difference between the raw and managed Fetch API is that you must use a relative URL path with the managed version since the base URL was configured with the generic connector, which will be substituted. The fetch call will include headers that were added with the generic connector.

To use the managed Fetch API:

  1. Configure the generic connector.
  2. Configure the API connection in your workspace.
  3. Import the API connection that targets the generic connector into your code.
  4. From the imported namespace, you can access the fetch  function.

Given the path for the API connection that targets the generic connector is /api/json , the example above, if using managed Fetch API, would look something like this:

js
// Imports API Connection with path of '/api/json' under the namespace of 'JsonPlaceholder' import JsonPlaceholder from './api/json'; export default async function(event: any, context: Context): Promise<void> { // Calls managed Fetch API from JsonPlaceholder namespace const response = await JsonPlaceholder.fetch('/posts', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ userId: 1, id: 1, title: 'Test', body: 'Hello World' }) }); }

Handling Responses

Every time you make a fetch call, you're going to receive a response. A response tells you what happened with the request. And if it did succeed, then you can also extract the body from it, if the body is present.

The following response properties are perhaps the most noteworthy: 

  • status  - Represent response status code in numerical form.
  • statusText - Represents response status code in human-readable form.
  • ok - Represents if the response is OK or not; under the hood, it checks if the response is in the 200 range.
  • arrayBuffer() - Function that returns the body as ArrayBuffer (raw bytes). Use this when you need to work with binary data directly.
  • text() - Function that returns the body as string  (text). Use this when you're expecting to work with human-readable data.
  • json() - Function that returns the body as JSON parsed JavaScript object. Use this when you're expecting a JSON object to be returned.

Response handling works the same regardless of if you're using the raw or the managed Fetch API version. But at this time, the raw Fetch API returns more properties in the response than the managed version, thus making it more closely aligned with the open standard. However, the properties listed above do exist and work the same for both versions.

An Example

Here is a typical example of making a Fetch API call, checking if the response is OK, and then extracting the body as a JSON object:

js
export default async function(event: any, context: Context): Promise<void> { // Fetch posts const response = await fetch('https://jsonplaceholder.typicode.com/posts'); // Check if the response is OK if (!response.ok) { // If it's not, then throw an error throw Error(`Unexpected response code: ${response.status} - ${await response.text()}`); } // If it's OK, then proceed by getting the JSON object from the body that represents the posts const posts = await response.json(); // And finally print out the posts console.log('Posts', posts); }

Helpful templates ðŸ’¡

Helpful code snippets 💡

  • Working with attachments
    Contains examples of more advanced use cases of Fetch API being used to upload binary data as attachments.