@forge/bridge
5.15.2-next.0-experimental-5b726e65.16.0-next.1
out/fetch/fetch.js~
out/fetch/fetch.jsModified+12
Index: package/out/fetch/fetch.js
===================================================================
--- package/out/fetch/fetch.js
+++ package/out/fetch/fetch.js
@@ -4,13 +4,20 @@
const blobParser_1 = require("../utils/blobParser");
const parseFormData = async (form, matchFilePrefix = false) => {
const parsed = {};
for (const [key, value] of form.entries()) {
+ // Jira and Confluence REST APIs requires that the field containing
+ // the file MUST be named exactly 'file'
const isFileKey = matchFilePrefix ? key.startsWith('file') : key === 'file';
if (isFileKey) {
const fileName = value.name;
const fileType = value.type;
+ // we parse the file as a base64 string so it
+ // can be properly transfered over the bridge.
+ // we'll parse it back to Blob in the host product
parsed[key] = await (0, blobParser_1.blobToBase64)(value);
+ // we also need to pass the file name and type,
+ // as those will be lost in the base64 conversion
parsed[`__${key}Name`] = fileName;
parsed[`__${key}Type`] = fileType;
}
else {
@@ -23,9 +30,11 @@
if (!init) {
return init;
}
if ('signal' in init) {
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
const { signal: _signal, ...rest } = init;
+ // eslint-disable-next-line no-console
console.error('Signal is not supported in @forge/bridge and was removed from fetch options. Please use the fetch method from @forge/api for signal support.');
return rest;
}
return init;
@@ -33,8 +42,10 @@
const parseRequest = async (fetchType, init) => {
const isFormData = (init === null || init === void 0 ? void 0 : init.body) instanceof FormData ? true : false;
const requestBody = isFormData ? await parseFormData(init === null || init === void 0 ? void 0 : init.body, fetchType === 'remote') : init === null || init === void 0 ? void 0 : init.body;
const req = new Request('', { body: requestBody, method: init === null || init === void 0 ? void 0 : init.method, headers: init === null || init === void 0 ? void 0 : init.headers });
+ // If `init.body` is a `FormData`, a `content-type` header required for the body to be parsed by the
+ // API receiving this request will be generated in req.headers.
const headers = Object.fromEntries(req.headers.entries());
const body = req.method !== 'GET' ? await req.text() : null;
return {
body,
@@ -63,8 +74,9 @@
const productFetchApi = (callBridge) => {
const fetch = async (product, restPath, init) => {
const validatedInit = validateFetchOptions(init);
const { body: requestBody, headers: requestHeaders, isMultipartFormData } = await parseRequest('product', validatedInit);
+ // https://ecosystem.atlassian.net/browse/BUILD-1118 Skip xsrf check for oauth request
if (!requestHeaders.has('X-Atlassian-Token')) {
requestHeaders.set('X-Atlassian-Token', 'no-check');
}
const fetchPayload = {