plsgivemeachane commited on
Commit
603190e
·
1 Parent(s): fc01ef9

Added app

Browse files
Files changed (3) hide show
  1. app/index.js +380 -6
  2. app/package-lock.json +21 -0
  3. app/package.json +1 -0
app/index.js CHANGED
@@ -1,9 +1,383 @@
1
  // simple express app
2
- const express = require('express')
3
- const app = express()
4
 
5
- app.get('/', (req, res) => {
6
- res.send('Hello World!')
7
- })
8
 
9
- app.listen(7860, "0.0.0.0", () => console.log('Server started on port 5000'))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  // simple express app
2
+ const express = require("express");
3
+ const cors = require("cors");
4
 
5
+ const app = express();
 
 
6
 
7
+ app.use(
8
+ cors({
9
+ origin: "*",
10
+ })
11
+ );
12
+
13
+ /**
14
+ * Extracts the CID from the given URL.
15
+ *
16
+ * @param {string} url - The URL from which to extract the CID
17
+ * @return {string} The extracted CID
18
+ */
19
+ function extractCID(url) {
20
+ if (url.includes("dweb")) {
21
+ let parts = url.split("/");
22
+ let subParts = parts[2].split(".");
23
+ return subParts[0];
24
+ } else {
25
+ return url.split("/").pop();
26
+ }
27
+ }
28
+
29
+ const eachfilesize = {};
30
+
31
+ /**
32
+ * Calculate the total size of the files associated with the given content identifiers (CIDs).
33
+ *
34
+ * @param {array} cids - An array of content identifiers
35
+ * @return {number} The total size of the files in bytes
36
+ */
37
+ async function getFileSize(cids) {
38
+ var fileSize = 0;
39
+ for (var cid of cids) {
40
+ if (cid.includes("https://")) {
41
+ cid = extractCID(cid);
42
+ }
43
+
44
+ const res = await fetch(`https://ipfs.particle.network/${cid}`, {
45
+ method: "HEAD",
46
+ });
47
+
48
+ // console.log(res.headers.get("Content-Length") )
49
+
50
+ fileSize += parseInt(res.headers.get("Content-Length"), 10);
51
+
52
+ eachfilesize[cid] = parseInt(res.headers.get("Content-Length"), 10);
53
+ }
54
+
55
+ return fileSize;
56
+ }
57
+
58
+ /**
59
+ * Formats the given number of bytes into a human-readable string representation.
60
+ *
61
+ * @param {number} bytes - The number of bytes to be formatted.
62
+ * @param {number} [decimals=2] - The number of decimals to round the result to.
63
+ * @return {string} The formatted string representation of the input bytes.
64
+ */
65
+ function formatBytes(bytes, decimals = 2) {
66
+ if (!+bytes) return "0 Bytes";
67
+
68
+ const k = 1024;
69
+ const dm = decimals < 0 ? 0 : decimals;
70
+ const sizes = [
71
+ "Bytes",
72
+ "KiB",
73
+ "MiB",
74
+ "GiB",
75
+ "TiB",
76
+ "PiB",
77
+ "EiB",
78
+ "ZiB",
79
+ "YiB",
80
+ ];
81
+
82
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
83
+
84
+ return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
85
+ }
86
+
87
+ /**
88
+ * Asynchronously fetches data in chunks from the specified URL using the given headers and controller.
89
+ *
90
+ * @param {string} url - The URL to fetch data from
91
+ * @param {Object} headers - The headers to include in the fetch request
92
+ * @param {AbortController} controller - The controller to signal the fetch should be aborted
93
+ * @param {number} start - The starting byte index for fetching data
94
+ * @param {number} fileSize - The total size of the file being fetched
95
+ */
96
+ // async function customFetch(url, controller, start, fileSize) {
97
+ // console.log('Fetching ' + url);
98
+ // // let chunkSize = 10 * 1024 * 1024; // 10 MB!
99
+ // // for (; start < fileSize; start += chunkSize) {
100
+ // // let end = Math.min(start + chunkSize - 1, fileSize - 1);
101
+ // // // console.log('Fetch ' + start + ' - ' + end);
102
+ // // let headers = { Range: `bytes=${start}-${end}` };
103
+ // // let response = await fetch(url, { headers });
104
+
105
+ // // // Process the chunk of data
106
+ // let response = await fetch(url, { headers: { Range: `bytes=${start}-${fileSize - 1}` } });
107
+ // let chunkData = await response.arrayBuffer(); // Or other method for data type
108
+ // controller.enqueue(new Uint8Array(chunkData));
109
+ // // }
110
+ // }
111
+
112
+ app.get("/", async (req, res) => {
113
+ // console.log('HERE');
114
+ const shared = req.query.shared;
115
+ const filename = req.query.filename;
116
+
117
+ if (shared) {
118
+ // Very gud code but it only serve <80MB file:>>
119
+ // const originalUrl = `https://ipfs.particle.network/${shared}`;
120
+
121
+ // const options = {};
122
+
123
+ // if (req.headers.range) {
124
+ // options.headers = { Range: req.headers.range };
125
+ // }
126
+
127
+ // const originalReq = http.request(
128
+ // originalUrl,
129
+ // options,
130
+ // async (originalRes) => {
131
+ // const links = [originalUrl];
132
+ // const fileSize = await getFileSize(links);
133
+
134
+ // const blob = []; // Để nhận dữ liệu trả về từ response
135
+
136
+ // originalRes.on("data", (chunk) => {
137
+ // blob.push(chunk);
138
+ // });
139
+
140
+ // originalRes.on("end", () => {
141
+ // const response = Buffer.concat(blob);
142
+
143
+ // res.writeHead(originalRes.statusCode, originalRes.headers);
144
+ // res.end(response);
145
+ // });
146
+ // }
147
+ // );
148
+
149
+ // originalReq.end();
150
+
151
+ // My code lol
152
+ // Api for getting data cids
153
+ const APIRES = await fetch(
154
+ "https://www.ufsdrive.com/api/reqdata?shared=" + shared
155
+ );
156
+
157
+ if (!APIRES.ok) {
158
+ // ctx.waitUntil(log("Get data fail"));
159
+ APIRES.status(404).send("Not found");
160
+ }
161
+
162
+ const data = await APIRES.json();
163
+ const file = data.data;
164
+
165
+ // console.log(file);
166
+
167
+ var siez;
168
+
169
+ if (file.profile_picture != "Multipart") {
170
+ siez = await getFileSize([file.profile_picture]);
171
+ } else {
172
+ siez = await getFileSize(file.data);
173
+ }
174
+
175
+ // console.log(siez)
176
+
177
+ var parts, start, end;
178
+ if (req.headers.range != null) {
179
+ console.log(req.headers.range);
180
+ parts = req.headers.range.replace(/bytes=/, "").split("-");
181
+ start = parseInt(parts[0], 10);
182
+ end = parts[1] ? parseInt(parts[1], 10) : siez - 1;
183
+ }
184
+
185
+ var headers = {
186
+ "content-type": data.contentType,
187
+ "Cache-Control": "public, max-age=29030400",
188
+ "Content-Disposition": `inline; filename="${
189
+ filename ? filename : data.filename
190
+ }"`,
191
+ "Access-Control-Allow-Origin": "*",
192
+ "Access-Control-Allow-Methods": "GET",
193
+ "Access-Control-Expose-Headers":
194
+ "Content-Range, Content-Length, ETag, Access-Control-Allow-Methods, Access-Control-Allow-Origin",
195
+ Vary: "Origin, Access-Control-Request-Headers, Access-Control-Request-Method, Accept-Encoding",
196
+ Connection: "keep-alive",
197
+ "Accept-Ranges": "bytes",
198
+ };
199
+
200
+ // if requested has content-range header then we need to change the headers
201
+ if (req.headers.range) {
202
+ headers["Content-Range"] = `bytes ${start}-${end}/${siez}`;
203
+ headers["Content-Length"] = end - start - 1;
204
+ } else {
205
+ headers["Content-Length"] = siez;
206
+ }
207
+
208
+ console.log(headers);
209
+
210
+ // res.set(headers);
211
+ if (req.headers.range) {
212
+ res.writeHead(206, headers);
213
+ } else {
214
+ res.writeHead(200, headers);
215
+ }
216
+
217
+ if (req.headers.range) {
218
+ // send only requested.
219
+ // await log("Have range query")
220
+ if (file.profile_picture != "Multipart") {
221
+ // await log('One File Query');
222
+ const res2 = await fetch(
223
+ `https://ipfs.particle.network/${extractCID(file.profile_picture)}`,
224
+ {
225
+ method: "GET",
226
+ headers: {
227
+ Range: req.headers.range,
228
+ },
229
+ }
230
+ );
231
+ const blob = new Uint8Array(await res2.arrayBuffer());
232
+ // controller.enqueue(blob);
233
+ // controller.close();
234
+ res.write(blob);
235
+ res.end();
236
+ } else {
237
+ var content_range_start = start;
238
+ var content_range_end = end;
239
+ var current_range = 0;
240
+
241
+ for (var cid of file.data) {
242
+ if (cid.includes("https://")) {
243
+ cid = extractCID(cid);
244
+ }
245
+
246
+ // Skip chunks completely outside the range
247
+ if (current_range + eachfilesize[cid] <= content_range_start) {
248
+ current_range += eachfilesize[cid];
249
+ continue;
250
+ }
251
+
252
+ // Calculate the starting byte within the current chunk
253
+ let start_byte = Math.max(content_range_start - current_range, 0);
254
+
255
+ // Calculate the number of bytes to fetch from this chunk
256
+ let bytes_to_fetch = Math.min(
257
+ eachfilesize[cid] - start_byte,
258
+ content_range_end - current_range
259
+ );
260
+
261
+ // Adjust the range for the fetch request
262
+ let fetch_start = start_byte;
263
+ let fetch_end = Math.min(
264
+ start_byte + bytes_to_fetch,
265
+ eachfilesize[cid] - 1
266
+ );
267
+
268
+ const res2 = await fetch(`https://ipfs.particle.network/${cid}`, {
269
+ method: "GET",
270
+ headers: {
271
+ range: `bytes=${fetch_start}-${fetch_end}`,
272
+ },
273
+ });
274
+
275
+ // Check if the response is partial content
276
+ if (res2.status === 206) {
277
+ // 206 Partial Content
278
+ // Extract the Content-Range header
279
+ const contentRange = res2.headers.get("Content-Range");
280
+ console.log(contentRange);
281
+
282
+ // Ensure the range matches the request
283
+ // if (rangeStart === fetch_start && rangeEnd === fetch_end) {
284
+ // Enqueue the received chunk
285
+ // controller.enqueue(new Uint8Array(await res.arrayBuffer()));
286
+ res.write(new Uint8Array(await res2.arrayBuffer()));
287
+
288
+ // } else {
289
+ // // Handle unexpected range mismatch
290
+ // console.error('Range mismatch in response');
291
+ // }
292
+ } else {
293
+ // Handle unexpected response status
294
+ console.error("Unexpected response status:", res2.status);
295
+ }
296
+
297
+ // // Enqueue the fetched data
298
+ // controller.enqueue(new Uint8Array(await res.arrayBuffer()));
299
+
300
+ // // Update the current range
301
+ // current_range += bytes_to_fetch;
302
+
303
+ // // Break if we've reached the end of the requested range
304
+ // if (current_range >= content_range_end) {
305
+ // break;
306
+ // }
307
+
308
+ // Update the current range
309
+ current_range += bytes_to_fetch;
310
+
311
+ // Check if the end of the requested range has been reached
312
+ if (current_range >= content_range_end) {
313
+ // controller.close();
314
+ res.end();
315
+ break;
316
+ }
317
+ }
318
+
319
+ // controller.close();
320
+ res.end();
321
+ }
322
+ } else {
323
+ // await log("No range query")
324
+ if (file.profile_picture != "Multipart") {
325
+ // siez = await getFileSize([file.profile_picture]);
326
+ // log("Comsume data")
327
+ const res2 = await fetch(
328
+ `https://ipfs.particle.network/${extractCID(file.profile_picture)}`
329
+ );
330
+ const blob = new Uint8Array(await res2.arrayBuffer());
331
+ res.write(blob);
332
+ res.end();
333
+ } else {
334
+ // siez = await getFileSize(file.data);
335
+ console.log("One MUL REq");
336
+ for (var cid of file.data) {
337
+ if (cid.includes("https://")) {
338
+ cid = extractCID(cid);
339
+ }
340
+ // const res = await fetch(`https://ipfs.particle.network/${cid}`);
341
+ // const blob = new Uint8Array(await res.arrayBuffer());
342
+ console.log("process " + cid);
343
+ const response = await fetch(`https://ipfs.particle.network/${cid}`);
344
+
345
+ // console.log(response.headers.get('Content-Length'));
346
+
347
+ const blob = new Uint8Array(await response.arrayBuffer());
348
+ // controller.enqueue(blob);
349
+ res.write(blob);
350
+ // await customFetch(
351
+ // `https://ipfs.particle.network/${cid}`,
352
+ // controller,
353
+ // 0,
354
+ // eachfilesize[cid]
355
+ // );
356
+ // controller.enqueue(blob);
357
+ }
358
+
359
+ console.log("Done");
360
+
361
+ res.end();
362
+ }
363
+ }
364
+ // log("Success")
365
+ // const tstream = new TransformStream();
366
+ // // ctx.waitUntil(readable.pipeTo(tstream.writable));
367
+ // await readable.pipeTo(tstream.writable)
368
+ // log("Sended!")
369
+
370
+ // if (req.headers.range) {
371
+ // res.status(206).send(readable);
372
+ // } else {
373
+ // res.status(200).send(readable);
374
+ // }
375
+
376
+ // tstream.readable.pipeTo(res);
377
+ // res.pipe(tstream.readable);
378
+ } else {
379
+ res.status(400).send("Missing shared or filename parameter");
380
+ }
381
+ });
382
+
383
+ app.listen(7860, "0.0.0.0", () => console.log("Server started on port 7860"));
app/package-lock.json CHANGED
@@ -9,6 +9,7 @@
9
  "version": "1.0.0",
10
  "license": "ISC",
11
  "dependencies": {
 
12
  "express": "^4.18.3"
13
  }
14
  },
@@ -110,6 +111,18 @@
110
  "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
111
  "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
112
  },
 
 
 
 
 
 
 
 
 
 
 
 
113
  "node_modules/debug": {
114
  "version": "2.6.9",
115
  "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -454,6 +467,14 @@
454
  "node": ">= 0.6"
455
  }
456
  },
 
 
 
 
 
 
 
 
457
  "node_modules/object-inspect": {
458
  "version": "1.13.1",
459
  "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
 
9
  "version": "1.0.0",
10
  "license": "ISC",
11
  "dependencies": {
12
+ "cors": "^2.8.5",
13
  "express": "^4.18.3"
14
  }
15
  },
 
111
  "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
112
  "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
113
  },
114
+ "node_modules/cors": {
115
+ "version": "2.8.5",
116
+ "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
117
+ "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
118
+ "dependencies": {
119
+ "object-assign": "^4",
120
+ "vary": "^1"
121
+ },
122
+ "engines": {
123
+ "node": ">= 0.10"
124
+ }
125
+ },
126
  "node_modules/debug": {
127
  "version": "2.6.9",
128
  "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
 
467
  "node": ">= 0.6"
468
  }
469
  },
470
+ "node_modules/object-assign": {
471
+ "version": "4.1.1",
472
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
473
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
474
+ "engines": {
475
+ "node": ">=0.10.0"
476
+ }
477
+ },
478
  "node_modules/object-inspect": {
479
  "version": "1.13.1",
480
  "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
app/package.json CHANGED
@@ -10,6 +10,7 @@
10
  "author": "",
11
  "license": "ISC",
12
  "dependencies": {
 
13
  "express": "^4.18.3"
14
  }
15
  }
 
10
  "author": "",
11
  "license": "ISC",
12
  "dependencies": {
13
+ "cors": "^2.8.5",
14
  "express": "^4.18.3"
15
  }
16
  }