218 lines
6.5 KiB
JavaScript
218 lines
6.5 KiB
JavaScript
// /**
|
|
// * @swagger
|
|
// * /api/documents/download/{id}:
|
|
// * get:
|
|
// * tags:
|
|
// * - Documents
|
|
// * description: Get document
|
|
// * parameters:
|
|
// * - name: id
|
|
// * in: path
|
|
// * description: iShare ID
|
|
// * type: string
|
|
// * required: true
|
|
// * default: A41567436
|
|
// * - name: hash
|
|
// * in: query
|
|
// * description: Hash string
|
|
// * default: e0a1c9cd2817826a25bca67e60b807eae747cbed769e3ec42cf997541c32be71
|
|
// * responses:
|
|
// * 200:
|
|
// * description: Success
|
|
// */
|
|
|
|
// import axios from "axios";
|
|
// import CryptoJS from "crypto-js";
|
|
|
|
// const WORDKEY = process.env.HASHKEY;
|
|
// const accessTokenEndpoint = process.env.ACCESS_TOKEN_ENDPOINT;
|
|
// const tenantId = process.env.TENANT;
|
|
|
|
// const WEBAPI_URL =
|
|
// process.env.RELAY_ROOT ||
|
|
// "https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
|
|
|
|
// const hashAPIPath = (queryPath) => {
|
|
// var hashlink = CryptoJS.HmacSHA256(
|
|
// queryPath,
|
|
// CryptoJS.enc.Hex.parse(WORDKEY)
|
|
// );
|
|
// hashlink = hashlink.toString(CryptoJS.enc.Hex);
|
|
|
|
// //return "&hash=" + hashlink;
|
|
|
|
// return (queryPath.indexOf("?") > -1 ? "&hash=" : "?hash=") + hashlink;
|
|
// };
|
|
|
|
// const azureHeadersPaged = (access_token) => {
|
|
// return {
|
|
// headers: {
|
|
// "OData-MaxVersion": "4.0",
|
|
// "OData-Version": "4.0",
|
|
// "Accept": "application/json;odata.metadata=none",
|
|
// "Prefer":
|
|
// 'odata.include-annotations="*",return=representation, odata.maxpagesize=10',
|
|
// "Content-Type": "application/json",
|
|
// "Authorization": "Bearer " + access_token,
|
|
// },
|
|
// };
|
|
// };
|
|
|
|
// export default async function ApiProxy(req, res) {
|
|
// var token = await getToken();
|
|
|
|
// var docRef = req.query;
|
|
|
|
// var queryUrl = "documents/download/" + docRef.id + "?hash=" + docRef.hash;
|
|
|
|
// const configDocument = (access_token) => {
|
|
// return {
|
|
// headers: {
|
|
// "OData-MaxVersion": "4.0",
|
|
// "OData-Version": "4.0",
|
|
// "Accept": "application/json",
|
|
// "Prefer": 'odata.include-annotations="*",return=representation',
|
|
// "Content-Type": "application/json",
|
|
// "Authorization": "Bearer " + access_token,
|
|
// },
|
|
// responseType: "arraybuffer",
|
|
// };
|
|
// };
|
|
|
|
// return axios
|
|
// .get(
|
|
// WEBAPI_URL + queryUrl, // + hashAPIPath(queryUrl),
|
|
// configDocument(token.access_token)
|
|
// )
|
|
// .then((response) => {
|
|
// const bytes = response.data.byteLength;
|
|
// console.log(bytes);
|
|
|
|
// res.setHeader(
|
|
// "content-disposition",
|
|
// "attachment; filename=" +
|
|
// response.headers["content-disposition"].split(
|
|
// "filename="
|
|
// )[1]
|
|
// );
|
|
// return res.status(200).send(response.data);
|
|
// })
|
|
// .then(() => {
|
|
// console.log(docRef.id + "has downloaded");
|
|
|
|
// return "downloadComplete";
|
|
// })
|
|
// .catch((error) => {
|
|
// consoleLogger(error);
|
|
// res.redirect("/filenotavailable");
|
|
// });
|
|
// }
|
|
|
|
import axios from "axios";
|
|
import { getToken } from "../../../../actions/core/token";
|
|
import { consoleLogger } from "../../../../actions/core/logger";
|
|
|
|
const WEBAPI_URL =
|
|
process.env.RELAY_ROOT ||
|
|
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
|
|
|
|
const FILE_NOT_AVAILABLE_PATH = "/filenotavailable";
|
|
|
|
// Retry utility with logging
|
|
async function retry(fn, retries = 3, delay = 1000) {
|
|
for (let attempt = 1; attempt <= retries; attempt++) {
|
|
try {
|
|
return { response: await fn(), attempts: attempt };
|
|
} catch (err) {
|
|
if (attempt === retries) throw err;
|
|
console.log(`Retry ${attempt} failed, retrying in ${delay}ms...`);
|
|
await new Promise((res) => setTimeout(res, delay));
|
|
delay *= 2; // exponential backoff
|
|
}
|
|
}
|
|
}
|
|
|
|
const ApiProxy = async (req, res) => {
|
|
const docRef = req.query;
|
|
|
|
if (
|
|
typeof docRef?.id !== "string" ||
|
|
docRef.id.length === 0 ||
|
|
typeof docRef?.hash !== "string" ||
|
|
docRef.hash.length === 0
|
|
) {
|
|
if (!res.headersSent) {
|
|
res.redirect(FILE_NOT_AVAILABLE_PATH);
|
|
}
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const token = await getToken();
|
|
const startTime = Date.now();
|
|
|
|
const fetchStream = async () => {
|
|
const queryUrl =
|
|
"documents/download/" + docRef.id + "?hash=" + docRef.hash;
|
|
|
|
return axios.get(WEBAPI_URL + queryUrl, {
|
|
headers: {
|
|
"OData-MaxVersion": "4.0",
|
|
"OData-Version": "4.0",
|
|
"Accept": "application/json",
|
|
"Prefer":
|
|
'odata.include-annotations="*",return=representation',
|
|
"Content-Type": "application/json",
|
|
"Authorization": "Bearer " + token.access_token
|
|
},
|
|
responseType: "stream"
|
|
});
|
|
};
|
|
|
|
const { response, attempts } = await retry(fetchStream, 3, 1000);
|
|
|
|
// Extract filename
|
|
const contentDisposition = response.headers["content-disposition"];
|
|
const filename = contentDisposition
|
|
? contentDisposition.split("filename=")[1]
|
|
: docRef.id;
|
|
|
|
res.setHeader(
|
|
"Content-Disposition",
|
|
`attachment; filename=${filename}`
|
|
);
|
|
res.setHeader("Content-Type", "application/octet-stream");
|
|
|
|
let totalBytes = 0;
|
|
|
|
response.data.on("data", (chunk) => {
|
|
totalBytes += chunk.length;
|
|
});
|
|
|
|
response.data.pipe(res);
|
|
|
|
response.data.on("end", () => {
|
|
const durationMs = Date.now() - startTime;
|
|
console.log(
|
|
`[Download Complete] Document: ${filename}, ID: ${docRef.id}, Size: ${totalBytes} bytes, Duration: ${durationMs}ms, Attempts: ${attempts}`
|
|
);
|
|
});
|
|
|
|
response.data.on("error", (err) => {
|
|
consoleLogger(err);
|
|
if (!res.headersSent) res.redirect(FILE_NOT_AVAILABLE_PATH);
|
|
});
|
|
} catch (error) {
|
|
consoleLogger(error);
|
|
if (!res.headersSent) res.redirect(FILE_NOT_AVAILABLE_PATH);
|
|
}
|
|
};
|
|
|
|
export const config = {
|
|
api: {
|
|
responseLimit: false
|
|
}
|
|
};
|
|
|
|
export default ApiProxy;
|