forked from denuitt1/mhr-cfw
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCode.gs
More file actions
142 lines (119 loc) · 3.37 KB
/
Copy pathCode.gs
File metadata and controls
142 lines (119 loc) · 3.37 KB
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/**
* DomainFront Relay — Google Apps Script With Cloudflare Worker Exit
*
* FLOW:
* Client → GAS (Google Apps Script) → CFW (Cloudflare Worker) → Internet
*
* MODES:
* 1. Single: POST { k, m, u, h, b, ct, r } → { s, h, b }
* 2. Batch: POST { k, q: [{m,u,h,b,ct,r}, ...] } → { q: [{s,h,b}, ...] }
*
* CHANGE THESE:
*/
const AUTH_KEY = "STRONG_SECRET_KEY";
const WORKER_URL = "https://example.workers.dev";
const SKIP_HEADERS = {
host: 1, connection: 1, "content-length": 1,
"transfer-encoding": 1, "proxy-connection": 1, "proxy-authorization": 1,
};
function doPost(e) {
try {
var req = JSON.parse(e.postData.contents);
if (req.k !== AUTH_KEY) return _json({ e: "unauthorized" });
if (Array.isArray(req.q)) return _doBatch(req.q);
return _doSingle(req);
} catch (err) {
return _json({ e: String(err) });
}
}
function _doSingle(req) {
if (!req.u || typeof req.u !== "string" || !req.u.match(/^https?:\/\//i)) {
return _json({ e: "bad url" });
}
var payload = _buildWorkerPayload(req);
var resp = UrlFetchApp.fetch(WORKER_URL, {
method: "post",
contentType: "application/json",
payload: JSON.stringify(payload),
muteHttpExceptions: true,
followRedirects: true
});
try {
return _json(JSON.parse(resp.getContentText()));
} catch (e) {
return _json({ e: "invalid worker response", raw: resp.getContentText() });
}
}
function _doBatch(items) {
var fetchArgs = [];
var errorMap = {};
for (var i = 0; i < items.length; i++) {
var item = items[i];
if (!item.u || typeof item.u !== "string" || !item.u.match(/^https?:\/\//i)) {
errorMap[i] = "bad url";
continue;
}
var payload = _buildWorkerPayload(item);
fetchArgs.push({
_i: i,
_o: {
url: WORKER_URL,
method: "post",
contentType: "application/json",
payload: JSON.stringify(payload),
muteHttpExceptions: true,
followRedirects: true
}
});
}
var responses = [];
if (fetchArgs.length > 0) {
responses = UrlFetchApp.fetchAll(fetchArgs.map(function(x) { return x._o; }));
}
var results = [];
var rIdx = 0;
for (var i = 0; i < items.length; i++) {
if (errorMap.hasOwnProperty(i)) {
results.push({ e: errorMap[i] });
} else {
var resp = responses[rIdx++];
try {
results.push(JSON.parse(resp.getContentText()));
} catch (e) {
results.push({ e: "invalid worker response", raw: resp.getContentText() });
}
}
}
return _json({ q: results });
}
function _buildWorkerPayload(req) {
var headers = {};
if (req.h && typeof req.h === "object") {
for (var k in req.h) {
if (req.h.hasOwnProperty(k) && !SKIP_HEADERS[k.toLowerCase()]) {
headers[k] = req.h[k];
}
}
}
return {
u: req.u,
m: (req.m || "GET").toUpperCase(),
h: headers,
b: req.b || null,
ct: req.ct || null,
r: req.r !== false
};
}
function doGet(e) {
return HtmlService.createHtmlOutput(
"<!DOCTYPE html><html><head><title>My App</title></head>" +
'<body style="font-family:sans-serif;max-width:600px;margin:40px auto">' +
"<h1>Relay Active</h1><p>Cloudflare Worker routing enabled.</p>" +
"</body></html>"
);
}
function _json(obj) {
return ContentService
.createTextOutput(JSON.stringify(obj))
.setMimeType(ContentService.MimeType.JSON);
}