How do you use fetch within a web trigger

I have a web trigger setup to run a fetch request after an external webhook sends a POST request to the web trigger’s URL. The web trigger works and receives the requests from the webhooks successfully.

However, I need to run a fetch request to an external API after this happens and I cannot figure out how to get it to run. I have a console.log after the fetch request and nothing gets logged.

Any pointers on another approach or where to look would be greatly appreciated. Thanks for the help!

Here is my code if that helps:

import { fetch } from "@forge/api";

const token =
  "token123";

exports.runAsync = (request) => {
  const requestJSON = JSON.parse(request.body);
  if (request.method != "GET") {
    const target = requestJSON.data.links.target;
    // The target is the request URL to the external API which is always successfully logged
    // I tried hardcoding it and got the same result
    sendRequest(target, "get").then((data) => {
      console.log(data);
    });
  } else {
    // A POST request is sent to authorize the webhook
    const validationToken = request.queryParameters.validationToken[0];
    const result = forgeWebhookResponse(validationToken);
    return result;
  }
};

// Response used to authorize webhook
const forgeWebhookResponse = (token) => ({
  body: token,
  headers: {
    "Content-Type": ["text/plain"],
    Accept: ["*/*"],
  },
  statusCode: 200,
});

// Function to send fetch request to external API
async function sendRequest(url, method) {
  const fetch = await fetch(url, {
    method: method,
    headers: {
      "Authorization": token,
      "Content-Type": "application/json",
    },
    redirect: "follow",
  });
  const data = await fetch.json();
  return data;
}
1 Like

Have you added the external url in the manifest file?

https://developer.atlassian.com/platform/forge/manifest-reference/permissions/#fetch

3 Likes

Hey Nathan,

Thanks for the response. Yes, I have added the external URL to the manifest file. Just to confirm, I’ve just added the site URL i.e. api.example.com

Based on the docs, I should be good for all endpoints with that site URL.

Two things I’m noticing poking around on this…

Firstly, you’re mixing async/await with promise resoultion via .then. No clue whether that is causing problems or not, but definitely makes it tricky to keep up with what is going on.

Secondly, you’re overloading the fetch variable here:

That seems risky and likely to lead you to frustration.

I have this paired down version of your code working as I’d expect:

import { fetch } from "@forge/api";

const token = "token123";

// Response used to authorize webhook
const forgeWebhookResponse = (token) => ({
  body: token,
  headers: {
    "Content-Type": ["text/plain"],
    Accept: ["*/*"],
  },
  statusCode: 200,
});

exports.runAsync = async (request) => {
  const target= 'https://reqres.in/api/users?page=2'
  let response = await sendRequest(target, "get");
  console.log(response);
  return forgeWebhookResponse(token)
};

// Function to send fetch request to external API
async function sendRequest(url, method) {
  let data = await fetch(url, {
    method: method,
    headers: {
      "Authorization": token,
      "Content-Type": "application/json",
    },
    redirect: "follow",
  });
  data = await data.json();
  return data;
}
1 Like

Also, are you using forge tunnel for debugging? If not, I’d highly recommend it. It makes the feedback loop way faster.

1 Like

Hey @bentley - thanks for the reply. You were right about my promise resolution being mixed up. I updated my code and was able to return the JSON response body in the sendRequest function.

And I have been using forge tunnel for debugging. It is very useful.