telos-autocors 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,78 @@
1
+ # AutoCORS
2
+
3
+ ## 1 - Abstract
4
+
5
+ ***You Shall Pass!***
6
+
7
+ AutoCORS is a JavaScript IO library, which, among other things, provides a set utilities, built
8
+ upon associated conventions, which enable in-browser HTTP requests to be automatically routed
9
+ through CORS proxies.
10
+
11
+ ## 2 - Contents
12
+
13
+ ### 2.1 - Conventions
14
+
15
+ #### 2.1.1 - HTTP JSON
16
+
17
+ HTTP JSON is a JSON object format for representing HTTP requests and responses.
18
+
19
+ An HTTP JSON object shall have a "request" field if representing a request, and a "response" field
20
+ if representing a response. Either type may optionally have a "headers" field and a "body" field.
21
+
22
+ The request field shall contain an object which shall have the string fields "method", specifying
23
+ the HTTP method of the request "uri", specifying the URI or URL of the request, and, optionally,
24
+ "version", specifying the version of the request.
25
+
26
+ The response field shall contain an object which shall have the string fields "version", specifying
27
+ the HTTP version of the response, "status", specifying the status code of the response, and
28
+ "reason", specifying the reason for said status code.
29
+
30
+ The headers field, if present, contains an object where each field's alias defines the alias of an
31
+ HTTP header, and the corresponding value is a string specifying the value of said header.
32
+
33
+ The body field, if present, contains a string specifying the body of the HTTP request or response.
34
+
35
+ ##### 2.1.1.1 - HTTP JSON Examples
36
+
37
+ An HTTP JSON GET request to example.com:
38
+
39
+ { "request": { "method: "GET", uri: "https://example.com/" } }
40
+
41
+ An HTTP JSON POST request to example.com:
42
+
43
+ {
44
+ "request": { "method: "POST", uri: "https://example.com/" },
45
+ "headers": {
46
+ "Host": "example.com",
47
+ "Content-Type": "application/x-www-form-urlencoded",
48
+ "Content-Length": "27"
49
+ },
50
+ "body": "field1=value1\nfield2=value2"
51
+ }
52
+
53
+ ### 2.2 - Usage
54
+
55
+ AutoCORS may be used on any page via the AutoCORS script.
56
+
57
+ Once included, sthe scripehall place an object with the alias "autoCORS" into the global namespace
58
+ of the page.
59
+
60
+ The default functionality of AutoCORS can be activated by running:
61
+
62
+ autoCORS.applyDefault();
63
+
64
+ This will modify the XMLHttpRequest and fetch APIs to automatically route all requests through a
65
+ CORS proxy.
66
+
67
+ Manual customization of the behavior of AutoCORS is possible, though it requires an understanding
68
+ of HTTP JSON.
69
+
70
+ #### 2.2.1 - Script CDN
71
+
72
+ The AutoCORS script can be included in your website from the following CDN link:
73
+
74
+ https://cdn.jsdelivr.net/gh/Telos-Project/AutoCORS/Code/autoCORS.js
75
+
76
+ #### 2.2.2 - Supported Proxies
77
+
78
+ The AutoCORS script makes use of [https://corsproxy.io/](https://corsproxy.io/) by default.
package/apintUtils.js ADDED
@@ -0,0 +1,114 @@
1
+ var apintUtils = {
2
+ buildAPInt: (apint, path) => {
3
+
4
+ apint = JSON.parse(JSON.stringify(apint));
5
+ path = path != null ? path : [];
6
+
7
+ if(apint.packages == null)
8
+ return apint;
9
+
10
+ Object.keys(apint.packages).forEach(key => {
11
+
12
+ if(typeof apint.packages[key] == "string") {
13
+
14
+ if(path.includes(apint.packages[key]))
15
+ return;
16
+
17
+ apint.packages[key] = apintUtils.buildAPInt(
18
+ use(apint.packages[key]),
19
+ path.concat(apint.packages[key])
20
+ );
21
+ }
22
+
23
+ else {
24
+
25
+ apint.packages[key] = apintUtils.buildAPInt(
26
+ apint.packages[key], path
27
+ );
28
+ }
29
+ })
30
+
31
+ return apint;
32
+ },
33
+ queryUtilities: (apint, path, properties, inheritance) => {
34
+
35
+ path = path != null ? path : [];
36
+
37
+ if(typeof path == "string")
38
+ path = path.split(".").map(item => item.toLowerCase());
39
+
40
+ inheritance = inheritance != null ?
41
+ JSON.parse(JSON.stringify(inheritance)) : { };
42
+
43
+ properties = properties != null ? properties : { };
44
+
45
+ if(apint.properties != null)
46
+ Object.assign(inheritance, apint.properties);
47
+
48
+ let utilities = [];
49
+
50
+ if(path.length <= 1 && apint.utilities != null) {
51
+
52
+ Object.keys(apint.utilities).forEach(key => {
53
+
54
+ let utility = JSON.parse(JSON.stringify(apint.utilities[key]));
55
+
56
+ utility.properties = Object.assign(
57
+ Object.assign({ }, inheritance),
58
+ utility.properties != null ? utility.properties : { }
59
+ );
60
+
61
+ let match = true;
62
+
63
+ Object.keys(properties).forEach((item) => {
64
+
65
+ if(JSON.stringify(properties[item]) !=
66
+ JSON.stringify(utility.properties[item])) {
67
+
68
+ match = false;
69
+ }
70
+ });
71
+
72
+ if(match)
73
+ utilities.push(utility);
74
+ });
75
+ }
76
+
77
+ if(apint.packages != null) {
78
+
79
+ Object.keys(apint.packages).forEach(key => {
80
+
81
+ if(typeof apint.packages[key] == "string")
82
+ return;
83
+
84
+ if(path.length > 0) {
85
+
86
+ if(key.toLowerCase() == path[0])
87
+ path = path.slice(1);
88
+ }
89
+
90
+ utilities = utilities.concat(
91
+ apintUtils.queryUtilities(
92
+ apint.packages[key], path, properties, inheritance
93
+ )
94
+ );
95
+ });
96
+ }
97
+
98
+ return utilities;
99
+ },
100
+ loadUtility: (apint, query) => {
101
+
102
+ let utility = apintUtils.queryUtilities(apint, query)[0];
103
+
104
+ if(utility == null)
105
+ return null;
106
+
107
+ return use(
108
+ Array.isArray(utility.source) ? utility.source[0] : utility.source
109
+ );
110
+ }
111
+ };
112
+
113
+ if(typeof module == "object")
114
+ module.exports = apintUtils;
package/autoCORS.js ADDED
@@ -0,0 +1,468 @@
1
+ var autoCORS = {
2
+ applyDefault: () => {
3
+
4
+ autoCORS.proxy = autoCORS.utils.proxies.corsProxy;
5
+
6
+ autoCORS.onSend(autoCORS.onRequestDefault);
7
+ },
8
+ defaultFetch: typeof window != "undefined" ? window.fetch : null,
9
+ DefaultXMLHttpRequest: typeof window != "undefined" ?
10
+ window.XMLHttpRequest : null,
11
+ getPlatform: () => {
12
+
13
+ if(typeof process === 'object') {
14
+
15
+ if(typeof process.versions === 'object') {
16
+
17
+ if(typeof process.versions.node !== 'undefined') {
18
+ return "node";
19
+ }
20
+ }
21
+ }
22
+
23
+ return "browser";
24
+ },
25
+ disable: () => {
26
+ window.XMLHttpRequest = autoCORS.DefaultXMLHttpRequest;
27
+ window.fetch = autoCORS.defaultFetch;
28
+ },
29
+ input: (text) => {
30
+
31
+ return autoCORS.getPlatform() == "browser" ?
32
+ prompt(text) : require("readline-sync").question(text);
33
+ },
34
+ onRequestDefault: (request) => {
35
+ return autoCORS.proxy != null ? autoCORS.proxy(request) : null;
36
+ },
37
+ onSend: (onRequest, onResponse) => {
38
+
39
+ window.XMLHttpRequest = class extends autoCORS.DefaultXMLHttpRequest {
40
+
41
+ constructor() {
42
+
43
+ super();
44
+
45
+ this.request = {
46
+ request: {
47
+ method: "",
48
+ uri: ""
49
+ },
50
+ headers: {
51
+
52
+ },
53
+ body: null
54
+ };
55
+
56
+ this.sync = false;
57
+ }
58
+
59
+ open(method, uri, sync) {
60
+
61
+ this.request.request.method = method;
62
+ this.request.request.uri = uri;
63
+
64
+ this.sync = sync;
65
+ }
66
+
67
+ setRequestHeader(name, value) {
68
+ this.request.headers[name] = value;
69
+ }
70
+
71
+ send(body) {
72
+
73
+ this.request.body = body;
74
+
75
+ this.request = onRequest(this.request);
76
+
77
+ let response = onResponse != null ?
78
+ onResponse(this.request) : null;
79
+
80
+ if(response != null) {
81
+
82
+ Object.defineProperty(this, 'readyState', {
83
+ value: 4,
84
+ writable: true
85
+ });
86
+
87
+ Object.defineProperty(this, 'status', {
88
+ value: 200,
89
+ writable: true
90
+ });
91
+
92
+ Object.defineProperty(this, 'responseText', {
93
+ value: "" + response,
94
+ writable: true
95
+ });
96
+
97
+ if(this.onreadystatechange != null)
98
+ this.onreadystatechange();
99
+ }
100
+
101
+ else {
102
+
103
+ super.open(
104
+ this.request.request.method,
105
+ this.request.request.uri,
106
+ this.sync
107
+ );
108
+
109
+ Object.keys(this.request.headers).forEach(key => {
110
+ super.setRequestHeader(key, this.request.headers[key]);
111
+ });
112
+
113
+ super.send(this.request.body);
114
+ }
115
+ }
116
+ }
117
+
118
+ window.fetch = (uri, options) => {
119
+
120
+ options = options != null ? options : { };
121
+
122
+ let request = {
123
+ request: {
124
+ method: options.method != null ?
125
+ options.method : "GET", uri: uri
126
+ },
127
+ headers: options.headers,
128
+ body: options.body
129
+ }
130
+
131
+ request = onRequest != null ? onRequest(request) : request;
132
+
133
+ let response = onResponse != null ? onResponse(request) : null;
134
+
135
+ return onResponse == null ?
136
+ autoCORS.defaultFetch(url, options) :
137
+ new Promise(
138
+ (resolve) => {
139
+ resolve({ text: () => { return response; } });
140
+ }
141
+ );
142
+ }
143
+ },
144
+ proxy: null,
145
+ read: (path, callback) => {
146
+
147
+ if(typeof path == "function") {
148
+
149
+ let input = document.createElement("input");
150
+
151
+ input.setAttribute("type", "file");
152
+ input.setAttribute("style", "display: none");
153
+
154
+ let listener = function(event) {
155
+
156
+ let upload = event.target.files[0];
157
+
158
+ if(!upload)
159
+ return;
160
+
161
+ let reader = new FileReader();
162
+
163
+ reader.onload = function(event) {
164
+ path(event.target.result, upload.name);
165
+ };
166
+
167
+ reader.readAsText(upload);
168
+ }
169
+
170
+ input.addEventListener(
171
+ 'change',
172
+ listener,
173
+ false
174
+ );
175
+
176
+ document.documentElement.appendChild(input);
177
+
178
+ input.click();
179
+
180
+ document.documentElement.removeChild(input);
181
+
182
+ return;
183
+ }
184
+
185
+ if(autoCORS.getPlatform() == "browser" ||
186
+ path.startsWith("http://") ||
187
+ path.startsWith("https://")) {
188
+
189
+ let response = autoCORS.send(
190
+ { request: { method: "GET", uri: path } },
191
+ callback != null ?
192
+ (response) => { callback(response.body); } : null
193
+ );
194
+
195
+ return callback != null ? null : response.body;
196
+ }
197
+
198
+ return callback != null ?
199
+ require("fs").readFile(path, "utf-8", callback) :
200
+ require("fs").readFileSync(path, "utf-8");
201
+ },
202
+ send: (request, callback) => {
203
+
204
+ if(typeof request == "string")
205
+ request = autoCORS.toJSON(request);
206
+
207
+ let call = autoCORS.getPlatform() == "browser" ?
208
+ new XMLHttpRequest() :
209
+ new (require("xmlhttprequest").XMLHttpRequest)();
210
+
211
+ call.open(
212
+ request.request.method, request.request.uri, callback != null
213
+ );
214
+
215
+ if(request.headers != null) {
216
+
217
+ let keys = Object.keys(request.headers);
218
+
219
+ for(let i = 0; i < keys.length; i++)
220
+ call.setRequestHeader(keys[i], request.headers[keys[i]]);
221
+ }
222
+
223
+ var response = {
224
+ response: { version: "", status: "" },
225
+ headers: { },
226
+ body: ""
227
+ };
228
+
229
+ call.onreadystatechange = function() {
230
+
231
+ if(call.readyState === 4) {
232
+
233
+ response.response.status = call.status;
234
+
235
+ let headers = call.getAllResponseHeaders().trim();
236
+
237
+ if(headers != null) {
238
+
239
+ headers = headers.split("\r\n");
240
+
241
+ for(let i = 0; i < headers.length; i++) {
242
+
243
+ let header = headers[i].split(":");
244
+
245
+ if(header.length >= 2) {
246
+
247
+ response.headers[header[0].trim()] =
248
+ header[1].trim();
249
+ }
250
+
251
+ else
252
+ response.headers[header[0].trim()] = "";
253
+ }
254
+ }
255
+
256
+ response.body = call.responseText;
257
+
258
+ if(callback != null)
259
+ callback(response);
260
+ }
261
+ }
262
+
263
+ call.send(request.body);
264
+
265
+ if(callback == null)
266
+ return response;
267
+ },
268
+ toHTTP: (json) => {
269
+
270
+ let http = "";
271
+
272
+ if(json.request != null) {
273
+
274
+ http += json.request.method + " ";
275
+ http += json.request.uri;
276
+
277
+ if(json.request.version != null)
278
+ http += " " + json.request.version;
279
+ }
280
+
281
+ else {
282
+
283
+ if(json.response.version != null)
284
+ http += " " + json.response.version;
285
+
286
+ if(json.response.status != null)
287
+ http += " " + json.response.status;
288
+
289
+ if(json.response.reason != null)
290
+ http += " " + json.response.reason;
291
+ }
292
+
293
+ if(json.headers != null) {
294
+
295
+ let keys = Object.keys(json.headers);
296
+
297
+ for(let i = 0; i < keys.length; i++)
298
+ http += "\n" + keys[i] + ": " + json.headers[keys[i]];
299
+ }
300
+
301
+ if(json.body != null)
302
+ http += "\n\n" + json.body;
303
+
304
+ return http;
305
+ },
306
+ toJSON: (http) => {
307
+
308
+ let json = { };
309
+
310
+ let lines = http.split("\n");
311
+ let definition = lines[0].split(" ");
312
+
313
+ if(!definition[0].includes("/")) {
314
+
315
+ json.request = {
316
+ method: definition[0],
317
+ uri: definition[1]
318
+ };
319
+
320
+ if(definition.length >= 3)
321
+ json.request.version = definition[2];
322
+ }
323
+
324
+ else {
325
+
326
+ json.response = {
327
+ version: definition[0],
328
+ status: definition[1]
329
+ };
330
+
331
+ if(definition.length >= 3) {
332
+
333
+ json.response.reason = lines[0].substring(
334
+ definition[0].length + definition[1].length + 2
335
+ );
336
+ }
337
+ }
338
+
339
+ for(let i = 1; i < lines.length; i++) {
340
+
341
+ if(lines[i].trim() != "") {
342
+
343
+ if(json.headers == null)
344
+ json.headers = { };
345
+
346
+ let alias =
347
+ lines[i].substring(0, lines[i].indexOf(":")).trim();
348
+
349
+ let value =
350
+ lines[i].substring(lines[i].indexOf(":") + 1).trim();
351
+
352
+ json.headers[alias] = value;
353
+ }
354
+
355
+ else {
356
+
357
+ json.body = lines.slice(i + 1).join("\n");
358
+
359
+ break;
360
+ }
361
+ }
362
+
363
+ return json;
364
+ },
365
+ utils: {
366
+ checkWhitelist: (uri) => {
367
+
368
+ return autoCORS.utils.whitelist.filter(
369
+ item => item.endsWith("/") ?
370
+ uri.toLowerCase().startsWith(item.toLowerCase()) :
371
+ uri.toLowerCase() == item.toLowerCase()
372
+ ).length == 0;
373
+ },
374
+ formatGithubURI: (uri) => {
375
+
376
+ uri = uri.substring(34);
377
+ let user = uri.substring(0, uri.indexOf("/"));
378
+
379
+ uri = uri.substring(uri.indexOf("/") + 1);
380
+ let repo = uri.substring(0, uri.indexOf("/"));
381
+
382
+ uri = uri.substring(uri.indexOf("/") + 1);
383
+
384
+ return "https://cdn.jsdelivr.net/gh/" +
385
+ user +
386
+ "/" +
387
+ repo +
388
+ "/" +
389
+ uri.substring(uri.indexOf("/") + 1);
390
+ },
391
+ proxies: {
392
+ corsProxy: (request) => {
393
+
394
+ if(!autoCORS.utils.checkWhitelist(request.request.uri))
395
+ return request;
396
+
397
+ request = JSON.parse(JSON.stringify(request));
398
+
399
+ if(request.request.uri.startsWith(
400
+ "https://raw.githubusercontent.com/")) {
401
+
402
+ request.request.uri =
403
+ autoCORS.utils.formatGithubURI(
404
+ request.request.uri
405
+ );
406
+ }
407
+
408
+ else {
409
+
410
+ request.request.uri =
411
+ "https://corsproxy.io/?url=" +
412
+ encodeURIComponent(
413
+ request.request.uri
414
+ ).split("%20").join("%2520");
415
+ }
416
+
417
+ return request;
418
+ }
419
+ },
420
+ whitelist: [
421
+ "http://127.0.0.1",
422
+ "https://127.0.0.1",
423
+ "http://localhost",
424
+ "https://localhost",
425
+ "https://cdn.jsdelivr.net/"
426
+ ]
427
+ },
428
+ write: (path, content, callback) => {
429
+
430
+ if(autoCORS.getPlatform() == "browser") {
431
+
432
+ if(callback == true) {
433
+
434
+ let element = document.createElement('a');
435
+
436
+ element.setAttribute(
437
+ 'href',
438
+ 'data:text/plain;charset=utf-8,' +
439
+ encodeURIComponent(content));
440
+
441
+ if(path != null)
442
+ element.setAttribute('download', path);
443
+
444
+ element.style.display = 'none';
445
+ document.documentElement.appendChild(element);
446
+
447
+ element.click();
448
+
449
+ document.documentElement.removeChild(element);
450
+ }
451
+
452
+ // STUB - DOWNLOAD / VIRTUAL SYSTEM
453
+
454
+ return;
455
+ }
456
+
457
+ if(callback != null)
458
+ require("fs").writeFile(path, content, "utf-8", callback);
459
+
460
+ else
461
+ require("fs").writeFileSync(path, content);
462
+
463
+ // STUB - FILL IN NON-EXISTENT PATHS
464
+ }
465
+ };
466
+
467
+ if(typeof module == "object")
468
+ module.exports = autoCORS;
package/package.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "telos-autocors",
3
+ "version": "1.0.0",
4
+ "description": "IO Library Featuring Automatic CORS Proxy Routing for HTTP Requests",
5
+ "main": "autoCORS.js",
6
+ "dependencies": {
7
+ "readline-sync": "~1.0.0",
8
+ "xmlhttprequest": "^1.8.0"
9
+ },
10
+ "author": "",
11
+ "license": "Apache-2.0",
12
+ "homepage": "https://github.com/Telos-Project/AutoCORS"
13
+ }