Spaces:
Runtime error
Runtime error
| // simple express app | |
| const express = require("express"); | |
| const cors = require("cors"); | |
| const app = express(); | |
| app.use( | |
| cors({ | |
| origin: "*", | |
| }) | |
| ); | |
| /** | |
| * Extracts the CID from the given URL. | |
| * | |
| * @param {string} url - The URL from which to extract the CID | |
| * @return {string} The extracted CID | |
| */ | |
| function extractCID(url) { | |
| if (url.includes("dweb")) { | |
| let parts = url.split("/"); | |
| let subParts = parts[2].split("."); | |
| return subParts[0]; | |
| } else { | |
| return url.split("/").pop(); | |
| } | |
| } | |
| const eachfilesize = {}; | |
| /** | |
| * Calculate the total size of the files associated with the given content identifiers (CIDs). | |
| * | |
| * @param {array} cids - An array of content identifiers | |
| * @return {number} The total size of the files in bytes | |
| */ | |
| async function getFileSize(cids) { | |
| var fileSize = 0; | |
| for (var cid of cids) { | |
| if (cid.includes("https://")) { | |
| cid = extractCID(cid); | |
| } | |
| const res = await fetch(`https://ipfs.particle.network/${cid}`, { | |
| method: "HEAD", | |
| }); | |
| // console.log(res.headers.get("Content-Length") ) | |
| fileSize += parseInt(res.headers.get("Content-Length"), 10); | |
| eachfilesize[cid] = parseInt(res.headers.get("Content-Length"), 10); | |
| } | |
| return fileSize; | |
| } | |
| /** | |
| * Formats the given number of bytes into a human-readable string representation. | |
| * | |
| * @param {number} bytes - The number of bytes to be formatted. | |
| * @param {number} [decimals=2] - The number of decimals to round the result to. | |
| * @return {string} The formatted string representation of the input bytes. | |
| */ | |
| function formatBytes(bytes, decimals = 2) { | |
| if (!+bytes) return "0 Bytes"; | |
| const k = 1024; | |
| const dm = decimals < 0 ? 0 : decimals; | |
| const sizes = [ | |
| "Bytes", | |
| "KiB", | |
| "MiB", | |
| "GiB", | |
| "TiB", | |
| "PiB", | |
| "EiB", | |
| "ZiB", | |
| "YiB", | |
| ]; | |
| const i = Math.floor(Math.log(bytes) / Math.log(k)); | |
| return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`; | |
| } | |
| /** | |
| * Asynchronously fetches data in chunks from the specified URL using the given headers and controller. | |
| * | |
| * @param {string} url - The URL to fetch data from | |
| * @param {Object} headers - The headers to include in the fetch request | |
| * @param {AbortController} controller - The controller to signal the fetch should be aborted | |
| * @param {number} start - The starting byte index for fetching data | |
| * @param {number} fileSize - The total size of the file being fetched | |
| */ | |
| async function customFetch(url, res, start, fileSize) { | |
| // console.log('Fetching ' + url); | |
| let chunkSize = 3 * 1024 * 1024; // 10 MB! | |
| for (; start < fileSize; start += chunkSize) { | |
| let end = Math.min(start + chunkSize - 1, fileSize - 1); | |
| // console.log('Fetch ' + start + ' - ' + end); | |
| let headers = { Range: `bytes=${start}-${end}` }; | |
| let response = await fetch(url, { headers }); | |
| // Process the chunk of data | |
| // let response = await fetch(url, { headers: { Range: `bytes=${start}-${fileSize - 1}` } }); | |
| let chunkData = await response.arrayBuffer(); // Or other method for data type | |
| res.write(new Uint8Array(chunkData)); | |
| } | |
| } | |
| app.get("/", async (req, res) => { | |
| // console.log('HERE'); | |
| const shared = req.query.shared; | |
| const filename = req.query.filename; | |
| if (shared) { | |
| // Very gud code but it only serve <80MB file:>> | |
| // const originalUrl = `https://ipfs.particle.network/${shared}`; | |
| // const options = {}; | |
| // if (req.headers.range) { | |
| // options.headers = { Range: req.headers.range }; | |
| // } | |
| // const originalReq = http.request( | |
| // originalUrl, | |
| // options, | |
| // async (originalRes) => { | |
| // const links = [originalUrl]; | |
| // const fileSize = await getFileSize(links); | |
| // const blob = []; // Để nhận dữ liệu trả về từ response | |
| // originalRes.on("data", (chunk) => { | |
| // blob.push(chunk); | |
| // }); | |
| // originalRes.on("end", () => { | |
| // const response = Buffer.concat(blob); | |
| // res.writeHead(originalRes.statusCode, originalRes.headers); | |
| // res.end(response); | |
| // }); | |
| // } | |
| // ); | |
| // originalReq.end(); | |
| // My code lol | |
| // Api for getting data cids | |
| const APIRES = await fetch( | |
| "https://www.ufsdrive.com/api/reqdata?shared=" + shared | |
| ); | |
| if (!APIRES.ok) { | |
| // ctx.waitUntil(log("Get data fail")); | |
| APIRES.status(404).send("Not found"); | |
| } | |
| const data = await APIRES.json(); | |
| const file = data.data; | |
| // console.log(file); | |
| var siez; | |
| if (file.profile_picture != "Multipart") { | |
| siez = await getFileSize([file.profile_picture]); | |
| } else { | |
| siez = await getFileSize(file.data); | |
| } | |
| // console.log(siez) | |
| var parts, start, end; | |
| if (req.headers.range != null) { | |
| // console.log(req.headers.range); | |
| parts = req.headers.range.replace(/bytes=/, "").split("-"); | |
| start = parseInt(parts[0], 10); | |
| end = parts[1] ? parseInt(parts[1], 10) : siez - 1; | |
| } | |
| data.filename = data.filename.replace(/[^a-zA-Z 0-9\.]+/g, ""); | |
| var headers = { | |
| "content-type": data.contentType, | |
| "Cache-Control": "public, max-age=29030400", | |
| "Content-Disposition": `inline; filename="${filename ? filename : data.filename}"`, | |
| "Access-Control-Allow-Origin": "*", | |
| "Access-Control-Allow-Methods": "GET", | |
| "Access-Control-Expose-Headers": | |
| "Content-Range, Content-Length, ETag, Access-Control-Allow-Methods, Access-Control-Allow-Origin", | |
| Vary: "Origin, Access-Control-Request-Headers, Access-Control-Request-Method, Accept-Encoding", | |
| Connection: "keep-alive", | |
| "Accept-Ranges": "bytes", | |
| }; | |
| // if requested has content-range header then we need to change the headers | |
| if (req.headers.range) { | |
| headers["Content-Range"] = `bytes ${start}-${end}/${siez}`; | |
| headers["Content-Length"] = end - start + 1; | |
| } else { | |
| headers["Content-Length"] = siez; | |
| } | |
| // console.log(headers); | |
| // res.set(headers); | |
| if (req.headers.range) { | |
| res.writeHead(206, headers); | |
| } else { | |
| res.writeHead(200, headers); | |
| } | |
| if (req.headers.range) { | |
| // send only requested. | |
| // await log("Have range query") | |
| if (file.profile_picture != "Multipart") { | |
| // await log('One File Query'); | |
| const res2 = await fetch( | |
| `https://ipfs.particle.network/${extractCID(file.profile_picture)}`, | |
| { | |
| method: "GET", | |
| headers: { | |
| Range: req.headers.range, | |
| }, | |
| } | |
| ); | |
| const blob = new Uint8Array(await res2.arrayBuffer()); | |
| // controller.enqueue(blob); | |
| // controller.close(); | |
| res.write(blob); | |
| res.end(); | |
| } else { | |
| var content_range_start = start; | |
| var content_range_end = end; | |
| var current_range = 0; | |
| for (var cid of file.data) { | |
| if (cid.includes("https://")) { | |
| cid = extractCID(cid); | |
| } | |
| // Skip chunks completely outside the range | |
| if (current_range + eachfilesize[cid] <= content_range_start) { | |
| current_range += eachfilesize[cid]; | |
| continue; | |
| } | |
| // Calculate the starting byte within the current chunk | |
| let start_byte = Math.max(content_range_start - current_range, 0); | |
| // Calculate the number of bytes to fetch from this chunk | |
| let bytes_to_fetch = Math.min( | |
| eachfilesize[cid] - start_byte, | |
| content_range_end - current_range | |
| ); | |
| // Adjust the range for the fetch request | |
| let fetch_start = start_byte; | |
| let fetch_end = Math.min( | |
| start_byte + bytes_to_fetch, | |
| eachfilesize[cid] | |
| ); | |
| await customFetch( | |
| `https://ipfs.particle.network/${cid}`, | |
| res, | |
| fetch_start, | |
| fetch_end | |
| ) | |
| // const res2 = await fetch(`https://ipfs.particle.network/${cid}`, { | |
| // method: "GET", | |
| // headers: { | |
| // range: `bytes=${fetch_start}-${fetch_end}`, | |
| // }, | |
| // }); | |
| // Check if the response is partial content | |
| // if (res2.status === 206) { | |
| // // 206 Partial Content | |
| // // Extract the Content-Range header | |
| // const contentRange = res2.headers.get("Content-Range"); | |
| // // console.log(contentRange); | |
| // // Ensure the range matches the request | |
| // // if (rangeStart === fetch_start && rangeEnd === fetch_end) { | |
| // // Enqueue the received chunk | |
| // // controller.enqueue(new Uint8Array(await res.arrayBuffer())); | |
| // res.write(new Uint8Array(await res2.arrayBuffer())); | |
| // // } else { | |
| // // // Handle unexpected range mismatch | |
| // // console.error('Range mismatch in response'); | |
| // // } | |
| // } else { | |
| // // Handle unexpected response status | |
| // console.error("Unexpected response status:", res2.status); | |
| // } | |
| // // Enqueue the fetched data | |
| // controller.enqueue(new Uint8Array(await res.arrayBuffer())); | |
| // // Update the current range | |
| // current_range += bytes_to_fetch; | |
| // // Break if we've reached the end of the requested range | |
| // if (current_range >= content_range_end) { | |
| // break; | |
| // } | |
| // Update the current range | |
| current_range += bytes_to_fetch; | |
| // Check if the end of the requested range has been reached | |
| if (current_range >= content_range_end) { | |
| // controller.close(); | |
| res.end(); | |
| break; | |
| } | |
| } | |
| // controller.close(); | |
| res.end(); | |
| } | |
| } else { | |
| // await log("No range query") | |
| if (file.profile_picture != "Multipart") { | |
| // siez = await getFileSize([file.profile_picture]); | |
| // log("Comsume data") | |
| // const res2 = await fetch( | |
| // `https://ipfs.particle.network/${extractCID(file.profile_picture)}` | |
| // ); | |
| // const blob = new Uint8Array(await res2.arrayBuffer()); | |
| // res.write(blob); | |
| await customFetch( | |
| `https://ipfs.particle.network/${extractCID(file.profile_picture)}`, | |
| res, | |
| 0, | |
| eachfilesize[extractCID(file.profile_picture)] | |
| ) | |
| res.end(); | |
| } else { | |
| // siez = await getFileSize(file.data); | |
| // console.log("One MUL REq"); | |
| for (var cid of file.data) { | |
| if (cid.includes("https://")) { | |
| cid = extractCID(cid); | |
| } | |
| // const res = await fetch(`https://ipfs.particle.network/${cid}`); | |
| // const blob = new Uint8Array(await res.arrayBuffer()); | |
| // console.log("process " + cid); | |
| // const response = await fetch(`https://ipfs.particle.network/${cid}`); | |
| // // console.log(response.headers.get('Content-Length')); | |
| // const blob = new Uint8Array(await response.arrayBuffer()); | |
| // // controller.enqueue(blob); | |
| // res.write(blob); | |
| await customFetch( | |
| `https://ipfs.particle.network/${cid}`, | |
| res, | |
| 0, | |
| eachfilesize[cid] | |
| ); | |
| // controller.enqueue(blob); | |
| } | |
| // console.log("Done"); | |
| res.end(); | |
| } | |
| } | |
| // log("Success") | |
| // const tstream = new TransformStream(); | |
| // // ctx.waitUntil(readable.pipeTo(tstream.writable)); | |
| // await readable.pipeTo(tstream.writable) | |
| // log("Sended!") | |
| // if (req.headers.range) { | |
| // res.status(206).send(readable); | |
| // } else { | |
| // res.status(200).send(readable); | |
| // } | |
| // tstream.readable.pipeTo(res); | |
| // res.pipe(tstream.readable); | |
| } else { | |
| res.status(400).send("Missing shared or filename parameter"); | |
| } | |
| }); | |
| app.listen(7860, "0.0.0.0", () => console.log("Server started on port 7860")); | |