-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathwebUtils.lib.js
128 lines (126 loc) · 6.11 KB
/
webUtils.lib.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
* /=======================================================\
* | webUtils |
* | Author(s): Francisco Medina [[email protected]] |
* | Date: 13/Apr/2022 |
* |==============================================================\
* |-> Purpose: HTTP(S) module wrapper with promises |
* \==============================================================/
* Portions of this code are extracted from StackOverflow: https://stackoverflow.com/a/38543075
* Now it should be easier to handle, "modern", with a few extra features, and hopefully won't crumble into pieces
*/
const http = require("http");
const https = require("https");
const zlib = require("zlib");
async function httpRequest(params, postData) {
return new Promise(function(resolve, reject) {
let req = http.request(params, function(res) {
let body = [];
switch(res.headers["content-encoding"]) {
/*
* The following code is the product of many tears trying to over engineer all of the compression cases for hours at 4AM.
* It "should" work on all servers considering that the server actually follows MDN specifications
* Basically we check when the decompression ends to send the final object, and, progressively push decompressed chunks.
*/
case "gzip":
gunzipInstance.on("data", function(chunk) {
body.push(chunk);
});
gunzipInstance.on("end", function() {
resolve({ status: res.statusCode, headers: res.headers, body: Buffer.concat(body) });
});
res.pipe(gunzipInstance);
break;
case "deflate":
deflateInstance.on("data", function(chunk) {
body.push(chunk);
});
deflateInstance.on("end", function() {
resolve({ status: res.statusCode, headers: res.headers, body: Buffer.concat(body) });
});
res.pipe(deflateInstance);
break;
case "br":
// this is the brotli compression algorithm
brotliInstance.on("data", function(chunk) {
body.push(chunk);
});
brotliInstance.on("end", function() {
resolve({ status: res.statusCode, headers: res.headers, body: Buffer.concat(body) });
});
res.pipe(brotliInstance);
break;
default:
// no compression? we store it as is.
res.on('data', function(chunk) {
body.push(chunk);
});
res.on('end', function() {
resolve({ status: res.statusCode, headers: res.headers, body: Buffer.concat(body) });
});
break;
}
});
req.on('error', function(err) { reject(err); });
if(postData) { req.write(postData); }
req.end();
});
}
async function httpsRequest(params, postData) {
const gunzipInstance = zlib.createGunzip();
const deflateInstance = zlib.createInflate();
const brotliInstance = zlib.createBrotliDecompress();
return new Promise(function(resolve, reject) {
let req = https.request(params, function(res) {
let body = [];
switch(res.headers["content-encoding"]) {
/*
* The following code is the product of many tears trying to over engineer all of the compression cases for hours at 4AM.
* It "should" work on all servers considering that the server actually follows MDN specifications
* Basically we check when the decompression ends to send the final object, and, progressively push decompressed chunks.
*/
case "gzip":
gunzipInstance.on("data", function(chunk) {
body.push(chunk);
});
gunzipInstance.on("end", function() {
resolve({ status: res.statusCode, headers: res.headers, body: Buffer.concat(body) });
});
res.pipe(gunzipInstance);
break;
case "deflate":
deflateInstance.on("data", function(chunk) {
body.push(chunk);
});
deflateInstance.on("end", function() {
resolve({ status: res.statusCode, headers: res.headers, body: Buffer.concat(body) });
});
res.pipe(deflateInstance);
break;
case "br":
// this is the brotli compression algorithm
brotliInstance.on("data", function(chunk) {
body.push(chunk);
});
brotliInstance.on("end", function() {
resolve({ status: res.statusCode, headers: res.headers, body: Buffer.concat(body) });
});
res.pipe(brotliInstance);
break;
default:
// no compression? we store it as is.
res.on('data', function(chunk) {
body.push(chunk);
});
res.on('end', function() {
resolve({ status: res.statusCode, headers: res.headers, body: Buffer.concat(body) });
});
break;
}
});
req.on('error', function(err) { reject(err); });
if(postData) { req.write(postData); }
req.end();
});
}
module.exports = { httpRequest, httpsRequest };