Jelajahi Sumber

Workaround nodejs/node#44985

Lutz Roeder 2 tahun lalu
induk
melakukan
87851bda63
1 mengubah file dengan 48 tambahan dan 46 penghapusan
  1. 48 46
      test/worker.js

+ 48 - 46
test/worker.js

@@ -1,5 +1,7 @@
 
 import * as fs from 'fs/promises';
+import * as http from 'http';
+import * as https from 'https';
 import * as path from 'path';
 import * as process from 'process';
 import * as url from 'url';
@@ -350,51 +352,53 @@ export class Target {
         }
     }
 
-    async request(url, init) {
-        const response = await fetch(url, init);
-        if (!response.ok) {
-            throw new Error(response.status.toString());
-        }
-        if (response.body) {
-            const reader = response.body.getReader();
-            const length = response.headers.has('Content-Length') ? parseInt(response.headers.get('Content-Length'), 10) : -1;
-            let position = 0;
-            const target = this;
-            const stream = new ReadableStream({
-                async start(controller) {
-                    const read = async () => {
-                        try {
-                            const result = await reader.read();
-                            if (result.done) {
-                                target.status({ name: 'download' });
-                                controller.close();
-                            } else {
-                                position += result.value.length;
-                                if (length >= 0) {
-                                    const percent = position / length;
-                                    target.status({ name: 'download', target: url, percent: percent });
-                                } else {
-                                    target.status({ name: 'download', target: url, position: position });
-                                }
-                                controller.enqueue(result.value);
-                                return await read();
-                            }
-                        } catch (error) {
-                            controller.error(error);
-                            throw error;
+    async request(location) {
+        const request = new Promise((resolve, reject) => {
+            const url = new URL(location);
+            const request = url.protocol === 'https:' ? https.request(location) : http.request(location);
+            request.on('response', (response) => resolve(response));
+            request.on('error', (error) => reject(error));
+            request.end();
+        });
+        const response = await request;
+        const url = new URL(location);
+        switch (response.statusCode) {
+            case 200: {
+                return new Promise((resolve, reject) => {
+                    let position = 0;
+                    const data = [];
+                    const length = response.headers['content-length'] ? Number(response.headers['content-length']) : -1;
+                    response.on('data', (chunk) => {
+                        position += chunk.length;
+                        if (length >= 0) {
+                            const percent = position / length;
+                            this.status({ name: 'download', target: location, percent: percent });
+                        } else {
+                            this.status({ name: 'download', target: location, position: position });
                         }
-                        return null;
-                    };
-                    return read();
-                }
-            });
-            return new Response(stream, {
-                status: response.status,
-                statusText: response.statusText,
-                headers: response.headers
-            });
+                        data.push(chunk);
+                    });
+                    response.on('end', () => {
+                        this.status({ name: 'download' });
+                        resolve(Buffer.concat(data));
+                    });
+                    response.on('error', (error) => {
+                        this.status({ name: 'download' });
+                        reject(error);
+                    });
+                });
+            }
+            case 301:
+            case 302: {
+                location = response.headers.location;
+                const context = location.startsWith('http://') || location.startsWith('https://') ? '' : url.protocol + '//' + url.hostname;
+                response.destroy();
+                return this.request(context + location);
+            }
+            default: {
+                throw new Error(response.statusCode.toString() + ' ' + location);
+            }
         }
-        return response;
     }
 
     async download(targets, sources) {
@@ -429,9 +433,7 @@ export class Target {
             const dir = path.dirname(this.folder + '/' + target);
             return fs.mkdir(dir, { recursive: true });
         }));
-        const response = await this.request(source);
-        const buffer = await response.arrayBuffer();
-        const data = new Uint8Array(buffer);
+        const data = await this.request(source);
         if (sourceFiles.length > 0) {
             this.status({ name: 'decompress' });
             const archive = decompress(data);