feat: 增加rate-limit限制

This commit is contained in:
lyz05
2024-01-01 16:31:08 +08:00
parent 19203dc51e
commit 59daa35412
5 changed files with 67 additions and 8776 deletions

8744
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -20,7 +20,7 @@
"dotenv": "^16.0.3",
"ejs": "^3.1.8",
"express": "~4.18.2",
"express-rate-limit": "^6.7.0",
"express-rate-limit": "^7.1.5",
"filesize": "^10.0.5",
"got": "^11.8.2",
"http-errors": "~1.6.3",

View File

@@ -15,10 +15,11 @@ const leancloud = require("../utils/leancloud");
const rateLimit = require('express-rate-limit');
// 访问频率限制
const MAX_count_today = 2000;
const allowlist = ['::1', '::ffff:127.0.0.1'];
const apiLimiter = rateLimit({
windowMs: 24 * 60 * 60 * 1000, // 1 days
max: 1000, // limit each IP to 1000 requests per windowMs
windowMs: 2 * 60 * 1000, // 2 minutes
max: 8, // limit each IP to 8 requests per windowMs
message: 'Too many requests from this IP, please try again later',
standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers
skipFailedRequests: true, // Don't count failed requests (status >= 400)
@@ -26,14 +27,14 @@ const apiLimiter = rateLimit({
});
async function build_response(url, req) {
for (let q = new URLSearchParams(URL.parse(url).query);q.has("url");) {
for (let q = new URLSearchParams(URL.parse(url).query); q.has("url");) {
console.log("Redirecting to", url);
url = q.get("url");
q = new URLSearchParams(URL.parse(url).query);
}
console.log("Real url:", url);
try {
await axios.get(url,{
await axios.get(url, {
headers: { "Accept-Encoding": "gzip,deflate,compress" }
});
} catch (e) {
@@ -66,26 +67,12 @@ async function build_response(url, req) {
return ret;
}
/* GET home page. */
router.get("/", apiLimiter, async function (req, res) {
leancloud.add("DanmakuAccess", {
remoteIP: req.ip,
url: req.query.url,
UA: req.headers["user-agent"]
});
//检查是否包含URL参数
if (!req.query.url) {
const urls = [mgtv.example_urls[0], bilibili.example_urls[0], tencentvideo.example_urls[0], youku.example_urls[0], iqiyi.example_urls[0]];
const path = req.protocol + "://" + req.headers.host + req.originalUrl;
res.render("danmaku", {
path,
urls
});
} else {
const url = req.query.url;
const download = (req.query.download === "on");
const ret = await build_response(url, req);
memory(); //显示内存使用量
async function resolve(req, res) {
const url = req.query.url;
const download = (req.query.download === "on");
const ret = await build_response(url, req);
memory(); //显示内存使用量
try {
if (ret.msg !== "ok") {
res.status(403).send(ret.msg);
return;
@@ -98,8 +85,38 @@ router.get("/", apiLimiter, async function (req, res) {
if (ret.url)
res.redirect(ret.url);
else
res.render("danmaku-xml",{contents: ret.content});
res.render("danmaku-xml", { contents: ret.content });
} catch (e) {
console.log("返回响应出错可能ip被封禁");
}
}
async function index(req, res) {
const urls = [mgtv.example_urls[0], bilibili.example_urls[0], tencentvideo.example_urls[0], youku.example_urls[0], iqiyi.example_urls[0]];
const path = req.protocol + "://" + req.headers.host + req.originalUrl;
res.render("danmaku", {
path,
urls
});
}
/* GET home page. */
router.get("/", apiLimiter, async function (req, res) {
leancloud.add("DanmakuAccess", {
remoteIP: req.ip,
url: req.query.url,
UA: req.headers["user-agent"]
});
// 查询该IP今日访问次数
leancloud.danmakuQuery(leancloud.currentDay(), req.ip).then((count) => {
console.log("访问次数:", req.ip, count);
if (count > MAX_count_today) {
res.status(403).send("今日访问次数过多,请明日再试!");
return;
}
});
//检查是否包含URL参数
if (!req.query.url) index(req, res); else resolve(req, res);
});
router.get("/pageinfo", async function (req, res) {

View File

@@ -75,30 +75,4 @@ describe("App", () => {
done();
});
});
describe("ipinfo模块", () => {
it("GET the ipinfo response", (done) => {
chai.request(app)
.get("/ipinfo")
.end((err, res) => {
res.should.have.status(200);
done();
});
});
it("GET the ipinfo with name", (done) => {
chai.request(app)
.get("/ipinfo?name=home999.cc")
.end((err, res) => {
res.should.have.status(200);
done();
});
});
it("GET the ddns", (done) => {
chai.request(app)
.get("/ipinfo/ddns")
.end((err, res) => {
res.text.should.have.string("subdomain");
done();
});
});
});
});

View File

@@ -1,3 +1,4 @@
const { query } = require("express");
const AV = require("leancloud-storage");
const libqqwry = require("lib-qqwry");
const qqwry = libqqwry();
@@ -31,10 +32,11 @@ function currentMonth() {
return [firstDay, lastDay];
}
async function danmakuQuery(date) {
async function danmakuQuery(date, ip) {
const query = new AV.Query("DanmakuAccess");
query.greaterThanOrEqualTo("createdAt", date[0]);
query.lessThan("createdAt", date[1]);
if (ip) query.equalTo("remoteIP", ip);
query.exists("url");
return await query.count();