UNPKG

mindee

Version:

Mindee Client Library for Node.js

105 lines (104 loc) 4.44 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.UrlInput = void 0; const inputSource_1 = require("./inputSource"); const url_1 = require("url"); const path_1 = require("path"); const crypto_1 = require("crypto"); const promises_1 = require("fs/promises"); const https_1 = require("https"); const bytesInput_1 = require("./bytesInput"); const logger_1 = require("../../logger"); class UrlInput extends inputSource_1.InputSource { constructor({ url }) { super(); this.url = url; } async init() { if (this.initialized) { return; } logger_1.logger.debug(`source URL: ${this.url}`); if (!this.url.toLowerCase().startsWith("https")) { throw new Error("URL must be HTTPS"); } this.fileObject = this.url; this.initialized = true; } async fetchFileContent(options) { const { username, password, token, headers = {}, maxRedirects = 3 } = options; if (token) { headers["Authorization"] = `Bearer ${token}`; } const auth = username && password ? `${username}:${password}` : undefined; return await this.makeRequest(this.url, auth, headers, 0, maxRedirects); } async saveToFile(options) { const { filepath, filename, ...fetchOptions } = options; const { content, finalUrl } = await this.fetchFileContent(fetchOptions); const finalFilename = this.fillFilename(filename, finalUrl); const fullPath = `${filepath}/${finalFilename}`; await (0, promises_1.writeFile)(fullPath, content); return fullPath; } async asLocalInputSource(options = {}) { const { filename, ...fetchOptions } = options; const { content, finalUrl } = await this.fetchFileContent(fetchOptions); const finalFilename = this.fillFilename(filename, finalUrl); return new bytesInput_1.BytesInput({ inputBytes: content, filename: finalFilename }); } static extractFilenameFromUrl(uri) { return (0, path_1.basename)(new url_1.URL(uri).pathname || ""); } static generateFileName(extension = ".tmp") { const randomString = (0, crypto_1.randomBytes)(4).toString("hex"); const timestamp = new Date().toISOString().replace(/[-:]/g, "").split(".")[0]; return `mindee_temp_${timestamp}_${randomString}${extension}`; } static getFileExtension(filename) { const ext = (0, path_1.extname)(filename); return ext ? ext.toLowerCase() : null; } fillFilename(filename, finalUrl) { if (!filename) { filename = finalUrl ? UrlInput.extractFilenameFromUrl(finalUrl) : UrlInput.extractFilenameFromUrl(this.url); } if (!filename || !(0, path_1.extname)(filename)) { filename = UrlInput.generateFileName(UrlInput.getFileExtension(filename || "") || undefined); } return filename; } async makeRequest(url, auth, headers, redirects, maxRedirects) { const parsedUrl = new url_1.URL(url); const options = { hostname: parsedUrl.hostname, path: parsedUrl.pathname + parsedUrl.search, method: "GET", headers: headers, auth: auth, }; const response = await new Promise((resolve, reject) => { const req = (0, https_1.request)(options, resolve); req.on("error", reject); req.end(); }); if (response.statusCode && response.statusCode >= 300 && response.statusCode < 400) { if (redirects === maxRedirects) { throw new Error(`Can't reach URL after ${redirects} out of ${maxRedirects} redirects, aborting operation.`); } if (response.headers.location) { return await this.makeRequest(response.headers.location, auth, headers, redirects + 1, maxRedirects); } throw new Error("Redirect location not found"); } if (!response.statusCode || response.statusCode >= 400 || response.statusCode < 200) { throw new Error(`Couldn't retrieve file from server, error code ${response.statusCode}.`); } const chunks = []; for await (const chunk of response) { chunks.push(chunk); } return { content: Buffer.concat(chunks), finalUrl: url }; } } exports.UrlInput = UrlInput;