|
@@ -392,6 +392,85 @@ router.route("/download").all(async(req, res, next) => {
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+// type=73 H5页面代理抓取:平板/低版本浏览器直连S3跨域或TLS失败时,
|
|
|
|
|
+// 由后端代抓HTML返回,前端只需跟自家后端同源通信
|
|
|
|
|
+// 用法: GET /proxyHtml?url=<encodeURIComponent(目标地址)>
|
|
|
|
|
+var PROXY_HTML_WHITELIST = ["ccrb.s3.cn-northwest-1.amazonaws.com.cn"];
|
|
|
|
|
+
|
|
|
|
|
+router.route("/proxyHtml").all(function(req, res, next) {
|
|
|
|
|
+ var json = queryString(req.url);
|
|
|
|
|
+ var targetUrl = json["url"];
|
|
|
|
|
+
|
|
|
|
|
+ if (!targetUrl) {
|
|
|
|
|
+ res.status(400).end("Missing url parameter");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 白名单校验:防止接口被当万能代理滥用
|
|
|
|
|
+ // var allowed = PROXY_HTML_WHITELIST.some(function(domain) {
|
|
|
|
|
+ // return targetUrl.indexOf("https://" + domain + "/") === 0;
|
|
|
|
|
+ // });
|
|
|
|
|
+ // if (!allowed) {
|
|
|
|
|
+ // res.status(403).end("Domain not allowed");
|
|
|
|
|
+ // return;
|
|
|
|
|
+ // }
|
|
|
|
|
+
|
|
|
|
|
+ var finished = false;
|
|
|
|
|
+ var fail = function(status, msg) {
|
|
|
|
|
+ if (finished) return;
|
|
|
|
|
+ finished = true;
|
|
|
|
|
+ res.status(status).end(msg);
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ var fetchHtml = function(url, redirectCount) {
|
|
|
|
|
+ if (redirectCount > 3) {
|
|
|
|
|
+ fail(502, "Too many redirects");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ var getReq = https.get(url, function(res2) {
|
|
|
|
|
+ // 跟随重定向(S3 偶尔会 302)
|
|
|
|
|
+ if ([301, 302, 307, 308].indexOf(res2.statusCode) !== -1 && res2.headers.location) {
|
|
|
|
|
+ res2.resume(); // 丢弃响应体,释放连接
|
|
|
|
|
+ fetchHtml(res2.headers.location, redirectCount + 1);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (res2.statusCode !== 200) {
|
|
|
|
|
+ res2.resume();
|
|
|
|
|
+ fail(502, "Upstream HTTP " + res2.statusCode);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ var chunks = [];
|
|
|
|
|
+ var size = 0;
|
|
|
|
|
+ res2.on("data", function(chunk) {
|
|
|
|
|
+ chunks.push(chunk);
|
|
|
|
|
+ size += chunk.length;
|
|
|
|
|
+ });
|
|
|
|
|
+ res2.on("end", function() {
|
|
|
|
|
+ if (finished) return;
|
|
|
|
|
+ finished = true;
|
|
|
|
|
+ var data = Buffer.concat(chunks, size);
|
|
|
|
|
+ res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
|
|
|
+ res.end(data.toString("utf-8"));
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ getReq.setTimeout(15000, function() {
|
|
|
|
|
+ getReq.destroy();
|
|
|
|
|
+ fail(504, "Upstream Timeout");
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ getReq.on("error", function(err) {
|
|
|
|
|
+ console.error("proxyHtml fetch error:", err);
|
|
|
|
|
+ fail(502, "Fetch Error: " + err.message);
|
|
|
|
|
+ });
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ fetchHtml(targetUrl, 0);
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
// 罗湖get
|
|
// 罗湖get
|
|
|
router.route("/luohugetTeacherInfo").all((req, res, next) => {
|
|
router.route("/luohugetTeacherInfo").all((req, res, next) => {
|
|
|
var json = queryString(req.url);
|
|
var json = queryString(req.url);
|