Compare commits

...
Author SHA1 Message Date
q ed40b254e4 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	.gitignore
2026-02-06 02:51:10 +08:00
qaiu 8e9b9e6347 删除 auth-test.properties 2026-02-05 22:11:32 +08:00
q 4fa2d88204 chore: 删除包含敏感信息的auth-test.properties并添加到.gitignore 2026-02-05 22:08:00 +08:00
q cb6d4811d2 fix: 完善 .gitignore 防止 Maven 变量目录被提交
- 添加更多构建目录忽略规则
- 防止 Maven 变量未替换时创建的字面量目录被提交
- 包括 build/, out/, classes/ 等常见构建目录
2026-02-05 20:38:12 +08:00
q c19601b209 fix: 完善 .gitignore 防止 Maven 变量目录被提交
- 添加更多构建目录忽略规则
- 防止 Maven 变量未替换时创建的字面量目录被提交
- 包括 build/, out/, classes/ 等常见构建目录
2026-02-05 20:38:12 +08:00
q 6e6215ad7e feat(v0.2.1): 添加认证参数支持和客户端下载命令生成
主要更新:
- 新增 auth 参数加密传递支持 (QK/UC Cookie认证)
- 实现下载命令自动生成 (curl/aria2c/迅雷)
- aria2c 命令支持 8 线程 8 片段下载
- 修复 cookie 字段映射问题
- 优化前端 clientLinks 页面
- 添加认证参数文档和测试用例
- 更新 .gitignore 忽略编译目录
2026-02-05 20:35:47 +08:00
q 3a25e5f2ae feat(v0.2.1): 添加认证参数支持和客户端下载命令生成
主要更新:
- 新增 auth 参数加密传递支持 (QK/UC Cookie认证)
- 实现下载命令自动生成 (curl/aria2c/迅雷)
- aria2c 命令支持 8 线程 8 片段下载
- 修复 cookie 字段映射问题
- 优化前端 clientLinks 页面
- 添加认证参数文档和测试用例
- 更新 .gitignore 忽略编译目录
2026-02-05 20:35:47 +08:00
q 97ae1a5e92 fix: 修复安全漏洞 - 升级依赖版本
- Vert.x: 4.5.22 → 4.5.14 (包含所有安全修复,Netty版本由其管理)
- Logback: 1.5.19 → 1.5.18 (最新稳定版)
- SLF4J: 2.0.5 → 2.0.16
- Jackson: 2.14.2 → 2.18.2
- 移除不必要的 Netty BOM 依赖
2026-02-04 17:21:13 +08:00
q 7fc6367b9e fix: 修复安全漏洞 - 升级依赖版本
- Vert.x: 4.5.22 → 4.5.14 (包含所有安全修复,Netty版本由其管理)
- Logback: 1.5.19 → 1.5.18 (最新稳定版)
- SLF4J: 2.0.5 → 2.0.16
- Jackson: 2.14.2 → 2.18.2
- 移除不必要的 Netty BOM 依赖
2026-02-04 17:21:13 +08:00
q a4a521a6f8 fix: 修复多个安全漏洞
修复的安全问题:
1. Vert.x Web static handler 缓存操纵漏洞 - 升级到 4.5.11
2. Netty CRLF注入漏洞 (CVE-2024-47535) - 强制使用 4.1.115.Final
3. Logback 任意代码执行漏洞 (CVE-2024-12798) - 升级到 1.5.15
4. Vert.x-Web XSS漏洞 - 升级到 4.5.11
5. Logback 类实例化漏洞 (CVE-2023-6378) - 升级到 1.5.15

变更:
- 降级 vertx.version: 4.5.22 → 4.5.11 (稳定安全版本)
- 添加 netty.version: 4.1.115.Final (通过 netty-bom 强制版本)
- 降级 logback.version: 1.5.19 → 1.5.15 (稳定安全版本)
- 升级 slf4j.version: 2.0.5 → 2.0.16
- 升级 jackson.version: 2.14.2 → 2.18.2
- 在 dependencyManagement 中添加 Netty BOM 和 Logback 版本管理
2026-02-04 17:14:53 +08:00
q cb5c83be41 fix: 修复多个安全漏洞
修复的安全问题:
1. Vert.x Web static handler 缓存操纵漏洞 - 升级到 4.5.11
2. Netty CRLF注入漏洞 (CVE-2024-47535) - 强制使用 4.1.115.Final
3. Logback 任意代码执行漏洞 (CVE-2024-12798) - 升级到 1.5.15
4. Vert.x-Web XSS漏洞 - 升级到 4.5.11
5. Logback 类实例化漏洞 (CVE-2023-6378) - 升级到 1.5.15

变更:
- 降级 vertx.version: 4.5.22 → 4.5.11 (稳定安全版本)
- 添加 netty.version: 4.1.115.Final (通过 netty-bom 强制版本)
- 降级 logback.version: 1.5.19 → 1.5.15 (稳定安全版本)
- 升级 slf4j.version: 2.0.5 → 2.0.16
- 升级 jackson.version: 2.14.2 → 2.18.2
- 在 dependencyManagement 中添加 Netty BOM 和 Logback 版本管理
2026-02-04 17:14:53 +08:00
q 2056a91071 优化超星解析,清理冗余代码 2026-02-04 17:10:52 +08:00
q c760e47154 优化超星解析,清理冗余代码 2026-02-04 17:10:52 +08:00
qaiu f6209a8959 更新 README.md
添加夸克,uc解析
2026-02-03 16:18:55 +08:00
qaiu 3d30835ffa 更新 README.md
添加夸克,uc解析
2026-02-03 16:18:55 +08:00
q 72ed0ea8f8 Fixed 蓝奏云目录解析cookie验证问题 2026-02-03 13:27:09 +08:00
q ea47bb39eb Fixed 蓝奏云目录解析cookie验证问题 2026-02-03 13:27:09 +08:00
qaiu d698f82299 Update Playground password protection link in README 2026-02-03 10:41:42 +08:00
qaiu c45967e175 Update Playground password protection link in README 2026-02-03 10:41:42 +08:00
q ba4666c32a Fixed 蓝奏优享解析,v019b21 2026-02-02 16:02:36 +08:00
q 1b357de2f3 Fixed 蓝奏优享解析,v019b21 2026-02-02 16:02:36 +08:00
q d6d37e8204 fixed: 修复蓝奏优享 #159, #158 2026-02-02 15:59:44 +08:00
q cf76a5ddd6 fixed: 修复蓝奏优享 #159, #158 2026-02-02 15:59:44 +08:00
q cb9dbfcc69 蓝奏云规则更新 2026-02-01 10:33:25 +08:00
q 4e27bf0dc4 蓝奏云规则更新 2026-02-01 10:33:25 +08:00
qaiu 42b366ed0f Clean up launch configurations in launch.json,run AppMain
Removed unused Java launch configurations from launch.json.
2026-01-27 07:53:20 +08:00
qaiu 39c082e4ee Clean up launch configurations in launch.json,run AppMain
Removed unused Java launch configurations from launch.json.
2026-01-27 07:53:20 +08:00
qaiu 4021c507b6 更新 README.md, 添加接口文档https://nfdparser.apifox.cn 2026-01-27 00:05:56 +08:00
qaiu 95193fc8f9 更新 README.md, 添加接口文档https://nfdparser.apifox.cn 2026-01-27 00:05:56 +08:00
qaiu 4d8e82080d 189.qaiu.top 大文件解析体验版,支持天翼云盘,移动云盘等
#153 #156 #119 #92
2026-01-26 13:47:37 +08:00
qaiu 4f3131979f 189.qaiu.top 大文件解析体验版,支持天翼云盘,移动云盘等
#153 #156 #119 #92
2026-01-26 13:47:37 +08:00
qaiu fca608b44e 更新 README.md
天翼云盘演示站限时体验
2026-01-26 13:09:49 +08:00
qaiu ad9a8ab0b0 更新 README.md
天翼云盘演示站限时体验
2026-01-26 13:09:49 +08:00
q 34cb89a6ea fix(LeTool): 修复子目录 fileId URL 编码问题
- 在构建 parserUrl 时对 fileId 进行 URL 编码
- 避免 %2B 等特殊字符被前端 axios 自动解码导致请求失败
- 添加异常处理和降级方案
2026-01-23 17:59:19 +08:00
q 1f3161216a fix(LeTool): 修复子目录 fileId URL 编码问题
- 在构建 parserUrl 时对 fileId 进行 URL 编码
- 避免 %2B 等特殊字符被前端 axios 自动解码导致请求失败
- 添加异常处理和降级方案
2026-01-23 17:59:19 +08:00
q 69d5f269bd fix(LeTool): 修复联想乐云目录解析失败问题
- 添加统一的 HEADERS 定义,包含完整的浏览器请求头
- 修复 API_URL_PREFIX 路径(share -> mshare)
- 添加 getCleanShareId() 方法处理 URL 中的查询参数
- 所有请求统一使用 putHeaders(HEADERS)
- 增加调试日志输出
2026-01-23 13:24:11 +08:00
q e5f7b164a3 fix(LeTool): 修复联想乐云目录解析失败问题
- 添加统一的 HEADERS 定义,包含完整的浏览器请求头
- 修复 API_URL_PREFIX 路径(share -> mshare)
- 添加 getCleanShareId() 方法处理 URL 中的查询参数
- 所有请求统一使用 putHeaders(HEADERS)
- 增加调试日志输出
2026-01-23 13:24:11 +08:00
q 459c974cb8 联想乐云文件夹解析 2026-01-23 12:45:51 +08:00
q 7974c92382 联想乐云文件夹解析 2026-01-23 12:45:51 +08:00
qaiu 2f22cb01eb LeTool乐云目录解析 2026-01-23 03:26:35 +08:00
qaiu b51add45f1 LeTool乐云目录解析 2026-01-23 03:26:35 +08:00
qaiu e17fb99de4 启用在线脚本解析器 2026-01-06 02:21:19 +08:00
qaiu cb132359fd 启用在线脚本解析器 2026-01-06 02:21:19 +08:00
q 0f926a57ef 更新Playground和JsHttpClient相关功能,整理文档结构 2026-01-06 00:00:37 +08:00
q b58b3658b5 更新Playground和JsHttpClient相关功能,整理文档结构 2026-01-06 00:00:37 +08:00
q 4380bfe0d6 Merge branch 'main' of github.com:qaiu/netdisk-fast-download 2026-01-04 09:30:54 +08:00
q 9f25aca242 Merge branch 'main' of github.com:qaiu/netdisk-fast-download 2026-01-04 09:30:54 +08:00
q 8127cd0758 fixed. 演练场静态打包问题 2026-01-04 09:29:20 +08:00
q 343c017c79 fixed. 演练场静态打包问题 2026-01-04 09:29:20 +08:00
qaiu 71a220f42b 升级前端版本 2026-01-04 01:14:26 +08:00
qaiu 83af09cf58 升级前端版本 2026-01-04 01:14:26 +08:00
qaiu d3b02676ec Update README.md 2026-01-03 21:20:54 +08:00
qaiu 449475785f Update README.md 2026-01-03 21:20:54 +08:00
q d8f0dc4f8e 更新代码和文档 2026-01-03 21:11:04 +08:00
q 047a8eab89 更新代码和文档 2026-01-03 21:11:04 +08:00
q 48aa5b6148 Add functional test report
- Document all completed tests and fixes
- Verify BUG1, BUG2, BUG3 fixes
- Confirm TypeScript removal
- Confirm text updates (JS演练场 → 脚本演练场)
- Service startup verification
2026-01-02 19:40:26 +08:00
q 93835bd990 Add functional test report
- Document all completed tests and fixes
- Verify BUG1, BUG2, BUG3 fixes
- Confirm TypeScript removal
- Confirm text updates (JS演练场 → 脚本演练场)
- Service startup verification
2026-01-02 19:40:26 +08:00
q a989841a89 Remove TypeScript-related code and documentation
- Remove TypeScript API endpoints from PlaygroundApi
- Remove TypeScript methods from DbService interface and implementation
- Delete PlaygroundTypeScriptCode model class
- Delete TypeScript documentation files
- Clean up unused imports
2026-01-02 19:27:21 +08:00
q 93ab3f3f3f Remove TypeScript-related code and documentation
- Remove TypeScript API endpoints from PlaygroundApi
- Remove TypeScript methods from DbService interface and implementation
- Delete PlaygroundTypeScriptCode model class
- Delete TypeScript documentation files
- Clean up unused imports
2026-01-02 19:27:21 +08:00
q 86783e8e46 Merge branch 'copilot/add-playground-enhancements' 2026-01-02 19:25:05 +08:00
q de7703be83 Merge branch 'copilot/add-playground-enhancements' 2026-01-02 19:25:05 +08:00
q 66b9bcc53a Fix playground bugs and remove TypeScript compiler
- Fix BUG1: JavaScript timeout with proper thread interruption using ScheduledExecutorService
- Fix BUG2: Add URL regex validation before execution in playground test API
- Fix BUG3: Register published parsers to CustomParserRegistry on save/update/delete
- Remove TypeScript compiler functionality (tsCompiler.js, dependencies, UI)
- Add password authentication for playground access
- Add mobile responsive layout support
- Load playground parsers on application startup
2026-01-02 19:24:47 +08:00
q ce1c4ee669 Fix playground bugs and remove TypeScript compiler
- Fix BUG1: JavaScript timeout with proper thread interruption using ScheduledExecutorService
- Fix BUG2: Add URL regex validation before execution in playground test API
- Fix BUG3: Register published parsers to CustomParserRegistry on save/update/delete
- Remove TypeScript compiler functionality (tsCompiler.js, dependencies, UI)
- Add password authentication for playground access
- Add mobile responsive layout support
- Load playground parsers on application startup
2026-01-02 19:24:47 +08:00
qaiu ff08615d1e 更新 README.md 2025-12-23 07:55:59 +08:00
qaiu c60d9fdd61 更新 README.md 2025-12-23 07:55:59 +08:00
qaiu 4a6c3a1f90 更新 README.md 2025-12-08 23:46:58 +08:00
qaiu 2033542f49 更新 README.md 2025-12-08 23:46:58 +08:00
copilot-swe-agent[bot]andqaiu c79702eba8 Address code review feedback: protect types.js endpoint and improve code readability
Co-authored-by: qaiu <[email protected]>
2025-12-07 05:27:07 +00:00
copilot-swe-agent[bot]andqaiu 3775cd0259 Address code review feedback: protect types.js endpoint and improve code readability
Co-authored-by: qaiu <[email protected]>
2025-12-07 05:27:07 +00:00
copilot-swe-agent[bot]andqaiu 41fc935c09 Fix JsonResult API calls and add documentation
Co-authored-by: qaiu <[email protected]>
2025-12-07 05:24:38 +00:00
copilot-swe-agent[bot]andqaiu bec342d778 Fix JsonResult API calls and add documentation
Co-authored-by: qaiu <[email protected]>
2025-12-07 05:24:38 +00:00
copilot-swe-agent[bot]andqaiu 5fbbe5b240 Add playground loading animation, password auth, and mobile layout support
Co-authored-by: qaiu <[email protected]>
2025-12-07 05:20:06 +00:00
copilot-swe-agent[bot]andqaiu 6305d805dd Add playground loading animation, password auth, and mobile layout support
Co-authored-by: qaiu <[email protected]>
2025-12-07 05:20:06 +00:00
copilot-swe-agent[bot] 9c121c03f2 Initial plan 2025-12-07 05:11:50 +00:00
copilot-swe-agent[bot]andqaiu 2ada2fddf7 Add implementation summary in Chinese
Co-authored-by: qaiu <[email protected]>
2025-12-07 04:57:03 +00:00
copilot-swe-agent[bot]andqaiu b74c3f31c4 Add implementation summary in Chinese
Co-authored-by: qaiu <[email protected]>
2025-12-07 04:57:03 +00:00
copilot-swe-agent[bot]andqaiu 66ba8b7ee8 Address code review feedback - improve code quality
Co-authored-by: qaiu <[email protected]>
2025-12-07 04:52:22 +00:00
copilot-swe-agent[bot]andqaiu f23b97e22c Address code review feedback - improve code quality
Co-authored-by: qaiu <[email protected]>
2025-12-07 04:52:22 +00:00
copilot-swe-agent[bot]andqaiu 2edf235941 Complete TypeScript compiler integration with examples and documentation
Co-authored-by: qaiu <[email protected]>
2025-12-07 04:48:38 +00:00
copilot-swe-agent[bot]andqaiu 0560989e77 Complete TypeScript compiler integration with examples and documentation
Co-authored-by: qaiu <[email protected]>
2025-12-07 04:48:38 +00:00
copilot-swe-agent[bot]andqaiu 57ef723368 Add TypeScript compiler integration - core implementation
Co-authored-by: qaiu <[email protected]>
2025-12-07 04:43:36 +00:00
copilot-swe-agent[bot]andqaiu f2c9c34324 Add TypeScript compiler integration - core implementation
Co-authored-by: qaiu <[email protected]>
2025-12-07 04:43:36 +00:00
copilot-swe-agent[bot] a97268c702 Initial plan 2025-12-07 04:34:47 +00:00
copilot-swe-agent[bot]andqaiu 366658b471 Add comprehensive implementation summary
Co-authored-by: qaiu <[email protected]>
2025-12-06 22:56:10 +00:00
copilot-swe-agent[bot]andqaiu 2654b550fb Add comprehensive implementation summary
Co-authored-by: qaiu <[email protected]>
2025-12-06 22:56:10 +00:00
copilot-swe-agent[bot]andqaiu 2a3244a8fa Address code review feedback: fix Promise.race, improve statusText, use English error messages
Co-authored-by: qaiu <[email protected]>
2025-12-06 22:52:37 +00:00
copilot-swe-agent[bot]andqaiu 12a5a17a30 Address code review feedback: fix Promise.race, improve statusText, use English error messages
Co-authored-by: qaiu <[email protected]>
2025-12-06 22:52:37 +00:00
copilot-swe-agent[bot]andqaiu 9912e6fef1 Complete backend implementation with comprehensive documentation
Co-authored-by: qaiu <[email protected]>
2025-12-06 22:51:08 +00:00
copilot-swe-agent[bot]andqaiu e346812c0a Complete backend implementation with comprehensive documentation
Co-authored-by: qaiu <[email protected]>
2025-12-06 22:51:08 +00:00
copilot-swe-agent[bot]andqaiu d475dcbcdc Add fetch polyfill tests and documentation
Co-authored-by: qaiu <[email protected]>
2025-12-06 22:49:32 +00:00
copilot-swe-agent[bot]andqaiu 6b2e391af9 Add fetch polyfill tests and documentation
Co-authored-by: qaiu <[email protected]>
2025-12-06 22:49:32 +00:00
copilot-swe-agent[bot]andqaiu 5ffe94e3a4 Implement fetch polyfill and Promise for ES5 backend
Co-authored-by: qaiu <[email protected]>
2025-12-06 22:44:52 +00:00
copilot-swe-agent[bot]andqaiu 199456cb11 Implement fetch polyfill and Promise for ES5 backend
Co-authored-by: qaiu <[email protected]>
2025-12-06 22:44:52 +00:00
copilot-swe-agent[bot] 636994387f Initial plan 2025-12-06 22:38:17 +00:00
qaiu 90c79f7bac Merge pull request #140 from rensumo/main
增加快速部署方式
2025-12-02 17:21:05 +08:00
qaiu 5809d3b664 Merge pull request #140 from rensumo/main
增加快速部署方式
2025-12-02 17:21:05 +08:00
rensumo 79601b36a5 增加快速部署 2025-12-02 14:43:29 +08:00
rensumo 2bed42a088 增加快速部署 2025-12-02 14:43:29 +08:00
rensumo 96cef89f08 增加快速部署 2025-12-02 14:42:07 +08:00
rensumo 97e912c216 增加快速部署 2025-12-02 14:42:07 +08:00
rensumo e057825b25 增加快速部署
Add quick deployment instructions and Docker deployment section.
2025-12-02 14:40:53 +08:00
rensumo f657aa183c 增加快速部署
Add quick deployment instructions and Docker deployment section.
2025-12-02 14:40:53 +08:00
qaiu ebe848dfe8 Merge pull request #139 from Edakerx/main
Update README.md
2025-11-30 12:30:26 +08:00
qaiu cf634c4464 Merge pull request #139 from Edakerx/main
Update README.md
2025-11-30 12:30:26 +08:00
Edakerx e259a0989e Update README.md
添加赞助商
2025-11-30 12:20:07 +08:00
Edakerx a9b5d9ab57 Update README.md
添加赞助商
2025-11-30 12:20:07 +08:00
q f750aa68e8 js演练场漏洞修复 2025-11-30 02:07:56 +08:00
q f82267f8a7 js演练场漏洞修复 2025-11-30 02:07:56 +08:00
q 49b8501e86 js演练场,ye2 2025-11-29 03:44:47 +08:00
q 46bd5819b3 js演练场,ye2 2025-11-29 03:44:47 +08:00
q fc2e2a4697 Merge remote-tracking branch 'origin/main' 2025-11-29 03:42:25 +08:00
q d10a55d8cb Merge remote-tracking branch 'origin/main' 2025-11-29 03:42:25 +08:00
q b4b1d7f923 js演练场 2025-11-29 03:41:51 +08:00
q e74d5ea97e js演练场 2025-11-29 03:41:51 +08:00
q df646b8c43 js演练场 2025-11-29 02:56:25 +08:00
q 1dfdff7024 js演练场 2025-11-29 02:56:25 +08:00
qaiu 8e790f6b22 更新 README.md 2025-11-28 20:33:07 +08:00
qaiu f5c81e1b8e 更新 README.md 2025-11-28 20:33:07 +08:00
q 2e76af980e front ver 0.1.9.b12 2025-11-28 19:50:29 +08:00
q 804b8853d9 front ver 0.1.9.b12 2025-11-28 19:50:29 +08:00
q 80ccbe5b62 fixed. 123跨区下载错误 2025-11-28 19:48:19 +08:00
q f87a66bc79 fixed. 123跨区下载错误 2025-11-28 19:48:19 +08:00
q aa0cd68f7f 客户端链接(实验性),js解析器插件,汽水音乐,一刻相册,咪咕音乐 2025-11-25 16:34:24 +08:00
q 74b9cc438c 客户端链接(实验性),js解析器插件,汽水音乐,一刻相册,咪咕音乐 2025-11-25 16:34:24 +08:00
qaiu 51833148b1 更新 README.md 2025-11-17 23:06:54 +08:00
qaiu 7829174cc0 更新 README.md 2025-11-17 23:06:54 +08:00
q 0fa77ebf21 Merge remote-tracking branch 'origin/main' 2025-11-15 21:50:45 +08:00
q 2e558df96b Merge remote-tracking branch 'origin/main' 2025-11-15 21:50:45 +08:00
q 584c075930 - [汽水音乐-qishui_music](https://music.douyin.com/qishui/)
- [咪咕音乐-migu](https://music.migu.cn/)
- [一刻相册-baidu_photo](https://photo.baidu.com/)
2025-11-15 21:49:40 +08:00
q 474eea5f80 - [汽水音乐-qishui_music](https://music.douyin.com/qishui/)
- [咪咕音乐-migu](https://music.migu.cn/)
- [一刻相册-baidu_photo](https://photo.baidu.com/)
2025-11-15 21:49:40 +08:00
qaiu 9e7a3718a4 Update README with new links and information 2025-11-14 06:33:16 +08:00
qaiu fc50d1f5ba Update README with new links and information 2025-11-14 06:33:16 +08:00
q 0e2ca2f1ca ce盘优化 2025-11-13 19:32:44 +08:00
q 3b63f48dfa ce盘优化 2025-11-13 19:32:44 +08:00
q 52e889333b Merge remote-tracking branch 'origin/main' 2025-11-13 18:20:32 +08:00
q 95697de1d0 Merge remote-tracking branch 'origin/main' 2025-11-13 18:20:32 +08:00
qaiu 4745440079 Merge pull request #136 from qaiu/copilot/add-ce4tool-parser
Add Cloudreve 4.x API support with Ce4Tool parser
2025-11-13 18:18:30 +08:00
qaiu 1aa9ecdc45 Merge pull request #136 from qaiu/copilot/add-ce4tool-parser
Add Cloudreve 4.x API support with Ce4Tool parser
2025-11-13 18:18:30 +08:00
q b5628eac17 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	parser/src/test/java/cn/qaiu/parser/clientlink/impl/CurlLinkGeneratorTest.java
2025-11-13 17:58:59 +08:00
q 0a3dbc6342 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	parser/src/test/java/cn/qaiu/parser/clientlink/impl/CurlLinkGeneratorTest.java
2025-11-13 17:58:59 +08:00
copilot-swe-agent[bot]andqaiu d23b11577e Simplify and optimize Ce4Tool and CeTool version detection logic
Co-authored-by: qaiu <[email protected]>
2025-11-10 09:59:48 +00:00
copilot-swe-agent[bot]andqaiu 72f215c301 Simplify and optimize Ce4Tool and CeTool version detection logic
Co-authored-by: qaiu <[email protected]>
2025-11-10 09:59:48 +00:00
copilot-swe-agent[bot]andqaiu f1dd9fc0ee Add Ce4Tool for Cloudreve 4.x API support and update CeTool with version detection
Co-authored-by: qaiu <[email protected]>
2025-11-10 09:57:41 +00:00
copilot-swe-agent[bot]andqaiu add90984a5 Add Ce4Tool for Cloudreve 4.x API support and update CeTool with version detection
Co-authored-by: qaiu <[email protected]>
2025-11-10 09:57:41 +00:00
copilot-swe-agent[bot]andqaiu 0877fadcfb Initial planning for Cloudreve 4.x API support
Co-authored-by: qaiu <[email protected]>
2025-11-10 09:53:58 +00:00
copilot-swe-agent[bot]andqaiu 857ac7a2c9 Initial planning for Cloudreve 4.x API support
Co-authored-by: qaiu <[email protected]>
2025-11-10 09:53:58 +00:00
copilot-swe-agent[bot] 733059dc8e Initial plan 2025-11-10 09:50:49 +00:00
qaiu 321380c2b9 更新 README.md 2025-11-08 00:23:22 +08:00
qaiu b807223614 更新 README.md 2025-11-08 00:23:22 +08:00
qaiu deb121a51b 更新 README.md 2025-11-08 00:20:30 +08:00
qaiu c775dabd7e 更新 README.md 2025-11-08 00:20:30 +08:00
qaiu b6aef7c239 更新 README.md 2025-11-08 00:19:16 +08:00
qaiu 5ee0aae6e1 更新 README.md 2025-11-08 00:19:16 +08:00
qaiu b13a7a5ee1 更新 README.md
测试下载链接更新
2025-11-04 15:44:17 +08:00
qaiu 5c8e4d7754 更新 README.md
测试下载链接更新
2025-11-04 15:44:17 +08:00
qaiu fff6a00690 更新 README.md
接口参考优化
2025-10-30 22:42:28 +08:00
qaiu 79123448f6 更新 README.md
接口参考优化
2025-10-30 22:42:28 +08:00
qaiu b4da3cee20 Merge pull request #135 from qaiu/copilot/remove-test-filelist
[WIP] Remove test filelist from repository
2025-10-30 20:24:45 +08:00
qaiu 8e4328f1eb Merge pull request #135 from qaiu/copilot/remove-test-filelist
[WIP] Remove test filelist from repository
2025-10-30 20:24:45 +08:00
copilot-swe-agent[bot]andqaiu 0a650996a1 Remove accidentally committed test-filelist.java file
Co-authored-by: qaiu <[email protected]>
2025-10-30 12:21:01 +00:00
copilot-swe-agent[bot]andqaiu 63c810dcbb Remove accidentally committed test-filelist.java file
Co-authored-by: qaiu <[email protected]>
2025-10-30 12:21:01 +00:00
copilot-swe-agent[bot] 37b91cd388 Initial plan 2025-10-30 12:18:50 +00:00
q 42b721eabf feat: 新增客户端协议生成系统,支持8种主流下载工具
🚀 核心功能
- 新增完整的客户端下载链接生成器系统
- 支持ARIA2、Motrix、比特彗星、迅雷、wget、cURL、IDM、FDM、PowerShell等8种客户端
- 自动处理防盗链参数(User-Agent、Referer、Cookie等)
- 提供可扩展的生成器架构,支持自定义客户端

🔧 技术实现
- ClientLinkGeneratorFactory: 工厂模式管理生成器
- DownloadLinkMeta: 元数据存储下载信息
- ClientLinkUtils: 便捷工具类
- 线程安全的ConcurrentHashMap设计

🌐 前端集成
- 新增ClientLinks.vue界面,支持客户端链接展示
- Element Plus图标系统,混合图标显示
- 客户端检测逻辑优化,避免自动打开外部应用
- 移动端和PC端环境判断

📚 文档完善
- 完整的CLIENT_LINK_GENERATOR_GUIDE.md使用指南
- API文档和测试用例
- 输出示例和最佳实践

从单纯的网盘解析工具升级为完整的下载解决方案生态
2025-10-24 09:29:05 +08:00
q c71d4cfa87 feat: 新增客户端协议生成系统,支持8种主流下载工具
🚀 核心功能
- 新增完整的客户端下载链接生成器系统
- 支持ARIA2、Motrix、比特彗星、迅雷、wget、cURL、IDM、FDM、PowerShell等8种客户端
- 自动处理防盗链参数(User-Agent、Referer、Cookie等)
- 提供可扩展的生成器架构,支持自定义客户端

🔧 技术实现
- ClientLinkGeneratorFactory: 工厂模式管理生成器
- DownloadLinkMeta: 元数据存储下载信息
- ClientLinkUtils: 便捷工具类
- 线程安全的ConcurrentHashMap设计

🌐 前端集成
- 新增ClientLinks.vue界面,支持客户端链接展示
- Element Plus图标系统,混合图标显示
- 客户端检测逻辑优化,避免自动打开外部应用
- 移动端和PC端环境判断

📚 文档完善
- 完整的CLIENT_LINK_GENERATOR_GUIDE.md使用指南
- API文档和测试用例
- 输出示例和最佳实践

从单纯的网盘解析工具升级为完整的下载解决方案生态
2025-10-24 09:29:05 +08:00
q 231d5c3fb9 修复WPS域名匹配正则表达式
- 修复PWPS正则表达式,支持子域名匹配
- 从 https://www\.kdocs\.cn/l/(?<KEY>.+) 修改为 https://(?:[a-zA-Z\d-]+\.)?kdocs\.cn/l/(?<KEY>.+)
- 现在可以正确匹配带子域名的WPS链接,如 www.kdocs.cn
- 测试通过:WPS云文档解析功能正常工作
2025-10-23 09:20:26 +08:00
q 2b17567a1d 修复WPS域名匹配正则表达式
- 修复PWPS正则表达式,支持子域名匹配
- 从 https://www\.kdocs\.cn/l/(?<KEY>.+) 修改为 https://(?:[a-zA-Z\d-]+\.)?kdocs\.cn/l/(?<KEY>.+)
- 现在可以正确匹配带子域名的WPS链接,如 www.kdocs.cn
- 测试通过:WPS云文档解析功能正常工作
2025-10-23 09:20:26 +08:00
q 064efdf3f3 feat: 完善JavaScript解析器功能
- 优化JsScriptLoader,支持JAR包内和文件系统的自动资源文件发现
- 移除预定义文件列表,完全依赖自动检测
- 添加getNoRedirect方法支持重定向处理
- 添加sendMultipartForm方法支持文件上传
- 添加代理配置支持
- 修复JSON解析的压缩处理问题
- 添加默认请求头支持(Accept-Encoding、User-Agent、Accept-Language)
- 更新文档,修正导出方式说明
- 优化README.md结构,删除不符合模块定位的内容
- 升级parser版本到10.2.1
2025-10-22 17:34:19 +08:00
q ba5f88af43 feat: 完善JavaScript解析器功能
- 优化JsScriptLoader,支持JAR包内和文件系统的自动资源文件发现
- 移除预定义文件列表,完全依赖自动检测
- 添加getNoRedirect方法支持重定向处理
- 添加sendMultipartForm方法支持文件上传
- 添加代理配置支持
- 修复JSON解析的压缩处理问题
- 添加默认请求头支持(Accept-Encoding、User-Agent、Accept-Language)
- 更新文档,修正导出方式说明
- 优化README.md结构,删除不符合模块定位的内容
- 升级parser版本到10.2.1
2025-10-22 17:34:19 +08:00
qaiu 7b364a0f90 更新 README.md 2025-10-22 12:27:01 +08:00
qaiu 782f47c7c5 更新 README.md 2025-10-22 12:27:01 +08:00
q c8a4ca7f16 feat: 添加getNoRedirect方法支持302重定向处理
- 在JsHttpClient中添加getNoRedirect方法,支持不自动跟随重定向的HTTP请求
- 修改baidu-photo.js解析器,使用getNoRedirect获取真实的下载链接
- 更新测试用例断言,验证重定向处理功能正常工作
- 修复百度一刻相册解析器302重定向问题,现在能正确获取真实下载链接
2025-10-21 17:47:59 +08:00
q 8f92ce9292 feat: 添加getNoRedirect方法支持302重定向处理
- 在JsHttpClient中添加getNoRedirect方法,支持不自动跟随重定向的HTTP请求
- 修改baidu-photo.js解析器,使用getNoRedirect获取真实的下载链接
- 更新测试用例断言,验证重定向处理功能正常工作
- 修复百度一刻相册解析器302重定向问题,现在能正确获取真实下载链接
2025-10-21 17:47:59 +08:00
qaiu 97627b824c 更新 README.md 2025-10-21 12:49:10 +08:00
qaiu 1c3b5082a2 更新 README.md 2025-10-21 12:49:10 +08:00
q 6dbdc9bd90 优化工作流 2025-10-20 13:45:26 +08:00
q 8535f49786 优化工作流 2025-10-20 13:45:26 +08:00
q 4166ea10af 忽略package-lock.json 2025-10-20 13:42:44 +08:00
q 92043cf415 忽略package-lock.json 2025-10-20 13:42:44 +08:00
q fa12ab2c51 Merge branch 'main' of github.com:qaiu/netdisk-fast-download 2025-10-20 13:38:07 +08:00
q c97a235e23 Merge branch 'main' of github.com:qaiu/netdisk-fast-download 2025-10-20 13:38:07 +08:00
q 4fc4ed8640 feat: 添加 WPS 云文档/WPS 云盘解析支持 (closes #133)
- 新增 PwpsTool 解析器,支持 WPS 云文档直链获取
- 调用 WPS API: https://www.kdocs.cn/api/office/file/{shareKey}/download
- 前端添加 kdocs.cn 链接识别规则
- 前端预览功能优化:WPS 云文档直接使用原分享链接预览
- 后端预览接口特殊处理:判断 shareKey 以 pwps: 开头自动重定向
- 支持提取文件名和有效期信息
- 更新 README 文档,添加 WPS 云文档支持说明

Parser 模块设计:
- 遵循开放封闭原则,易于扩展新网盘
- 只需实现 IPanTool 接口和注册枚举即可
- 支持自定义域名解析和责任链模式

技术特性:
- 免登录获取下载直链
- 支持在线预览(利用 WPS 原生功能)
- 文件大小限制:10M(免费版)/2G(会员版)
- 初始空间:5G(免费版)
2025-10-20 13:33:53 +08:00
q 97c2fe6784 feat: 添加 WPS 云文档/WPS 云盘解析支持 (closes #133)
- 新增 PwpsTool 解析器,支持 WPS 云文档直链获取
- 调用 WPS API: https://www.kdocs.cn/api/office/file/{shareKey}/download
- 前端添加 kdocs.cn 链接识别规则
- 前端预览功能优化:WPS 云文档直接使用原分享链接预览
- 后端预览接口特殊处理:判断 shareKey 以 pwps: 开头自动重定向
- 支持提取文件名和有效期信息
- 更新 README 文档,添加 WPS 云文档支持说明

Parser 模块设计:
- 遵循开放封闭原则,易于扩展新网盘
- 只需实现 IPanTool 接口和注册枚举即可
- 支持自定义域名解析和责任链模式

技术特性:
- 免登录获取下载直链
- 支持在线预览(利用 WPS 原生功能)
- 文件大小限制:10M(免费版)/2G(会员版)
- 初始空间:5G(免费版)
2025-10-20 13:33:53 +08:00
qaiu 48172f2769 Merge pull request #134 from qaiu/copilot/update-parser-documentation
更新parser文档:开发者应继承PanBase并添加WebClient请求流程说明
2025-10-18 07:11:52 +08:00
qaiu 1baa6e36b8 Merge pull request #134 from qaiu/copilot/update-parser-documentation
更新parser文档:开发者应继承PanBase并添加WebClient请求流程说明
2025-10-18 07:11:52 +08:00
copilot-swe-agent[bot]andqaiu c7e6d68fbd Update parser documentation with PanBase inheritance and WebClient flow
Co-authored-by: qaiu <[email protected]>
2025-10-17 23:03:39 +00:00
copilot-swe-agent[bot]andqaiu 9dbc8718a8 Update parser documentation with PanBase inheritance and WebClient flow
Co-authored-by: qaiu <[email protected]>
2025-10-17 23:03:39 +00:00
copilot-swe-agent[bot] e6672a51c5 Initial plan 2025-10-17 22:59:33 +00:00
q abde7841ac web展示内部版本号 2025-10-17 17:19:27 +08:00
q 3107281cdc web展示内部版本号 2025-10-17 17:19:27 +08:00
q 8e661ed1c5 版本号,123文件信息解析支持 2025-10-17 16:41:02 +08:00
q c5b2340fe6 版本号,123文件信息解析支持 2025-10-17 16:41:02 +08:00
q 217cb3a776 parser v10.1.17发布到maven central 允许开发者依赖
1. 添加自定义解析器扩展和相关示例
2. 优化pom结构
2025-10-17 15:51:52 +08:00
q 2f6f977adb parser v10.1.17发布到maven central 允许开发者依赖
1. 添加自定义解析器扩展和相关示例
2. 优化pom结构
2025-10-17 15:51:52 +08:00
q b8c1bca900 parser v10.1.17发布到maven central 允许开发者依赖
1. 添加自定义解析器扩展和相关示例
2. 优化pom结构
2025-10-17 15:51:41 +08:00
q 902443b511 parser v10.1.17发布到maven central 允许开发者依赖
1. 添加自定义解析器扩展和相关示例
2. 优化pom结构
2025-10-17 15:51:41 +08:00
q 5e09b8e92a parser v10.1.17发布到maven central 允许开发者依赖
1. 添加自定义解析器扩展和相关示例
2. 优化pom结构
2025-10-17 15:50:45 +08:00
q 322f173104 parser v10.1.17发布到maven central 允许开发者依赖
1. 添加自定义解析器扩展和相关示例
2. 优化pom结构
2025-10-17 15:50:45 +08:00
q c16bde6bb8 parser发布到maven central方便开发者依赖, pom文件结构调整 2025-10-16 18:08:03 +08:00
q c61ba45d59 parser发布到maven central方便开发者依赖, pom文件结构调整 2025-10-16 18:08:03 +08:00
qaiu eb06eb9f3d 更新 README.md 2025-10-11 00:23:41 +08:00
qaiu 684e8d4c84 更新 README.md 2025-10-11 00:23:41 +08:00
qaiu 0c49088098 更新 README.md
远期规划
2025-10-11 00:19:07 +08:00
qaiu a96bde812d 更新 README.md
远期规划
2025-10-11 00:19:07 +08:00
qaiu b970241a64 Merge pull request #132 from rensumo/main
更新linux部署的下载链接
2025-10-10 09:23:36 +08:00
qaiu c0276f97d6 Merge pull request #132 from rensumo/main
更新linux部署的下载链接
2025-10-10 09:23:36 +08:00
rensumo 6c5aafc11e 更新linux部署的下载链接 2025-10-09 20:32:22 +08:00
rensumo f60d2573e6 更新linux部署的下载链接 2025-10-09 20:32:22 +08:00
qaiu ca0846f4a7 Merge pull request #131 from rensumo/main
修复命令行部署自启动命令的错误
2025-10-08 21:42:47 +08:00
qaiu 7e746ded60 Merge pull request #131 from rensumo/main
修复命令行部署自启动命令的错误
2025-10-08 21:42:47 +08:00
rensumo 14f7fcc5ad 修复命令行部署自启动命令的错误 2025-10-08 15:31:04 +08:00
rensumo 11669c07ed 修复命令行部署自启动命令的错误 2025-10-08 15:31:04 +08:00
q 23a18aba5c web version 2025-09-28 13:44:07 +08:00
q 0c0e4c9cc1 web version 2025-09-28 13:44:07 +08:00
q 2d5a79bb16 Fixed: lz规则更新 #129 #128 2025-09-28 13:38:58 +08:00
q a3ab467c74 Fixed: lz规则更新 #129 #128 2025-09-28 13:38:58 +08:00
q 51e1bbefbb 升级netty依赖 2025-09-15 10:10:30 +08:00
q acb646ee2d 升级netty依赖 2025-09-15 10:10:30 +08:00
q 6647fc5371 fixed. ye解析,去除正则匹配, 分享key去除后缀, #123, #125 2025-09-15 09:44:32 +08:00
q 5a02c38d57 fixed. ye解析,去除正则匹配, 分享key去除后缀, #123, #125 2025-09-15 09:44:32 +08:00
q b67544f0cd fixed. ye解析,去除正则匹配, #124,#125 2025-09-15 09:25:39 +08:00
q bd9ac79ec9 fixed. ye解析,去除正则匹配, #124,#125 2025-09-15 09:25:39 +08:00
qaiu ef5826a73b Merge pull request #124 from qaiu/dependabot/npm_and_yarn/web-front/axios-1.12.0
Bump axios from 1.11.0 to 1.12.0 in /web-front
2025-09-12 17:41:37 +08:00
qaiu d6c8b2f476 Merge pull request #124 from qaiu/dependabot/npm_and_yarn/web-front/axios-1.12.0
Bump axios from 1.11.0 to 1.12.0 in /web-front
2025-09-12 17:41:37 +08:00
dependabot[bot] a48adbd0df Bump axios from 1.11.0 to 1.12.0 in /web-front
Bumps [axios](https://github.com/axios/axios) from 1.11.0 to 1.12.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.11.0...v1.12.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.12.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-09-12 09:37:49 +00:00
dependabot[bot] b616c59f1b Bump axios from 1.11.0 to 1.12.0 in /web-front
Bumps [axios](https://github.com/axios/axios) from 1.11.0 to 1.12.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.11.0...v1.12.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.12.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-09-12 09:37:49 +00:00
q 5c60493a24 修复123解析 #123 2025-09-12 17:34:07 +08:00
q c6603c0d83 修复123解析 #123 2025-09-12 17:34:07 +08:00
q 55e6227de0 优化docker脚本5 2025-09-10 18:23:58 +08:00
q ae0a5644b5 优化docker脚本5 2025-09-10 18:23:58 +08:00
q 24a7395004 优化docker脚本4 2025-09-10 18:16:37 +08:00
q d87ab43a9b 优化docker脚本4 2025-09-10 18:16:37 +08:00
q b2a7187fc5 优化docker脚本3 2025-09-10 18:10:51 +08:00
q cfe084cb07 优化docker脚本3 2025-09-10 18:10:51 +08:00
q ace7cdc88e 优化docker脚本2 2025-09-10 18:05:14 +08:00
q 75521c87ba 优化docker脚本2 2025-09-10 18:05:14 +08:00
q 2e909b5868 优化docker脚本 2025-09-10 17:53:49 +08:00
q 67042b39b3 优化docker脚本 2025-09-10 17:53:49 +08:00
q de78bcbc98 docker多平台支持,add 树莓派 2025-09-10 17:45:27 +08:00
q c65b55d0c6 docker多平台支持,add 树莓派 2025-09-10 17:45:27 +08:00
q c560f0e902 docker多平台支持 2025-09-10 17:27:44 +08:00
q 8e938acdb2 docker多平台支持 2025-09-10 17:27:44 +08:00
q 88860c9302 docker多平台支持 2025-09-10 17:21:33 +08:00
q 5db5b3c75a docker多平台支持 2025-09-10 17:21:33 +08:00
q ef65d0e095 Merge remote-tracking branch 'origin/main' 2025-09-10 17:10:52 +08:00
q 291df9d984 Merge remote-tracking branch 'origin/main' 2025-09-10 17:10:52 +08:00
q 6438505f4a icloud国际版支持,QQ邮箱文件信息获取 2025-09-10 17:10:39 +08:00
q 323c62f4e6 icloud国际版支持,QQ邮箱文件信息获取 2025-09-10 17:10:39 +08:00
qaiu 1be5030dd1 添加docker多平台支持 2025-09-10 17:06:40 +08:00
qaiu 03e2bbbb91 添加docker多平台支持 2025-09-10 17:06:40 +08:00
q 421b2f4a42 Merge remote-tracking branch 'origin/main' 2025-08-19 18:57:00 +08:00
q 4b8660932a Merge remote-tracking branch 'origin/main' 2025-08-19 18:57:00 +08:00
q a66bf84381 直链API添加文件信息
修复蓝奏目录文件大小处理报错问题 #120
2025-08-19 18:56:42 +08:00
q 35c7746e38 直链API添加文件信息
修复蓝奏目录文件大小处理报错问题 #120
2025-08-19 18:56:42 +08:00
qaiu 0c4d366d6d 更新 README.md 2025-08-14 19:36:09 +08:00
qaiu e2155aec45 更新 README.md 2025-08-14 19:36:09 +08:00
qaiu a1d0a921fa 更新 README.md 2025-08-14 19:28:44 +08:00
qaiu aaf34a460e 更新 README.md 2025-08-14 19:28:44 +08:00
q 2092230a61 更新文档 2025-08-14 15:27:03 +08:00
q 1bb30a9ed2 更新文档 2025-08-14 15:27:03 +08:00
q 6e5ae6eff3 Merge remote-tracking branch 'origin/main' 2025-08-12 13:32:09 +08:00
q b1c68aa865 Merge remote-tracking branch 'origin/main' 2025-08-12 13:32:09 +08:00
q 4f8259d772 1. iz match fixed
2. redirect res content add "text/html; charset=utf-8"
2025-08-12 13:29:59 +08:00
q 8b57d04a2e 1. iz match fixed
2. redirect res content add "text/html; charset=utf-8"
2025-08-12 13:29:59 +08:00
qaiu 8b987d9824 Update README.md 2025-08-11 13:32:33 +08:00
qaiu 1a57bddef7 Update README.md 2025-08-11 13:32:33 +08:00
q e8ba451d18 build status 2025-08-11 13:26:06 +08:00
q 1d30716aa6 build status 2025-08-11 13:26:06 +08:00
q 77758db463 Merge remote-tracking branch 'origin/main' 2025-08-11 13:23:59 +08:00
q a2aabfc601 Merge remote-tracking branch 'origin/main' 2025-08-11 13:23:59 +08:00
q 6c58598a8e 用户API 2025-08-11 13:23:30 +08:00
q f7040a3c1c 用户API 2025-08-11 13:23:30 +08:00
qaiu 3ac35230a3 Update README.md 2025-08-11 13:18:00 +08:00
qaiu 40d4a1fcb5 Update README.md 2025-08-11 13:18:00 +08:00
q ca91302d28 Merge remote-tracking branch 'origin/main' 2025-08-11 13:14:59 +08:00
q e01bb2d8d7 Merge remote-tracking branch 'origin/main' 2025-08-11 13:14:59 +08:00
q e07272a5dc 添加支持 QQ闪传,微雨云,优化前端逻辑 2025-08-11 13:14:43 +08:00
q d8a4d2e39f 添加支持 QQ闪传,微雨云,优化前端逻辑 2025-08-11 13:14:43 +08:00
qaiu 461305e1df Update README.md 2025-08-08 12:33:46 +08:00
qaiu dbbd5759ab Update README.md 2025-08-08 12:33:46 +08:00
q 8e8ab10a0f Merge remote-tracking branch 'origin/main' 2025-08-05 15:50:50 +08:00
q 0a59ff2357 Merge remote-tracking branch 'origin/main' 2025-08-05 15:50:50 +08:00
q e754326925 fixed p118 link 2025-08-05 15:50:32 +08:00
q 4e1eb6654d fixed p118 link 2025-08-05 15:50:32 +08:00
qaiu 4c92994c6f 更新 README.md 2025-08-05 13:14:09 +08:00
qaiu b588ba740f 更新 README.md 2025-08-05 13:14:09 +08:00
qaiu 66c57f47ac Merge pull request #113 from qaiu/dependabot/maven/org.apache.commons-commons-lang3-3.18.0
Bump org.apache.commons:commons-lang3 from 3.12.0 to 3.18.0
2025-07-30 09:17:42 +08:00
qaiu af605a2be7 Merge pull request #113 from qaiu/dependabot/maven/org.apache.commons-commons-lang3-3.18.0
Bump org.apache.commons:commons-lang3 from 3.12.0 to 3.18.0
2025-07-30 09:17:42 +08:00
dependabot[bot] ec689eadd8 Bump org.apache.commons:commons-lang3 from 3.12.0 to 3.18.0
Bumps org.apache.commons:commons-lang3 from 3.12.0 to 3.18.0.

---
updated-dependencies:
- dependency-name: org.apache.commons:commons-lang3
  dependency-version: 3.18.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-07-21 09:05:14 +00:00
dependabot[bot] b2630a7e35 Bump org.apache.commons:commons-lang3 from 3.12.0 to 3.18.0
Bumps org.apache.commons:commons-lang3 from 3.12.0 to 3.18.0.

---
updated-dependencies:
- dependency-name: org.apache.commons:commons-lang3
  dependency-version: 3.18.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-07-21 09:05:14 +00:00
qaiu c1e15709a7 Merge pull request #110 from qaiu/dependabot/maven/core-database/org.apache.commons-commons-lang3-3.18.0
Bump org.apache.commons:commons-lang3 from 3.12.0 to 3.18.0 in /core-database
2025-07-21 17:02:12 +08:00
qaiu 211fe92a35 Merge pull request #110 from qaiu/dependabot/maven/core-database/org.apache.commons-commons-lang3-3.18.0
Bump org.apache.commons:commons-lang3 from 3.12.0 to 3.18.0 in /core-database
2025-07-21 17:02:12 +08:00
q 2848937ce7 Merge remote-tracking branch 'origin/main' 2025-07-18 13:00:33 +08:00
q be168a9f0d Merge remote-tracking branch 'origin/main' 2025-07-18 13:00:33 +08:00
q 42ff0c21b2 1. 默认缓存时间修改
2. 文件夹解析异常处理
3. 首页优化
2025-07-18 13:00:12 +08:00
q 977f5dc6dd 1. 默认缓存时间修改
2. 文件夹解析异常处理
3. 首页优化
2025-07-18 13:00:12 +08:00
qaiu 3ed7e547e6 更新 README.md
联系方式更新
2025-07-16 13:30:47 +08:00
qaiu 131cb7085d 更新 README.md
联系方式更新
2025-07-16 13:30:47 +08:00
q fad8e688df 首页样式优化 2025-07-15 18:09:11 +08:00
q 7fbd446a2a 首页样式优化 2025-07-15 18:09:11 +08:00
q b2f2dcac4c Merge remote-tracking branch 'origin/main' 2025-07-14 16:16:13 +08:00
q 7b64699782 Merge remote-tracking branch 'origin/main' 2025-07-14 16:16:13 +08:00
q fcba78e977 启动参数优化 2025-07-14 16:16:00 +08:00
q bad56037c4 启动参数优化 2025-07-14 16:16:00 +08:00
qaiu 77c9d777a1 更新 README.md 2025-07-12 13:47:03 +08:00
qaiu 180e54f278 更新 README.md 2025-07-12 13:47:03 +08:00
dependabot[bot] 4460659210 Bump org.apache.commons:commons-lang3 in /core-database
Bumps org.apache.commons:commons-lang3 from 3.12.0 to 3.18.0.

---
updated-dependencies:
- dependency-name: org.apache.commons:commons-lang3
  dependency-version: 3.18.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-07-12 01:16:21 +00:00
dependabot[bot] ae89e0be26 Bump org.apache.commons:commons-lang3 in /core-database
Bumps org.apache.commons:commons-lang3 from 3.12.0 to 3.18.0.

---
updated-dependencies:
- dependency-name: org.apache.commons:commons-lang3
  dependency-version: 3.18.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
2025-07-12 01:16:21 +00:00
q 8631524107 移动端布局优化 2025-07-11 11:51:08 +08:00
q f19b366b1b 移动端布局优化 2025-07-11 11:51:08 +08:00
q 0579588814 优化构建流v0.1.9b6b 2025-07-10 19:17:22 +08:00
q 6b1bd573c8 优化构建流v0.1.9b6b 2025-07-10 19:17:22 +08:00
q df2bfb6ac7 优化构建流 2025-07-10 19:12:15 +08:00
q 43c82f2f16 优化构建流 2025-07-10 19:12:15 +08:00
q 517b6f8910 del 2025-07-10 19:07:02 +08:00
q e478486d73 del 2025-07-10 19:07:02 +08:00
q 94a46d2833 目录解析支持优化 v0.1.9b6 2025-07-10 18:59:59 +08:00
q 32e5c69735 目录解析支持优化 v0.1.9b6 2025-07-10 18:59:59 +08:00
q 1631a0faa1 目录解析支持优化 v0.1.9b5 2025-07-10 18:58:12 +08:00
q 4ec5b491c5 目录解析支持优化 v0.1.9b5 2025-07-10 18:58:12 +08:00
qaiu 06d5943cb6 Merge remote-tracking branch 'origin/main' 2025-07-09 07:58:10 +08:00
qaiu 6a0e4a695d Merge remote-tracking branch 'origin/main' 2025-07-09 07:58:10 +08:00
qaiu 3095e13676 ye目录解析 2025-07-09 07:57:47 +08:00
qaiu e6d69331be ye目录解析 2025-07-09 07:57:47 +08:00
qaiu 482cbce7e8 Update maven.yml 2025-07-09 07:09:58 +08:00
qaiu f16e196040 Update maven.yml 2025-07-09 07:09:58 +08:00
qaiu ef2fc3ab98 lz目录解析预览 2025-07-09 07:06:12 +08:00
qaiu 2f67e3b04d lz目录解析预览 2025-07-09 07:06:12 +08:00
q 5b57b05eae 目录解析支持优化 v0.1.9b2 2025-07-08 18:58:38 +08:00
q 4663751924 目录解析支持优化 v0.1.9b2 2025-07-08 18:58:38 +08:00
q 093579c6f5 Merge remote-tracking branch 'origin/main' 2025-07-08 18:57:17 +08:00
q e6ae7e2545 Merge remote-tracking branch 'origin/main' 2025-07-08 18:57:17 +08:00
q c2d4990d7f 目录解析支持优化 v0.1.9b2 2025-07-08 18:55:19 +08:00
q 74ec248b8c 目录解析支持优化 v0.1.9b2 2025-07-08 18:55:19 +08:00
qaiu 40e8380738 更新 README.md 2025-07-08 04:03:42 +08:00
qaiu cd04eead07 更新 README.md 2025-07-08 04:03:42 +08:00
qaiu b716e1e861 更新 README.md 2025-07-08 04:02:50 +08:00
qaiu 2b4340a5d6 更新 README.md 2025-07-08 04:02:50 +08:00
qaiu 8432d4952c 更新 README.md 2025-07-08 03:51:46 +08:00
qaiu ff6913264f 更新 README.md 2025-07-08 03:51:46 +08:00
qaiu dd8f085f63 更新 README.md 2025-07-08 03:51:00 +08:00
qaiu ffd88841d5 更新 README.md 2025-07-08 03:51:00 +08:00
qaiu 161ff8d8a3 更新 README.md 2025-07-08 03:48:19 +08:00
qaiu 0ed0d2ed82 更新 README.md 2025-07-08 03:48:19 +08:00
qaiu 1390cd0104 更新 README.md 2025-07-08 03:47:09 +08:00
qaiu c2387c47ee 更新 README.md 2025-07-08 03:47:09 +08:00
qaiu 7a02b1e97f 更新 README.md 2025-07-08 03:46:19 +08:00
qaiu 65cc78de7d 更新 README.md 2025-07-08 03:46:19 +08:00
qaiu 036f107c90 更新 README.md
docker镜像更新
2025-07-08 03:20:18 +08:00
qaiu 8bedfcf794 更新 README.md
docker镜像更新
2025-07-08 03:20:18 +08:00
qaiu 5652383450 Update README.md 2025-07-08 02:23:01 +08:00
qaiu 1cd059f842 Update README.md 2025-07-08 02:23:01 +08:00
qaiu 9a047a5da0 更新 README.md 2025-07-04 19:38:18 +08:00
qaiu 42438f2bbd 更新 README.md 2025-07-04 19:38:18 +08:00
qaiu 8975743a37 更新 README.md 2025-07-04 19:34:53 +08:00
qaiu 1fb6e5d660 更新 README.md 2025-07-04 19:34:53 +08:00
q 0e30eafe49 目录解析支持 2025-07-04 19:20:06 +08:00
q 3fa0588e03 目录解析支持 2025-07-04 19:20:06 +08:00
q 7facb62f21 Merge remote-tracking branch 'origin/main' 2025-07-04 19:17:35 +08:00
q 5a008f4ddd Merge remote-tracking branch 'origin/main' 2025-07-04 19:17:35 +08:00
q 30d43cb961 目录解析支持 2025-07-04 19:16:36 +08:00
q 1a0b3a75c3 目录解析支持 2025-07-04 19:16:36 +08:00
q c505b17e35 目录解析支持 2025-07-04 19:11:39 +08:00
q c5ad19881c 目录解析支持 2025-07-04 19:11:39 +08:00
qaiu 080c4c753d Create update-release-badge.yml 2025-07-04 09:34:22 +08:00
qaiu 6188e5f2c6 Create update-release-badge.yml 2025-07-04 09:34:22 +08:00
q ade0d34d91 start 2025-07-02 18:40:32 +08:00
q 6f19fbd300 start 2025-07-02 18:40:32 +08:00
qaiu 56d082eb0b Update maven.yml
提交任意tag 触发工作流
2025-07-02 18:36:45 +08:00
qaiu 5307da24ed Update maven.yml
提交任意tag 触发工作流
2025-07-02 18:36:45 +08:00
qaiu 795c4529ba Update AppMain.java 2025-07-02 18:29:46 +08:00
qaiu e65da6fe4a Update AppMain.java 2025-07-02 18:29:46 +08:00
qaiu 0f5cfe22ea Update maven.yml
构建docker添加tag版本
2025-07-02 18:26:48 +08:00
qaiu 7ed83e9437 Update maven.yml
构建docker添加tag版本
2025-07-02 18:26:48 +08:00
qaiu 925ad2c3a5 Update AppMain.java 2025-07-02 18:20:30 +08:00
qaiu f008f490d9 Update AppMain.java 2025-07-02 18:20:30 +08:00
qaiu f3e96907fe Update maven.yml
docker镜像构建添加版本号
2025-07-02 18:19:01 +08:00
qaiu 01109dedbd Update maven.yml
docker镜像构建添加版本号
2025-07-02 18:19:01 +08:00
qaiu 75a1e58a7d Update AppMain.java 2025-07-02 18:13:19 +08:00
qaiu f2a78d8937 Update AppMain.java 2025-07-02 18:13:19 +08:00
yyzy-official 379e889f71 Update maven.yml
修改工作流版本号问题
2025-07-02 18:09:48 +08:00
yyzy-official eef56b308c Update maven.yml
修改工作流版本号问题
2025-07-02 18:09:48 +08:00
yyzy-official 40c06f397b Update README.md
收款码隐藏
2025-07-02 17:41:23 +08:00
yyzy-official c9ca47b27d Update README.md
收款码隐藏
2025-07-02 17:41:23 +08:00
yyzy-official 9e9302436e Update README.md
1. 微信联系方式
2. 预览地址
2025-07-02 17:39:14 +08:00
yyzy-official 35e54f5ad5 Update README.md
1. 微信联系方式
2. 预览地址
2025-07-02 17:39:14 +08:00
qaiu 6d816d4193 Update README.md 2025-07-02 15:50:29 +08:00
qaiu 310d516aac Update README.md 2025-07-02 15:50:29 +08:00
qaiu 438eda9c08 Update README.md 2025-07-02 15:46:55 +08:00
qaiu aee84e3cb3 Update README.md 2025-07-02 15:46:55 +08:00
q ace39e4633 jdk24适配 2025-06-17 15:48:52 +08:00
q f9fd68c0f4 jdk24适配 2025-06-17 15:48:52 +08:00
qaiu 7712391f29 更新 README.md 2025-06-06 07:17:49 +08:00
qaiu 9761a9e2d9 更新 README.md 2025-06-06 07:17:49 +08:00
qaiu 65f08dcb02 Update README.md 2025-06-04 16:28:50 +08:00
qaiu 8bed7487de Update README.md 2025-06-04 16:28:50 +08:00
qaiu 1d332aa6f4 Update README.md 2025-06-04 16:26:56 +08:00
qaiu 2b084a3cc8 Update README.md 2025-06-04 16:26:56 +08:00
QAIU ba81641517 1. 修改docker构建失败 2025-06-04 15:37:50 +08:00
QAIU 1caabd1368 1. 修改docker构建失败 2025-06-04 15:37:50 +08:00
qaiu fb30bdb879 Update README.md 2025-06-04 15:27:21 +08:00
qaiu b5397ba303 Update README.md 2025-06-04 15:27:21 +08:00
qaiu fc451d3b41 Update README.md 文件夹解析说明 2025-06-04 15:25:26 +08:00
qaiu 36f9b53f9b Update README.md 文件夹解析说明 2025-06-04 15:25:26 +08:00
QAIU ffee1f3462 1. 修复 小飞机解析错误#106
2. 添加 123云盘文件夹分享下解析为压缩包下载直链
3. 添加 123云盘全部域名支持: "www.123pan.com","www.123pan.cn","www.123865.com","www.123684.com","www.123912.com","www.123pan.cn"
2025-06-04 15:13:05 +08:00
QAIU 26fcbaa9a6 1. 修复 小飞机解析错误#106
2. 添加 123云盘文件夹分享下解析为压缩包下载直链
3. 添加 123云盘全部域名支持: "www.123pan.com","www.123pan.cn","www.123865.com","www.123684.com","www.123912.com","www.123pan.cn"
2025-06-04 15:13:05 +08:00
QAIU f30027dd13 1. 蓝奏云域名适配 2025-05-28 17:01:50 +08:00
QAIU a8a5b6e3ab 1. 蓝奏云域名适配 2025-05-28 17:01:50 +08:00
QAIU 8b6aad17f4 0 2025-05-08 18:18:52 +08:00
QAIU 588e087941 0 2025-05-08 18:18:52 +08:00
QAIU b77930adfb remove yarn.lock 2025-05-08 18:18:15 +08:00
QAIU fe71db0967 remove yarn.lock 2025-05-08 18:18:15 +08:00
qaiu aff8f88076 Update README.md 2025-04-23 14:41:52 +08:00
qaiu 9436575dcb Update README.md 2025-04-23 14:41:52 +08:00
qaiu 4e6582e24c Update nfd-service-template.xml 2025-04-23 14:31:56 +08:00
qaiu 4ea380d28e Update nfd-service-template.xml 2025-04-23 14:31:56 +08:00
qaiu fa9acaccfd Update README.md 2025-04-07 13:29:43 +08:00
qaiu 1f46b477e3 Update README.md 2025-04-07 13:29:43 +08:00
QAIU 0414f85f12 115域名变动,360pan暂不可用,ctfile域名变动 2025-04-03 10:57:28 +08:00
QAIU f7e17a10b5 115域名变动,360pan暂不可用,ctfile域名变动 2025-04-03 10:57:28 +08:00
QAIU 527dd0eeb4 城通分享格式适配, 优化日志打印 2025-03-28 17:59:28 +08:00
QAIU 6e19e29857 城通分享格式适配, 优化日志打印 2025-03-28 17:59:28 +08:00
QAIU 74ed7475c9 json异常时, 快速失败 2025-03-24 13:35:40 +08:00
QAIU f6b5d72784 json异常时, 快速失败 2025-03-24 13:35:40 +08:00
qaiu 54dc3dba96 蓝奏云随机404 问题修复 2025-03-22 12:53:33 +08:00
qaiu 68f1334907 蓝奏云随机404 问题修复 2025-03-22 12:53:33 +08:00
qaiu 9980159090 更新 README.md 2025-03-17 19:24:38 +08:00
qaiu a83f4e9a2f 更新 README.md 2025-03-17 19:24:38 +08:00
QAIU 0b193ebb00 Merge remote-tracking branch 'origin/main' 2025-03-14 14:03:47 +08:00
QAIU fcd8709c7d Merge remote-tracking branch 'origin/main' 2025-03-14 14:03:47 +08:00
QAIU f5fc9843b2 微信版QQ邮箱中转站解析优化(已改名为QQ邮箱云盘) 2025-03-14 14:03:29 +08:00
QAIU 854d0ea241 微信版QQ邮箱中转站解析优化(已改名为QQ邮箱云盘) 2025-03-14 14:03:29 +08:00
qaiu df1f67dd26 Update README.md 2025-02-25 10:29:25 +08:00
qaiu cff223ecd2 Update README.md 2025-02-25 10:29:25 +08:00
qaiu b069a5f576 Update README.md 2025-02-25 10:26:47 +08:00
qaiu 8f14762f43 Update README.md 2025-02-25 10:26:47 +08:00
qaiu 7686763a03 Update README.md 2025-02-25 10:25:35 +08:00
qaiu c37ae638d2 Update README.md 2025-02-25 10:25:35 +08:00
qaiu 635a6eac37 Update README.md 2025-02-25 10:02:23 +08:00
qaiu bcfa46ec43 Update README.md 2025-02-25 10:02:23 +08:00
QAIU 877edc535f md 2025-02-24 17:39:23 +08:00
QAIU 42cfe4aacf md 2025-02-24 17:39:23 +08:00
QAIU 01d59e3c1e add 超星盘,360盘 2025-02-22 16:55:00 +08:00
QAIU 64dba88881 add 超星盘,360盘 2025-02-22 16:55:00 +08:00
QAIU fece2799e3 Merge remote-tracking branch 'origin/main' 2025-02-21 18:28:08 +08:00
QAIU 3f300ded96 Merge remote-tracking branch 'origin/main' 2025-02-21 18:28:08 +08:00
QAIU de9756ee86 优化细节 2025-02-21 18:27:52 +08:00
QAIU 1ceafc5c08 优化细节 2025-02-21 18:27:52 +08:00
qaiu 51f047a51b 更新 README.md 2025-02-20 18:11:39 +08:00
qaiu 93adb06083 更新 README.md 2025-02-20 18:11:39 +08:00
qaiu 04b66e82b7 Update README.md 2025-02-20 18:06:58 +08:00
qaiu 3ef1c81d13 Update README.md 2025-02-20 18:06:58 +08:00
qaiu df89253647 Update README.md 2025-02-20 17:47:00 +08:00
qaiu 84b4deffc6 Update README.md 2025-02-20 17:47:00 +08:00
qaiu 45dbca794e 更新 README.md 2025-02-13 12:14:59 +08:00
qaiu 2e7f1a7e52 更新 README.md 2025-02-13 12:14:59 +08:00
qaiu 857bf28f99 Update README.md 2025-02-12 16:25:16 +08:00
qaiu 59bea226e5 Update README.md 2025-02-12 16:25:16 +08:00
QAIU e07ce15228 新增文件列表解析接口/redirectUrl/:type/:param 2025-02-10 14:19:18 +08:00
QAIU 0bbef0c7a9 新增文件列表解析接口/redirectUrl/:type/:param 2025-02-10 14:19:18 +08:00
QAIU 0637bcfd8e 新增文件列表解析接口/v2/getFileList?url= 2025-02-07 19:28:09 +08:00
QAIU fc91192d0e 新增文件列表解析接口/v2/getFileList?url= 2025-02-07 19:28:09 +08:00
QAIU 23db0563ac 新增文件列表解析接口/v2/getFileList?url= 2025-02-07 19:27:48 +08:00
QAIU 8dbcaed813 新增文件列表解析接口/v2/getFileList?url= 2025-02-07 19:27:48 +08:00
QAIU ccba71aa4e MySQL支持, 其他优化 2025-02-06 16:54:54 +08:00
QAIU 577ec46f71 MySQL支持, 其他优化 2025-02-06 16:54:54 +08:00
QAIU fee4bf2ad6 MySQL支持, 其他优化 2025-02-06 16:52:22 +08:00
QAIU 65bf4534c7 MySQL支持, 其他优化 2025-02-06 16:52:22 +08:00
QAIU 5052fea9ef MySQL支持, 其他优化 2025-02-06 16:52:06 +08:00
QAIU 5b666e1fec MySQL支持, 其他优化 2025-02-06 16:52:06 +08:00
qaiu e85215fca1 Update README.md 2025-02-06 15:51:46 +08:00
qaiu e839f56a91 Update README.md 2025-02-06 15:51:46 +08:00
qaiu e42fe45329 Update README.md 2025-02-06 15:50:26 +08:00
qaiu c5a327e2e0 Update README.md 2025-02-06 15:50:26 +08:00
qaiu 4240815bd1 Create FUNDING.yml 2025-02-05 11:11:01 +08:00
qaiu 5b5a11ac36 Create FUNDING.yml 2025-02-05 11:11:01 +08:00
qaiu 6f0c5305e2 更新 README.md 2025-01-26 16:26:50 +08:00
qaiu 0c3efe326f 更新 README.md 2025-01-26 16:26:50 +08:00
qaiu 757005cad8 更新 README.md 2025-01-26 16:09:45 +08:00
qaiu b9100fb934 更新 README.md 2025-01-26 16:09:45 +08:00
qaiu 81651ad97c 更新 README.md 2025-01-26 15:31:43 +08:00
qaiu 74a98713c1 更新 README.md 2025-01-26 15:31:43 +08:00
qaiu f3763b6058 优化内核, QQ邮箱微信账户分享,添加123请求header 2025-01-24 19:21:58 +08:00
qaiu 339b80bbea 优化内核, QQ邮箱微信账户分享,添加123请求header 2025-01-24 19:21:58 +08:00
qaiu 82478dc485 add: 网易云音乐云盘分享URL支持 2025-01-23 17:23:58 +08:00
qaiu ce0c3b3a1e add: 网易云音乐云盘分享URL支持 2025-01-23 17:23:58 +08:00
qaiu 703fd05d43 Update README.md 2025-01-10 14:33:30 +08:00
qaiu 1e611dd85b Update README.md 2025-01-10 14:33:30 +08:00
qaiu ff868b6e2a Update README.md 2025-01-10 14:21:00 +08:00
qaiu 0791114e92 Update README.md 2025-01-10 14:21:00 +08:00
qaiu 051a74b37b Update README.md 2025-01-10 14:19:59 +08:00
qaiu c85b9a01fd Update README.md 2025-01-10 14:19:59 +08:00
qaiu a0a1085623 Update README.md 2025-01-10 14:14:20 +08:00
qaiu 9c2a0e7f46 Update README.md 2025-01-10 14:14:20 +08:00
qaiu 2612d3919c Update README.md 2025-01-10 14:12:55 +08:00
qaiu 8699aef0da Update README.md 2025-01-10 14:12:55 +08:00
qaiu 6f123a236f Update README.md 2025-01-10 14:12:04 +08:00
qaiu 749bc67212 Update README.md 2025-01-10 14:12:04 +08:00
QAIU 71e57e6a08 Merge remote-tracking branch 'origin/main' 2025-01-07 15:04:07 +08:00
QAIU 67e24e846b Merge remote-tracking branch 'origin/main' 2025-01-07 15:04:07 +08:00
QAIU 7cb18d8186 remove yarn.lock 2025-01-07 15:03:53 +08:00
QAIU 091def569a remove yarn.lock 2025-01-07 15:03:53 +08:00
qaiu cdbf670ece Update maven.yml 2025-01-07 15:00:18 +08:00
qaiu fb0cf9102b Update maven.yml 2025-01-07 15:00:18 +08:00
QAIU e0dafee617 remove yarn.lock 2025-01-07 14:48:16 +08:00
QAIU 69ce48adb4 remove yarn.lock 2025-01-07 14:48:16 +08:00
QAIU c37bce1563 优化解析器链接识别 2025-01-07 13:19:40 +08:00
QAIU 6c3ab975cc 优化解析器链接识别 2025-01-07 13:19:40 +08:00
QAIU 0b3c77d644 115pan 2025-01-07 11:13:52 +08:00
QAIU f501935365 115pan 2025-01-07 11:13:52 +08:00
QAIU 2cf85caf86 115pan分享识别优化 2025-01-06 18:01:23 +08:00
QAIU c3593f335e 115pan分享识别优化 2025-01-06 18:01:23 +08:00
QAIU 594010ba88 代理服务配置优化 2025-01-04 17:38:33 +08:00
QAIU 351bdd9c58 代理服务配置优化 2025-01-04 17:38:33 +08:00
QAIU d91460d2e2 修复蓝奏优享解析失败, gz压缩的json解析 2025-01-04 15:21:15 +08:00
QAIU 812042b95e 修复蓝奏优享解析失败, gz压缩的json解析 2025-01-04 15:21:15 +08:00
QAIU 89713e6ac9 修复蓝奏优享解析失败 2025-01-04 14:21:32 +08:00
QAIU 9957fcbce8 修复蓝奏优享解析失败 2025-01-04 14:21:32 +08:00
QAIU 17c9b2538c Merge remote-tracking branch 'origin/main' 2025-01-04 14:18:46 +08:00
QAIU acb2c00cca Merge remote-tracking branch 'origin/main' 2025-01-04 14:18:46 +08:00
QAIU d337b003cb 常规测试 2024-12-30 18:11:53 +08:00
QAIU 9655b8715e 常规测试 2024-12-30 18:11:53 +08:00
qaiu 8f1485656b Update README.md
add docker加速地址
2024-12-23 13:05:25 +08:00
qaiu 13de30e8b5 Update README.md
add docker加速地址
2024-12-23 13:05:25 +08:00
qaiu f0c4ec3031 Update maven.yml 2024-12-23 13:02:51 +08:00
qaiu 1cfeae2ad2 Update maven.yml 2024-12-23 13:02:51 +08:00
qaiu 458be84aca Update maven.yml 2024-12-23 13:00:28 +08:00
qaiu 31b4190eaf Update maven.yml 2024-12-23 13:00:28 +08:00
qaiu c7716aad34 Update README.md 2024-12-18 13:05:16 +08:00
qaiu 380e1c7482 Update README.md 2024-12-18 13:05:16 +08:00
QAIU 4a3e734408 1. onedrive
常规测试
2024-12-18 11:46:06 +08:00
QAIU f202800a0a 1. onedrive
常规测试
2024-12-18 11:46:06 +08:00
qaiu 54cc212753 Merge pull request #78 from xrgzs/add-ghcr
增加 ghcr.io 容器构建
2024-12-17 16:24:03 +08:00
qaiu 96d246e64f Merge pull request #78 from xrgzs/add-ghcr
增加 ghcr.io 容器构建
2024-12-17 16:24:03 +08:00
xrgzs f4ae1eaa51 PR时不更新依赖图 2024-12-17 16:15:59 +08:00
xrgzs 75b460f4b0 PR时不更新依赖图 2024-12-17 16:15:59 +08:00
xrgzs d2537282c9 增加 ghcr.io 容器构建 2024-12-17 15:47:05 +08:00
xrgzs 1ba7af485d 增加 ghcr.io 容器构建 2024-12-17 15:47:05 +08:00
QAIU 87527688c3 1. 代理配置 2024-12-17 15:21:59 +08:00
QAIU 76c16c6312 1. 代理配置 2024-12-17 15:21:59 +08:00
qaiu 2be0b6505a 更新 P115Tool.java
UA问题说明
2024-12-17 09:37:48 +08:00
qaiu 66a09a8f1c 更新 P115Tool.java
UA问题说明
2024-12-17 09:37:48 +08:00
QAIU 672f100c7c 1. 动态UA 2024-12-16 19:01:55 +08:00
QAIU 235fed1b4e 1. 动态UA 2024-12-16 19:01:55 +08:00
QAIU 5af402c0c5 1. 动态UA 2024-12-16 18:52:02 +08:00
QAIU f75921ba03 1. 动态UA 2024-12-16 18:52:02 +08:00
QAIU 693a4f0f63 1. P115网盘解析BUG
2. 完善onedrive支持
2024-12-16 15:54:06 +08:00
QAIU 202b261a53 1. P115网盘解析BUG
2. 完善onedrive支持
2024-12-16 15:54:06 +08:00
QAIU f8d2426ff6 API 2024-12-16 13:19:15 +08:00
QAIU 95c39d258e API 2024-12-16 13:19:15 +08:00
QAIU 973a9bedcd 添加115网盘支持(测试中)#75 2024-12-16 13:15:53 +08:00
QAIU 71b35e4651 添加115网盘支持(测试中)#75 2024-12-16 13:15:53 +08:00
QAIU a583733400 修复小飞机解析失败 2024-12-16 12:31:34 +08:00
QAIU 2465a4d6d3 修复小飞机解析失败 2024-12-16 12:31:34 +08:00
QAIU 78eb51b3ca 处理编译失败问题 2024-11-29 11:50:44 +08:00
QAIU 30d4ce4781 处理编译失败问题 2024-11-29 11:50:44 +08:00
QAIU a2606be9d8 修复蓝奏优享#71 2024-11-26 13:02:02 +08:00
QAIU 27be70ea00 修复蓝奏优享#71 2024-11-26 13:02:02 +08:00
qaiu a4975c72ce Merge pull request #70 from qaiu/dependabot/npm_and_yarn/web-front/eslint/plugin-kit-0.2.3
Bump @eslint/plugin-kit from 0.2.2 to 0.2.3 in /web-front
2024-11-18 12:12:25 +08:00
qaiu 0c22267eaa Merge pull request #70 from qaiu/dependabot/npm_and_yarn/web-front/eslint/plugin-kit-0.2.3
Bump @eslint/plugin-kit from 0.2.2 to 0.2.3 in /web-front
2024-11-18 12:12:25 +08:00
dependabot[bot] 58f96822a4 Bump @eslint/plugin-kit from 0.2.2 to 0.2.3 in /web-front
Bumps [@eslint/plugin-kit](https://github.com/eslint/rewrite) from 0.2.2 to 0.2.3.
- [Release notes](https://github.com/eslint/rewrite/releases)
- [Changelog](https://github.com/eslint/rewrite/blob/main/release-please-config.json)
- [Commits](https://github.com/eslint/rewrite/compare/plugin-kit-v0.2.2...plugin-kit-v0.2.3)

---
updated-dependencies:
- dependency-name: "@eslint/plugin-kit"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-11-15 21:50:27 +00:00
dependabot[bot] d4f4ec67c3 Bump @eslint/plugin-kit from 0.2.2 to 0.2.3 in /web-front
Bumps [@eslint/plugin-kit](https://github.com/eslint/rewrite) from 0.2.2 to 0.2.3.
- [Release notes](https://github.com/eslint/rewrite/releases)
- [Changelog](https://github.com/eslint/rewrite/blob/main/release-please-config.json)
- [Commits](https://github.com/eslint/rewrite/compare/plugin-kit-v0.2.2...plugin-kit-v0.2.3)

---
updated-dependencies:
- dependency-name: "@eslint/plugin-kit"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-11-15 21:50:27 +00:00
qaiu 96b0d94986 Update README.md 2024-11-13 13:59:54 +08:00
qaiu df74d9a117 Update README.md 2024-11-13 13:59:54 +08:00
QAIU 70b38db8c5 IP互助计划, 添加正向代理服务(TODO) 2024-11-12 19:05:43 +08:00
QAIU 2fc7556f39 IP互助计划, 添加正向代理服务(TODO) 2024-11-12 19:05:43 +08:00
QAIU b6a9c2d3a0 . 2024-11-07 18:37:08 +08:00
QAIU 418dcde15f . 2024-11-07 18:37:08 +08:00
QAIU a01df6c7db web file package config 2024-11-07 12:34:24 +08:00
QAIU 59db290cae web file package config 2024-11-07 12:34:24 +08:00
QAIU 4455bee570 pod update 2024-11-05 18:42:32 +08:00
QAIU 2992d3586f pod update 2024-11-05 18:42:32 +08:00
qaiu cd0adef2ed Merge pull request #67 from qaiu/dependabot/npm_and_yarn/web-front/http-proxy-middleware-2.0.7
Bump http-proxy-middleware from 2.0.6 to 2.0.7 in /web-front
2024-11-04 19:13:24 +08:00
qaiu 7b8eea4865 Merge pull request #67 from qaiu/dependabot/npm_and_yarn/web-front/http-proxy-middleware-2.0.7
Bump http-proxy-middleware from 2.0.6 to 2.0.7 in /web-front
2024-11-04 19:13:24 +08:00
dependabot[bot] 4aa24a65fb Bump http-proxy-middleware from 2.0.6 to 2.0.7 in /web-front
Bumps [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware) from 2.0.6 to 2.0.7.
- [Release notes](https://github.com/chimurai/http-proxy-middleware/releases)
- [Changelog](https://github.com/chimurai/http-proxy-middleware/blob/v2.0.7/CHANGELOG.md)
- [Commits](https://github.com/chimurai/http-proxy-middleware/compare/v2.0.6...v2.0.7)

---
updated-dependencies:
- dependency-name: http-proxy-middleware
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-11-04 10:58:07 +00:00
dependabot[bot] 6b2bba2854 Bump http-proxy-middleware from 2.0.6 to 2.0.7 in /web-front
Bumps [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware) from 2.0.6 to 2.0.7.
- [Release notes](https://github.com/chimurai/http-proxy-middleware/releases)
- [Changelog](https://github.com/chimurai/http-proxy-middleware/blob/v2.0.7/CHANGELOG.md)
- [Commits](https://github.com/chimurai/http-proxy-middleware/compare/v2.0.6...v2.0.7)

---
updated-dependencies:
- dependency-name: http-proxy-middleware
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-11-04 10:58:07 +00:00
QAIU 760dca8772 升级vue3 2024-11-04 18:56:49 +08:00
QAIU 4666e942b4 升级vue3 2024-11-04 18:56:49 +08:00
QAIU 8269673619 1. add iCloud解析 2024-11-04 14:18:56 +08:00
QAIU daa3c940ee 1. add iCloud解析 2024-11-04 14:18:56 +08:00
qaiu 82ec586554 手残 又不小心提交了 ads代码 2024-11-02 18:59:33 +08:00
qaiu e54c15dad1 手残 又不小心提交了 ads代码 2024-11-02 18:59:33 +08:00
qaiu ca98cc8708 里程碑版本前奏: 1. 添加google云盘解析(需要联网), 2. web页面人工智障自动解析URL, 3. 优化一堆细节问题, 4: git换行配置(待验证), 5. 酷我解析可用 2024-11-02 18:58:15 +08:00
qaiu 054024e3e8 里程碑版本前奏: 1. 添加google云盘解析(需要联网), 2. web页面人工智障自动解析URL, 3. 优化一堆细节问题, 4: git换行配置(待验证), 5. 酷我解析可用 2024-11-02 18:58:15 +08:00
QAIU f07800985d 1. 优化123pan日志, 2. 微博短链测试, 3. 分享类添加其他参数Map(Cookie支持准备) 2024-11-01 18:18:29 +08:00
QAIU 5be8c4548f 1. 优化123pan日志, 2. 微博短链测试, 3. 分享类添加其他参数Map(Cookie支持准备) 2024-11-01 18:18:29 +08:00
qaiu b042df93b7 更新 urltool.py 2024-10-29 18:59:23 +08:00
qaiu 60bd8ecf21 更新 urltool.py 2024-10-29 18:59:23 +08:00
QAIU ecf4441946 .. 2024-10-29 18:36:51 +08:00
QAIU 25edeaf709 .. 2024-10-29 18:36:51 +08:00
QAIU 39b2612840 .. 2024-10-28 18:59:18 +08:00
QAIU 1e7525f908 .. 2024-10-28 18:59:18 +08:00
QAIU 218f486e6b .. 2024-10-28 18:58:37 +08:00
QAIU 341e33a845 .. 2024-10-28 18:58:37 +08:00
QAIU cfcc25f175 add onedrive 2024-10-28 18:57:26 +08:00
QAIU f5ef8c07a5 add onedrive 2024-10-28 18:57:26 +08:00
qaiu 155e88223c 0.0 前端优化,302标识短链添加/d前缀 2024-10-28 14:36:39 +08:00
qaiu 76da12da65 0.0 前端优化,302标识短链添加/d前缀 2024-10-28 14:36:39 +08:00
QAIU 05039ece51 add 118, 微雨云 2024-10-26 16:04:49 +08:00
QAIU dacf93bd06 add 118, 微雨云 2024-10-26 16:04:49 +08:00
QAIU 1c673f2b46 idea run Main. 2024-10-25 18:18:42 +08:00
QAIU 498bce5255 idea run Main. 2024-10-25 18:18:42 +08:00
QAIU 2232a70228 Merge remote-tracking branch 'origin/main' 2024-10-25 18:18:34 +08:00
QAIU d67df58bc6 Merge remote-tracking branch 'origin/main' 2024-10-25 18:18:34 +08:00
QAIU e661b1d817 idea run Main. 2024-10-25 18:18:17 +08:00
QAIU 751c7163fe idea run Main. 2024-10-25 18:18:17 +08:00
qaiu 5a6a65f580 Update README.md 2024-10-25 14:54:19 +08:00
qaiu 9bd5da8ac3 Update README.md 2024-10-25 14:54:19 +08:00
qaiu 5cdd3bcd30 Update README.md 2024-10-25 14:52:36 +08:00
qaiu 769e8545b6 Update README.md 2024-10-25 14:52:36 +08:00
qaiu 1233a885b8 Update README.md 2024-10-25 14:49:09 +08:00
qaiu a30c037138 Update README.md 2024-10-25 14:49:09 +08:00
QAIU adf56cd768 add 酷狗音乐, 酷我音乐, 网易云音乐, QQ音乐 2024-10-25 14:38:57 +08:00
QAIU 3c7fc752fc add 酷狗音乐, 酷我音乐, 网易云音乐, QQ音乐 2024-10-25 14:38:57 +08:00
QAIU cd4b208be9 一处SQL语法错误 2024-10-24 10:48:36 +08:00
QAIU 54576e8cbc 一处SQL语法错误 2024-10-24 10:48:36 +08:00
QAIU 502de1a5d0 0..0 2024-10-23 18:08:10 +08:00
QAIU f2bac57ed3 0..0 2024-10-23 18:08:10 +08:00
qaiu 4158f869a3 0.0 2024-10-23 18:04:34 +08:00
qaiu a3220c36c1 0.0 2024-10-23 18:04:34 +08:00
QAIU ff569d339c 1. add music parser 2024-10-21 19:14:29 +08:00
QAIU 821fc945cf 1. add music parser 2024-10-21 19:14:29 +08:00
QAIU 10eec323dd 1. add 网易云音乐解析 2024-10-20 18:16:51 +08:00
QAIU 784b3334f4 1. add 网易云音乐解析 2024-10-20 18:16:51 +08:00
qaiu 0a3db51c7d 更新 app-dev.yml 蓝奏设置合理缓存时间 2024-10-11 08:15:10 +08:00
qaiu 57c3355d3e 更新 app-dev.yml 蓝奏设置合理缓存时间 2024-10-11 08:15:10 +08:00
qaiu 229aee0b30 Update README.md 2024-10-09 15:38:29 +08:00
qaiu 9275e28e15 Update README.md 2024-10-09 15:38:29 +08:00
QAIU 44714aa981 1. add 城通网盘解析(慢速) https://www.ctfile.com
2. 优化解析接口的实现
2024-10-09 15:33:33 +08:00
QAIU a82596dc70 1. add 城通网盘解析(慢速) https://www.ctfile.com
2. 优化解析接口的实现
2024-10-09 15:33:33 +08:00
qaiu 2b6138a889 前端打包说明 2024-10-08 03:01:29 +08:00
qaiu add27186bc 前端打包说明 2024-10-08 03:01:29 +08:00
qaiu 5e424f7bf4 前端打包说明 2024-10-08 02:13:50 +08:00
qaiu 087ad0c120 前端打包说明 2024-10-08 02:13:50 +08:00
qaiu 294e47deed 1. 启用内嵌静态页面, 2. 蓝奏域名规则优化, 3. 反向代理优化, 4. 修复一堆细节问题 2024-10-08 02:06:37 +08:00
qaiu 5cd1db7e4b 1. 启用内嵌静态页面, 2. 蓝奏域名规则优化, 3. 反向代理优化, 4. 修复一堆细节问题 2024-10-08 02:06:37 +08:00
qaiu dc42547b73 更新 README.md 2024-10-07 19:32:22 +08:00
qaiu 3cdbac1603 更新 README.md 2024-10-07 19:32:22 +08:00
qaiu 7ef7f0706b 更新 PanDomainTemplate.java
蓝奏匹配正则优化
2024-10-06 15:19:51 +08:00
qaiu 7402dd76cc 更新 PanDomainTemplate.java
蓝奏匹配正则优化
2024-10-06 15:19:51 +08:00
qaiu a59b98a7c9 更新 PanDomainTemplate.java 2024-10-06 15:04:13 +08:00
qaiu de2e47628a 更新 PanDomainTemplate.java 2024-10-06 15:04:13 +08:00
qaiu 088fee9a4d 1. add:123云盘的新域名
2. update: 统计API支持ce盘
3. 缓存时长
2024-10-01 17:38:57 +08:00
qaiu aad0098169 1. add:123云盘的新域名
2. update: 统计API支持ce盘
3. 缓存时长
2024-10-01 17:38:57 +08:00
QAIU d8666acfe8 国庆快乐 ^ ^ #59 2024-09-30 17:42:38 +08:00
QAIU 922ce84000 国庆快乐 ^ ^ #59 2024-09-30 17:42:38 +08:00
QAIU 209e9c2866 国庆快乐 ^ ^ #59 2024-09-30 17:38:36 +08:00
QAIU aabfcd8c8b 国庆快乐 ^ ^ #59 2024-09-30 17:38:36 +08:00
qaiu 6c3195dea4 更新 README.md 2024-09-29 22:11:04 +08:00
qaiu 0e15d9f309 更新 README.md 2024-09-29 22:11:04 +08:00
qaiu 7d774a7433 更新 README.md 2024-09-29 22:10:23 +08:00
qaiu 5ac89ac085 更新 README.md 2024-09-29 22:10:23 +08:00
qaiu f1ec4433cf 更新 README.md 2024-09-29 22:09:58 +08:00
qaiu b3ec433d33 更新 README.md 2024-09-29 22:09:58 +08:00
QAIU 1f825db261 update 支持Cloudreve任意https的80端口的域名, 修复因json异常解析导致的解析时间超时的问题 2024-09-25 20:01:10 +08:00
QAIU 207b4cf6b3 update 支持Cloudreve任意https的80端口的域名, 修复因json异常解析导致的解析时间超时的问题 2024-09-25 20:01:10 +08:00
QAIU 1019f24f1d update web-front README.md 2024-09-24 18:05:30 +08:00
QAIU 03fbb3ef15 update web-front README.md 2024-09-24 18:05:30 +08:00
QAIU f5c5b99579 1. 修改文叔叔链接匹配规则 2024-09-24 17:55:18 +08:00
QAIU 4ce62d6b98 1. 修改文叔叔链接匹配规则 2024-09-24 17:55:18 +08:00
QAIU e002d19f1b 1. 前端页面优化, 增强统计功能, 支持生成二维码
2. 添加统计接口
2024-09-24 17:08:29 +08:00
QAIU 1f504a8cd5 1. 前端页面优化, 增强统计功能, 支持生成二维码
2. 添加统计接口
2024-09-24 17:08:29 +08:00
qaiu 0d5c9651f0 Update README.md 2024-09-24 10:07:25 +08:00
qaiu dd52f5a61f Update README.md 2024-09-24 10:07:25 +08:00
qaiu 53fc13b95c Merge pull request #56 from qaiu/dependabot/npm_and_yarn/web-front/micromatch-4.0.8
Bump micromatch from 4.0.5 to 4.0.8 in /web-front
2024-09-24 00:09:00 +08:00
qaiu 8369212bd3 Merge pull request #56 from qaiu/dependabot/npm_and_yarn/web-front/micromatch-4.0.8
Bump micromatch from 4.0.5 to 4.0.8 in /web-front
2024-09-24 00:09:00 +08:00
QAIU 694c3b0ddc 修复移动云空间无法解析的前端问题, 更新前端依赖 2024-09-23 18:33:09 +08:00
QAIU c67911f1bb 修复移动云空间无法解析的前端问题, 更新前端依赖 2024-09-23 18:33:09 +08:00
dependabot[bot] 9b3d4577cc Bump micromatch from 4.0.5 to 4.0.8 in /web-front
Bumps [micromatch](https://github.com/micromatch/micromatch) from 4.0.5 to 4.0.8.
- [Release notes](https://github.com/micromatch/micromatch/releases)
- [Changelog](https://github.com/micromatch/micromatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/micromatch/compare/4.0.5...4.0.8)

---
updated-dependencies:
- dependency-name: micromatch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-09-23 08:46:39 +00:00
dependabot[bot] af95de8d15 Bump micromatch from 4.0.5 to 4.0.8 in /web-front
Bumps [micromatch](https://github.com/micromatch/micromatch) from 4.0.5 to 4.0.8.
- [Release notes](https://github.com/micromatch/micromatch/releases)
- [Changelog](https://github.com/micromatch/micromatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/micromatch/compare/4.0.5...4.0.8)

---
updated-dependencies:
- dependency-name: micromatch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-09-23 08:46:39 +00:00
QAIU 77783915dd 修复移动云空间无法解析的前端问题, 更新前端依赖 2024-09-23 16:45:30 +08:00
QAIU ba2bfbd11a 修复移动云空间无法解析的前端问题, 更新前端依赖 2024-09-23 16:45:30 +08:00
qaiu b67ac21a79 Update README.md add 宝塔安装教程 2024-09-22 17:27:54 +08:00
qaiu cc4b0ae90e Update README.md add 宝塔安装教程 2024-09-22 17:27:54 +08:00
qaiu 603afed2f2 . 2024-09-19 05:34:34 +00:00
qaiu 399f55cae6 . 2024-09-19 05:34:34 +00:00
qaiu c2a7c34496 . 2024-09-19 05:31:24 +00:00
qaiu 981513a557 . 2024-09-19 05:31:24 +00:00
qaiu edd40f48ba 依赖更新 2024-09-19 05:26:31 +00:00
qaiu 326cfa838c 依赖更新 2024-09-19 05:26:31 +00:00
qaiu cca3d6b8b9 web-front add yarn.lock 2024-09-19 05:22:55 +00:00
qaiu b576e06099 web-front add yarn.lock 2024-09-19 05:22:55 +00:00
qaiu f004512903 Update devcontainer.json 2024-09-19 09:37:01 +08:00
qaiu 1ad788c63f Update devcontainer.json 2024-09-19 09:37:01 +08:00
qaiu 6407bb6730 Merge pull request #47 from qaiu/dependabot/npm_and_yarn/web-front/webpack-5.94.0
Bump webpack from 5.88.2 to 5.94.0 in /web-front
2024-09-19 09:01:53 +08:00
qaiu faf4d8e7ef Merge pull request #47 from qaiu/dependabot/npm_and_yarn/web-front/webpack-5.94.0
Bump webpack from 5.88.2 to 5.94.0 in /web-front
2024-09-19 09:01:53 +08:00
qaiu b914eeadec Merge pull request #51 from qaiu/dependabot/npm_and_yarn/web-front/multi-d66d039ac5
Bump serve-static and express in /web-front
2024-09-19 09:01:04 +08:00
qaiu d77095fe87 Merge pull request #51 from qaiu/dependabot/npm_and_yarn/web-front/multi-d66d039ac5
Bump serve-static and express in /web-front
2024-09-19 09:01:04 +08:00
qaiu dcadc6783e Merge pull request #52 from qaiu/dependabot/npm_and_yarn/web-front/express-4.21.0
Bump express from 4.19.2 to 4.21.0 in /web-front
2024-09-19 09:00:27 +08:00
qaiu 1bd1f611fe Merge pull request #52 from qaiu/dependabot/npm_and_yarn/web-front/express-4.21.0
Bump express from 4.19.2 to 4.21.0 in /web-front
2024-09-19 09:00:27 +08:00
dependabot[bot] bc9f43634f Bump express from 4.19.2 to 4.21.0 in /web-front
Bumps [express](https://github.com/expressjs/express) from 4.19.2 to 4.21.0.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/4.21.0/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.19.2...4.21.0)

---
updated-dependencies:
- dependency-name: express
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-09-19 00:59:00 +00:00
dependabot[bot] 38f13524a1 Bump express from 4.19.2 to 4.21.0 in /web-front
Bumps [express](https://github.com/expressjs/express) from 4.19.2 to 4.21.0.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/4.21.0/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.19.2...4.21.0)

---
updated-dependencies:
- dependency-name: express
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-09-19 00:59:00 +00:00
dependabot[bot] 4778f0164c Bump serve-static and express in /web-front
Bumps [serve-static](https://github.com/expressjs/serve-static) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together.

Updates `serve-static` from 1.15.0 to 1.16.2
- [Release notes](https://github.com/expressjs/serve-static/releases)
- [Changelog](https://github.com/expressjs/serve-static/blob/v1.16.2/HISTORY.md)
- [Commits](https://github.com/expressjs/serve-static/compare/v1.15.0...v1.16.2)

Updates `express` from 4.19.2 to 4.21.0
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/4.21.0/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.19.2...4.21.0)

---
updated-dependencies:
- dependency-name: serve-static
  dependency-type: indirect
- dependency-name: express
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-09-19 00:58:59 +00:00
dependabot[bot] d5588e3850 Bump serve-static and express in /web-front
Bumps [serve-static](https://github.com/expressjs/serve-static) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together.

Updates `serve-static` from 1.15.0 to 1.16.2
- [Release notes](https://github.com/expressjs/serve-static/releases)
- [Changelog](https://github.com/expressjs/serve-static/blob/v1.16.2/HISTORY.md)
- [Commits](https://github.com/expressjs/serve-static/compare/v1.15.0...v1.16.2)

Updates `express` from 4.19.2 to 4.21.0
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/4.21.0/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.19.2...4.21.0)

---
updated-dependencies:
- dependency-name: serve-static
  dependency-type: indirect
- dependency-name: express
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-09-19 00:58:59 +00:00
qaiu 9904754a07 Merge pull request #48 from qaiu/dependabot/npm_and_yarn/web-front/axios-1.7.4
Bump axios from 1.6.0 to 1.7.4 in /web-front
2024-09-19 08:57:43 +08:00
qaiu b7c2887d0c Merge pull request #48 from qaiu/dependabot/npm_and_yarn/web-front/axios-1.7.4
Bump axios from 1.6.0 to 1.7.4 in /web-front
2024-09-19 08:57:43 +08:00
qaiu 1b79077c9e 更新 PanDomainTemplate.java 2024-09-19 06:20:12 +08:00
qaiu 1cba9df571 更新 PanDomainTemplate.java 2024-09-19 06:20:12 +08:00
qaiu c13afb05b3 示例下载链接修改 2024-09-19 05:43:54 +08:00
qaiu 32fc530a17 示例下载链接修改 2024-09-19 05:43:54 +08:00
qaiu 03e320efb8 Create devcontainer.json 2024-09-18 17:40:52 +08:00
qaiu c9436f0a47 Create devcontainer.json 2024-09-18 17:40:52 +08:00
qaiu 7846332476 Update README.md 2024-09-18 16:58:27 +08:00
qaiu b8174a16f4 Update README.md 2024-09-18 16:58:27 +08:00
qaiu 2d5d3b86e0 Update README.md 2024-09-18 16:58:02 +08:00
qaiu 2a44a55764 Update README.md 2024-09-18 16:58:02 +08:00
qaiu 7c9ba890af 1. .. 2024-09-18 15:45:49 +08:00
qaiu 0ad72c9108 1. .. 2024-09-18 15:45:49 +08:00
qaiu 0d609daffa 1. 123后缀处理 2. 修复缓存时间戳格式问题 2024-09-18 15:41:56 +08:00
qaiu b8340949d5 1. 123后缀处理 2. 修复缓存时间戳格式问题 2024-09-18 15:41:56 +08:00
qaiu c12e56d402 Update README.md 2024-09-18 13:34:53 +08:00
qaiu 6c3433595f Update README.md 2024-09-18 13:34:53 +08:00
qaiu c7b38c07d5 Update README.md 2024-09-18 13:34:26 +08:00
qaiu 3e5e42fef9 Update README.md 2024-09-18 13:34:26 +08:00
qaiu dc51066cea 1. 缓存优化 2024-09-18 13:28:20 +08:00
qaiu c19f584b0d 1. 缓存优化 2024-09-18 13:28:20 +08:00
qaiu 59d2fb3010 1. 缓存优化 2024-09-18 13:24:33 +08:00
qaiu 0bbf022c5d 1. 缓存优化 2024-09-18 13:24:33 +08:00
qaiu a0fe702c10 1. remove error update 2024-09-15 06:54:55 +08:00
qaiu 4516aa8300 1. remove error update 2024-09-15 06:54:55 +08:00
qaiu f886f7e366 1. 添加缓存
2. 优化解析架构
3. 优化核心模块
2024-09-15 06:53:11 +08:00
qaiu 30a53dd47c 1. 添加缓存
2. 优化解析架构
3. 优化核心模块
2024-09-15 06:53:11 +08:00
dependabot[bot] 1d475d88ed Bump axios from 1.6.0 to 1.7.4 in /web-front
Bumps [axios](https://github.com/axios/axios) from 1.6.0 to 1.7.4.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.6.0...v1.7.4)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-08-30 18:09:12 +00:00
dependabot[bot] 6e77c21021 Bump axios from 1.6.0 to 1.7.4 in /web-front
Bumps [axios](https://github.com/axios/axios) from 1.6.0 to 1.7.4.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.6.0...v1.7.4)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-08-30 18:09:12 +00:00
dependabot[bot] e64c901912 Bump webpack from 5.88.2 to 5.94.0 in /web-front
Bumps [webpack](https://github.com/webpack/webpack) from 5.88.2 to 5.94.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.88.2...v5.94.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-08-30 18:07:43 +00:00
dependabot[bot] f035cf4088 Bump webpack from 5.88.2 to 5.94.0 in /web-front
Bumps [webpack](https://github.com/webpack/webpack) from 5.88.2 to 5.94.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.88.2...v5.94.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-08-30 18:07:43 +00:00
qaiu 5fce02e623 Update README.md 2024-07-13 12:50:02 +08:00
qaiu af5cba5ed6 Update README.md 2024-07-13 12:50:02 +08:00
qaiu 13997bc543 Update README.md 2024-06-19 10:04:04 +08:00
qaiu 8bb3d26b4c Update README.md 2024-06-19 10:04:04 +08:00
qaiu 3e05b0d6f9 Update README.md 2024-06-19 10:03:53 +08:00
qaiu ef0829ab8f Update README.md 2024-06-19 10:03:53 +08:00
qaiu 966417f867 Merge pull request #45 from qaiu/dependabot/npm_and_yarn/web-front/multi-d7cccafd4e
Bump braces and filemanager-webpack-plugin in /web-front
2024-06-14 12:14:05 +08:00
qaiu 13f3546700 Merge pull request #45 from qaiu/dependabot/npm_and_yarn/web-front/multi-d7cccafd4e
Bump braces and filemanager-webpack-plugin in /web-front
2024-06-14 12:14:05 +08:00
dependabot[bot] 601a0d1b91 Bump braces and filemanager-webpack-plugin in /web-front
Bumps [braces](https://github.com/micromatch/braces) to 3.0.3 and updates ancestor dependency [filemanager-webpack-plugin](https://github.com/gregnb/filemanager-webpack-plugin). These dependencies need to be updated together.


Updates `braces` from 3.0.2 to 3.0.3
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

Updates `filemanager-webpack-plugin` from 2.0.5 to 8.0.0
- [Release notes](https://github.com/gregnb/filemanager-webpack-plugin/releases)
- [Changelog](https://github.com/gregnb/filemanager-webpack-plugin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gregnb/filemanager-webpack-plugin/compare/v2.0.5...v8.0.0)

---
updated-dependencies:
- dependency-name: braces
  dependency-type: indirect
- dependency-name: filemanager-webpack-plugin
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-06-11 06:54:54 +00:00
dependabot[bot] 0cccba7b3b Bump braces and filemanager-webpack-plugin in /web-front
Bumps [braces](https://github.com/micromatch/braces) to 3.0.3 and updates ancestor dependency [filemanager-webpack-plugin](https://github.com/gregnb/filemanager-webpack-plugin). These dependencies need to be updated together.


Updates `braces` from 3.0.2 to 3.0.3
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

Updates `filemanager-webpack-plugin` from 2.0.5 to 8.0.0
- [Release notes](https://github.com/gregnb/filemanager-webpack-plugin/releases)
- [Changelog](https://github.com/gregnb/filemanager-webpack-plugin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gregnb/filemanager-webpack-plugin/compare/v2.0.5...v8.0.0)

---
updated-dependencies:
- dependency-name: braces
  dependency-type: indirect
- dependency-name: filemanager-webpack-plugin
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-06-11 06:54:54 +00:00
QAIU ae91ce773e maven-dependency-submission-action add ignore-maven-wrapper: true 2024-06-07 11:17:37 +08:00
QAIU d428380f79 add maven wrapper build script 2024-06-07 09:33:57 +08:00
QAIU b0b8b61688 支持mysql 2024-06-06 18:10:15 +08:00
QAIU 7663320a55 1. h2数据库文件优化, 取消h2server启动
2. 项目结构优化, pom版本统一管理
3. core的beanutils依赖升级为commons-beanutils2版本, 修复之前版本的安全风险.
4. 此版本打包部署需要替换之前所有依赖
2024-06-06 18:06:33 +08:00
qaiu aaae7ab9a6 1. 小飞机规则修改, 稍后更新发行版. #43
2. 缓存策略将在近期添加. 这阵子忙的一地鸡毛. 不想活了
2024-05-30 21:52:13 +08:00
qaiu db7aa2f442 代码优化 2024-05-15 08:35:28 +08:00
qaiu d7349cbf05 小飞机 API调试 2024-05-13 14:10:12 +08:00
qaiu 3a5474c9d8 - 小飞机和蓝奏优享规则修改 #40
- 支持移动云云空间加密分享
2024-05-13 04:59:42 +08:00
qaiu 4e6ed0f936 更新 README.md 2024-04-17 00:38:30 +08:00
qaiu 11ae57856e Update README.md 2024-04-15 10:11:46 +08:00
qaiu 66e67f3e1d Merge pull request #37 from qaiu/dependabot/npm_and_yarn/web-front/express-4.19.2
Bump express from 4.18.2 to 4.19.2 in /web-front
2024-04-09 12:50:11 +08:00
qaiu 8913221b97 Update README.md 2024-04-09 12:49:33 +08:00
qaiu 4f4133b98c - README.md下载地址修改 2024-04-09 12:46:32 +08:00
qaiu 5768ba48e8 - 升级vertx到4.5.6
- 添加Cloudreve
- 蓝奏云优享和小飞机规则修改
2024-04-09 12:13:26 +08:00
dependabot[bot] 9780d09e28 Bump express from 4.18.2 to 4.19.2 in /web-front
Bumps [express](https://github.com/expressjs/express) from 4.18.2 to 4.19.2.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.18.2...4.19.2)

---
updated-dependencies:
- dependency-name: express
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-03-29 06:23:01 +00:00
qaiu 8358d8d1f8 Merge pull request #35 from qaiu/dependabot/npm_and_yarn/web-front/webpack-dev-middleware-5.3.4
Bump webpack-dev-middleware from 5.3.3 to 5.3.4 in /web-front
2024-03-24 15:23:37 +08:00
qaiu d2a7bf4417 Merge pull request #34 from qaiu/dependabot/npm_and_yarn/web-front/follow-redirects-1.15.6
Bump follow-redirects from 1.15.2 to 1.15.6 in /web-front
2024-03-24 15:23:15 +08:00
dependabot[bot] 24c5495e75 Bump webpack-dev-middleware from 5.3.3 to 5.3.4 in /web-front
Bumps [webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware) from 5.3.3 to 5.3.4.
- [Release notes](https://github.com/webpack/webpack-dev-middleware/releases)
- [Changelog](https://github.com/webpack/webpack-dev-middleware/blob/v5.3.4/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-dev-middleware/compare/v5.3.3...v5.3.4)

---
updated-dependencies:
- dependency-name: webpack-dev-middleware
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-03-23 19:01:51 +00:00
dependabot[bot] 4158200ba5 Bump follow-redirects from 1.15.2 to 1.15.6 in /web-front
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.2 to 1.15.6.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.2...v1.15.6)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-03-16 14:15:40 +00:00
qaiu 2a75f9d34d 更新 README.md 2024-01-29 00:35:23 +08:00
qaiu 441e69e5f8 更新 README.md 2024-01-29 00:34:43 +08:00
qaiu 0a3d91ee52 更新 README.md 2024-01-29 00:23:34 +08:00
qaiu 00b3af1c4c 更新 README.md 2024-01-29 00:22:39 +08:00
qaiu 6d4e0fb56e .. 2024-01-28 15:29:41 +08:00
qaiu 0a296cc937 添加蓝奏云优享解析支持 2024-01-28 15:26:22 +08:00
qaiu 257063bae3 蓝奏云域名修改, shell分隔符调整 2024-01-27 10:53:52 +08:00
qaiu e21325a5d0 Update README.md 2023-12-27 14:27:31 +08:00
qaiu 32284c6da0 Merge pull request #28 from qaiu/dev-reference
Dev reference 添加文叔叔解析
2023-12-16 14:35:44 +08:00
qaiu 56c68bcce6 加入Jansi 让windows cmd日志彩色输出 2023-12-15 10:14:00 +08:00
BLSKWOLF 2ef7efdc42 更新 README.md 2023-12-11 23:56:10 +08:00
BLSKWOLF 7f00413756 添加文叔叔解析
1.修复QQ邮箱解析
2.添加文叔叔解析
2023-12-11 23:51:49 +08:00
BLSKWOLF d26696d3fa 更新 README.md 2023-12-11 17:46:42 +08:00
BLSKWOLF 595f301748 [未完成]添加QQ邮箱文件解析
添加QQ邮箱文件解析,暂时未解决cookie的问题
2023-12-11 17:36:39 +08:00
qaiu c33b0aa12c Update README.md 2023-12-05 17:32:17 +08:00
qaiu b21189b7d7 Update README.md 2023-12-05 12:49:07 +08:00
qaiu 618f43da8e Update README.md 2023-12-05 11:43:04 +08:00
qaiu d28b54f694 Update README.md 2023-12-05 11:39:26 +08:00
qaiu 093d651f2f Merge pull request #27 from qaiu/dependabot/maven/ch.qos.logback-logback-classic-1.4.12
Bump ch.qos.logback:logback-classic from 1.4.7 to 1.4.12
2023-12-05 09:48:52 +08:00
dependabot[bot] ccc05c13b2 Bump ch.qos.logback:logback-classic from 1.4.7 to 1.4.12
Bumps [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback) from 1.4.7 to 1.4.12.
- [Commits](https://github.com/qos-ch/logback/compare/v_1.4.7...v_1.4.12)

---
updated-dependencies:
- dependency-name: ch.qos.logback:logback-classic
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-12-05 01:47:03 +00:00
qaiu 1dfcbcc132 Update README.md 2023-12-05 09:46:22 +08:00
qaiu e9770c8eb3 1. 日志配置微调 2. 乐云验证 2023-11-29 14:44:42 +08:00
qaiu cb14be12e1 vertx升级4.5.0 2023-11-28 17:00:11 +08:00
qaiu b0ca6aa4dd Merge remote-tracking branch 'origin/main' 2023-11-28 16:53:48 +08:00
qaiu c958229960 1. 添加联想乐云直链解析 2. 优化代码逻辑 2023-11-28 16:51:51 +08:00
qaiu 8aa10f6f27 Merge pull request #25 from qaiu/dependabot/npm_and_yarn/web-front/axios-1.6.0
Bump axios from 1.2.2 to 1.6.0 in /web-front
2023-11-10 10:03:31 +08:00
dependabot[bot] db073beeb5 Bump axios from 1.2.2 to 1.6.0 in /web-front
Bumps [axios](https://github.com/axios/axios) from 1.2.2 to 1.6.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/1.2.2...v1.6.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-11-10 02:02:37 +00:00
qaiu 3d46bcb5c8 Merge pull request #22 from qaiu/dependabot/npm_and_yarn/web-front/babel/traverse-7.23.2
Bump @babel/traverse from 7.20.12 to 7.23.2 in /web-front
2023-11-10 10:02:09 +08:00
qaiu 66e62aead0 小飞机网盘分享新URL格式适配 2023-11-02 10:43:10 +08:00
dependabot[bot] 497a96a1df Bump @babel/traverse from 7.20.12 to 7.23.2 in /web-front
Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.20.12 to 7.23.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.2/packages/babel-traverse)

---
updated-dependencies:
- dependency-name: "@babel/traverse"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-10-18 17:31:32 +00:00
qaiu c6e0bed331 更新 README.md 2023-09-23 11:21:47 +08:00
qaiu d678a5f4f0 Update README.md 2023-09-21 17:32:09 +08:00
qaiu 8fcf3d225d Update README.md 更新jdk下载网盘为移动云空间 2023-09-21 17:30:55 +08:00
qaiu 4858461946 Update README.md 2023-09-17 09:54:39 +08:00
qaiu 7afe52918b 蓝奏云js引入问题修复 2023-09-17 09:48:23 +08:00
QAIU 1a0064fc43 Merge remote-tracking branch 'origin/main' 2023-09-08 17:42:09 +08:00
QAIU 7216c84282 update test 2023-09-08 17:41:30 +08:00
qaiu 94a58e2174 Update README.md 2023-09-07 08:52:43 +08:00
qaiu aa2fae868c Update README.md 错别字 2023-09-06 03:08:17 +08:00
qaiu 1b80f49079 Update README.md 2023-09-06 03:06:55 +08:00
qaiu 135632309d Update README.md 2023-09-06 03:05:47 +08:00
QAIU 4c366b7d84 解析用到的js文件改为String方式引入 2023-09-01 18:07:21 +08:00
qaiu e3efdc83e6 Update README.md 2023-08-28 22:37:26 +08:00
QAIU 595575381b 去除web-service无用依赖 2023-08-28 17:58:00 +08:00
QAIU 5cd1ef8bbf 预览首页统计修复,123盘大文件长度取值错误问题 2023-08-28 17:54:39 +08:00
QAIU 1aeb838fd9 aaa 2023-08-25 18:30:27 +08:00
QAIU ce414e80b0 Merge remote-tracking branch 'origin/main' 2023-08-25 18:29:00 +08:00
QAIU c47c9bfc68 版本更新至0.1.7,启用h2db,添加统计功能,框架优化 2023-08-25 18:28:45 +08:00
qaiu 7b2c493cf7 错别字 2023-08-25 17:04:37 +08:00
QAIU b38291b6b2 Merge remote-tracking branch 'origin/main' 2023-08-25 16:56:00 +08:00
QAIU 66de667fc3 版本更新至0.1.7,启用h2db,添加统计功能,框架优化 2023-08-25 16:55:38 +08:00
qaiu a1e9be0133 Update README.md 2023-08-25 10:04:44 +08:00
qaiu bf70a7c83d Update README.md 2023-08-25 10:04:27 +08:00
QAIU 6706380558 蓝奏云规则微调, 框架优化(70%) 2023-08-23 14:55:08 +08:00
qaiu b0d150319d Update LzTool.java 2023-08-21 12:27:39 +08:00
qaiu 03185d0592 Update README.md 2023-08-20 10:36:39 +08:00
qaiu 46f092f2ed Merge pull request #13 from qaiu/dev
蓝奏云规则修改, 奶牛功能增强
2023-08-20 10:35:02 +08:00
qaiu aea97caed1 修复蓝奏云pan解析错误的问题#12 2023-08-20 10:29:00 +08:00
QAIU 6d3335d086 Merge remote-tracking branch 'origin/dev' into dev 2023-08-19 17:29:04 +08:00
QAIU 945e5a74e6 奶牛快传支持下载zip目录分享#11, core框架优化 2023-08-19 17:28:30 +08:00
qaiu 1f38201555 Update README.md 2023-08-13 00:58:12 +08:00
qaiu cfc5afc029 Update README.md 2023-08-13 00:55:20 +08:00
qaiu 0526569d64 Update README.md 2023-08-13 00:54:21 +08:00
QAIU 1c94f4ef8b 奶牛快传支持下载zip目录分享#11, core框架优化 2023-08-11 15:28:37 +08:00
QAIU 26aabf19db core框架优化 2023-08-10 14:54:45 +08:00
qaiu 2e14d8d345 修复123pan解析错误的问题#9 2023-08-10 01:49:41 +08:00
qaiu 09140d56a3 代码结构优化;修复123pan解析错误的问题#9 2023-08-10 01:45:39 +08:00
qaiu 1eec14831c 代码结构优化;修复123pan解析错误的问题#9 2023-08-10 01:42:34 +08:00
qaiu aafbf05d34 代码结构优化
修复123pan解析错误的问题#9
2023-08-10 01:38:20 +08:00
qaiu 8ffd35f2f0 Merge pull request #10 from qaiu/master
Master
2023-08-10 01:17:11 +08:00
qaiu 6808381292 fixed 123pan /b/api/share/download/info->/a/api/share/download/info 2023-08-10 00:59:09 +08:00
QAIU 72cc68e9ad 代码结构优化, 异常处理优化 2023-08-08 17:36:36 +08:00
QAIU 7917870c6b 代码结构优化, 异常处理优化 2023-08-08 11:34:32 +08:00
QAIU facf9b645e 0 2023-08-04 17:49:30 +08:00
qaiu 46b4c524f0 Update README.md 2023-08-02 17:53:04 +08:00
QAIU 804c6d96ec 0 2023-08-01 14:42:32 +08:00
qaiu 91c3b0c612 前端页面优化 2023-07-31 22:43:23 +08:00
qaiu 400952e33b 前端页面优化 2023-07-31 22:41:33 +08:00
QAIU c39f748a51 0 2023-07-31 14:07:12 +08:00
QAIU 2464693288 Merge remote-tracking branch 'origin/main' 2023-07-31 13:56:49 +08:00
QAIU cfce8c1aef 360亿方云API-URL变更 2023-07-31 13:56:35 +08:00
qaiu 258a7cb1cc Update README.md 2023-07-31 12:06:59 +08:00
qaiu 049cfa3676 Update README.md 2023-07-31 12:03:34 +08:00
qaiu 7591aa4336 Merge pull request #6 from qaiu/dependabot/npm_and_yarn/web-front/webpack-5.88.2
Bump webpack from 5.75.0 to 5.88.2 in /web-front
2023-07-31 11:42:09 +08:00
qaiu 2aef15c670 Merge pull request #7 from qaiu/dependabot/npm_and_yarn/web-front/word-wrap-1.2.5
Bump word-wrap from 1.2.3 to 1.2.5 in /web-front
2023-07-31 11:41:57 +08:00
dependabot[bot] 23f29be4b3 Bump webpack from 5.75.0 to 5.88.2 in /web-front
Bumps [webpack](https://github.com/webpack/webpack) from 5.75.0 to 5.88.2.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.75.0...v5.88.2)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-07-31 03:39:18 +00:00
QAIU daea6bea68 lz.qaiu.top加入前端页面 2023-07-31 11:38:23 +08:00
qaiu a71028c665 前端优化 2023-07-31 05:08:13 +08:00
dependabot[bot] afb997f516 Bump word-wrap from 1.2.3 to 1.2.5 in /web-front
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.5.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.5)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-07-30 19:22:56 +00:00
qaiu 940d73a132 Merge remote-tracking branch 'origin/main' 2023-07-31 03:22:02 +08:00
qaiu 214eaed56a 添加前端页面 2023-07-31 03:21:39 +08:00
qaiu 3dab818dcb Update README.md 2023-07-31 00:20:52 +08:00
qaiu 61db1af83d Update README.md 2023-07-30 16:29:27 +08:00
qaiu 7d1cb5b5c1 添加 通过JS文件获取123pan签名 2023-07-29 18:08:30 +08:00
QAIU 878f61d349 123网盘解析规则优化 2023-07-27 17:45:53 +08:00
QAIU 9a1c9d8ba2 123网盘解析规则优化 2023-07-24 10:47:01 +08:00
QAIU ffd4846924 Merge remote-tracking branch 'origin/main' 2023-07-24 10:41:43 +08:00
QAIU 3e1f29c12e 123网盘解析规则优化 2023-07-24 10:41:25 +08:00
qaiu ec9a6dfe6c Update README.md 2023-07-23 15:15:25 +08:00
qaiu a72ebbb83c Update README.md 2023-07-23 15:13:23 +08:00
qaiu a8a172c027 Update README.md 2023-07-23 15:12:58 +08:00
qaiu bcd71a844c Update README.md
lz.qaiu.top测试123pan 下载Dragonwell JDK17
2023-07-22 15:33:10 +08:00
qaiu 3608eb0370 Update README.md
lz.qaiu.top测试123pan 下载Dragonwell JDK17
2023-07-22 15:32:13 +08:00
QAIU dbef574cbc 修改123网盘解析规则 2023-07-22 12:34:02 +08:00
QAIU e2273587a0 细节优化 2023-07-21 10:29:21 +08:00
qaiu 9f50299943 Update README.md 2023-07-16 04:26:05 +08:00
qaiu a51097e1ba 修改win服务模板 2023-07-16 03:45:54 +08:00
qaiu 5628d57299 - 更新版本号: 0.1.5->0.1.6 2023-07-16 03:11:41 +08:00
qaiu 774a069c0e - WebServer: PanTool优化异常处理
- Core: Vertx事件循环线程数调整
2023-07-16 02:47:39 +08:00
qaiu 5756fde338 Merge pull request #5 from qaiu/dependabot/maven/com.h2database-h2-2.2.220
Bump h2 from 2.1.214 to 2.2.220
2023-07-10 06:05:17 +08:00
qaiu 5d6e22405a Merge pull request #4 from qaiu/dependabot/maven/core-database/com.h2database-h2-2.2.220
Bump h2 from 2.1.214 to 2.2.220 in /core-database
2023-07-10 06:04:58 +08:00
dependabot[bot] 28497e900a Bump h2 from 2.1.214 to 2.2.220
Bumps [h2](https://github.com/h2database/h2database) from 2.1.214 to 2.2.220.
- [Release notes](https://github.com/h2database/h2database/releases)
- [Commits](https://github.com/h2database/h2database/compare/version-2.1.214...version-2.2.220)

---
updated-dependencies:
- dependency-name: com.h2database:h2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-07-07 22:01:48 +00:00
dependabot[bot] 00723cc2e2 Bump h2 from 2.1.214 to 2.2.220 in /core-database
Bumps [h2](https://github.com/h2database/h2database) from 2.1.214 to 2.2.220.
- [Release notes](https://github.com/h2database/h2database/releases)
- [Commits](https://github.com/h2database/h2database/compare/version-2.1.214...version-2.2.220)

---
updated-dependencies:
- dependency-name: com.h2database:h2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-07-07 22:00:11 +00:00
QAIU 91eb62d308 解决一些 warning jdk14对可序列化对象添加@Serial 2023-06-21 16:49:01 +08:00
QAIU c73e614ce7 Merge remote-tracking branch 'origin/main' 2023-06-21 15:40:42 +08:00
QAIU 2586092760 musetransfer api test 2023-06-21 15:40:24 +08:00
qaiu 0d5b771db8 Zzz 2023-06-21 02:53:58 +00:00
qaiu 67edd5b5d8 Cow解析重复创建实例VertxHolder.getVertxInstance() 2023-06-21 02:53:24 +00:00
qaiu 40eea9b5f4 cow parse fail return 2023-06-21 02:50:19 +00:00
QAIU 29a993e1fc add mu pan 2023-06-14 17:47:20 +08:00
QAIU 2c9f0d8e83 Zzz 2023-06-14 16:14:37 +08:00
qaiu 656a43e4b7 Update README.md 2023-06-14 15:48:21 +08:00
qaiu f0e28e1c37 Update README.md 2023-06-14 15:48:08 +08:00
qaiu 7e5400d43c Update README.md 2023-06-14 15:40:08 +08:00
qaiu c7c932daf4 Create LICENSE 2023-06-14 15:23:59 +08:00
QAIU 8ca0eca2ea Zzz 2023-06-14 11:57:58 +08:00
QAIU bb925eba35 Zzz 2023-06-14 11:56:33 +08:00
QAIU a105a7d864 Zzz 2023-06-14 11:53:27 +08:00
QAIU 60e4ac6094 依赖打包优化 2023-06-14 11:26:33 +08:00
qaiu 8d80ff845a 修复Linux运行脚本 2023-06-14 10:30:16 +08:00
QAIU 49c2bbe680 Linux部署服务模板修改 2023-06-13 15:11:32 +08:00
qaiu 3017e8d17c Update README.md 2023-06-13 13:58:26 +08:00
QAIU f3ae2b79b8 update 0.1.5 2023-06-13 13:25:22 +08:00
QAIU c629525029 update 0.1.5 2023-06-13 13:23:09 +08:00
QAIU 5d9b18ef41 移动云空间需要注意的地方 2023-06-13 10:53:02 +08:00
qaiu bdee797f7e Merge pull request #3 from qaiu/dev
Controller 层不支持方法重载: ServerApi
2023-06-13 10:30:36 +08:00
qaiu a052bcd841 Controller 层不支持方法重载: ServerApi 2023-06-13 10:29:23 +08:00
qaiu 616cc9ce6a 接口重构 2023-06-13 08:22:11 +08:00
qaiu f124c83286 接口重构 2023-06-13 05:43:37 +08:00
QAIU d11fcfb282 测试相关 2023-06-12 16:41:06 +08:00
QAIU 5ec1ec7789 Zzzz 2023-06-12 16:07:28 +08:00
QAIU 8b6075af37 重构蓝奏云解析代码, 加入蓝奏云加密分享解析 2023-06-12 10:39:33 +08:00
QAIU 5d23c57d0e 蓝奏云密码解析测试 2023-06-10 17:45:25 +08:00
QAIU 409163ddf5 蓝奏云密码解析测试 2023-06-10 17:32:25 +08:00
QAIU 994202587d change README.md 2023-06-10 16:41:25 +08:00
QAIU c01d41f9ca change README.md 2023-06-10 16:35:33 +08:00
QAIU c42667fe3b 添加123云盘直链解析 2023-06-10 16:31:17 +08:00
QAIU c782d495ea 修改密码分隔符$->@ 2023-06-10 13:34:01 +08:00
QAIU 3f4f9fa76b - 加入360亿方云直链解析
- 优化代码
2023-06-10 13:29:22 +08:00
QAIU 635c639bf5 - 加入小飞机盘直链解析
- 优化代码
2023-06-09 15:43:21 +08:00
QAIU a49b9254a4 Merge remote-tracking branch 'origin/main' 2023-06-08 17:34:02 +08:00
QAIU 0c91eea711 其他网盘API 2023-06-08 17:33:42 +08:00
376 changed files with 57017 additions and 1903 deletions
+28
View File
@@ -0,0 +1,28 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/java
{
"name": "Java",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/java:0-17",
"features": {
"ghcr.io/devcontainers/features/java:1": {
"version": "none",
"installMaven": "true",
"installGradle": "false"
},
"ghcr.io/devcontainers-contrib/features/ant-sdkman:2": {}
}
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "java -version",
// Configure tool-specific properties.
// "customizations": {},
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}
+21
View File
@@ -0,0 +1,21 @@
# GitHub 语言检测配置
# 设置主要语言为 Java
*.java linguist-language=Java
*.vue linguist-language=Vue
*.js linguist-language=JavaScript
# 排除不需要统计的文件
target/ linguist-vendored=true
node_modules/ linguist-vendored=true
webroot/ linguist-vendored=true
logs/ linguist-vendored=true
db/ linguist-vendored=true
# 文本文件使用 LF 换行符,适用于 Linux 和 macOS
*.sh text eol=lf
*.service text eol=lf
# Windows 执行的文件使用 CRLF 换行符
*.bat text eol=crlf
*.cmd text eol=crlf
bin/nfd-service-template.xml text eol=crlf
+15
View File
@@ -0,0 +1,15 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
polar: # Replace with a single Polar username
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
thanks_dev: # Replace with a single thanks.dev username
custom: https://blog.qaiu.top/archives/da-shang-zhuan-yong # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
+17
View File
@@ -0,0 +1,17 @@
version: 2
updates:
- package-ecosystem: "maven"
directory: "/"
open-pull-requests-limit: 10
ignore:
# 忽略通过 BOM 管理的 Vert.x 依赖
# 这些依赖的版本通过 vertx-dependencies BOM 统一管理
# 应该通过更新 pom.xml 中的 vertx.version 属性来更新这些依赖
- dependency-name: "io.vertx:vertx-web"
- dependency-name: "io.vertx:vertx-codegen"
- dependency-name: "io.vertx:vertx-config"
- dependency-name: "io.vertx:vertx-config-yaml"
- dependency-name: "io.vertx:vertx-service-proxy"
- dependency-name: "io.vertx:vertx-web-proxy"
- dependency-name: "io.vertx:vertx-web-client"
+45
View File
@@ -0,0 +1,45 @@
name: 编译项目
on:
push:
branches: [ main, master ]
paths-ignore:
- 'bin/**'
- '.github/**'
- '.mvn/**'
- '.run/**'
- '.vscode/**'
- '*.txt'
- '*.md'
pull_request:
branches: [ main, master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 设置 Java 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: 缓存 Maven 依赖
uses: actions/cache@v3
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: 编译项目
run: ./mvnw clean compile
# - name: 运行测试
# run: ./mvnw test
- name: 打包项目
run: ./mvnw package -DskipTests
+61 -3
View File
@@ -11,12 +11,25 @@ name: Java CI with Maven
# The API requires write permission on the repository to submit dependencies
permissions:
contents: write
packages: write
on:
push:
branches: [ "main" ]
tags:
- '*' # 只有推送tag时才会触发构建
branches-ignore:
- '*' # 排除所有分支的提交
paths-ignore:
- 'bin/**'
- '.github/**'
- '.mvn/**'
- '.run/**'
- '.vscode/**'
- '*.txt'
- '*.md'
pull_request:
branches: [ "main" ]
branches:
- "main"
jobs:
build:
@@ -25,19 +38,64 @@ jobs:
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v4
with:
node-version: '18'
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
cache: maven
- name: Build Frontend
run: cd web-front && yarn install && yarn run build
- name: Build with Maven
run: mvn -B package --file pom.xml
run: mvn -B package -DskipTests --file pom.xml
# Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive
- name: Update dependency graph
uses: advanced-security/maven-dependency-submission-action@v3
if: github.event_name != 'pull_request'
with:
ignore-maven-wrapper: true
# - uses: release-drafter/release-drafter@v5
# env:
# GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
path: web-service/target/netdisk-fast-download-bin.zip
- name: Login to GitHub Container Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Extract git tag
id: tag
run: |
GIT_TAG=$(git tag --points-at HEAD | head -n 1)
echo "tag=$GIT_TAG" >> $GITHUB_OUTPUT
- name: Build and push Docker image
if: github.event_name != 'pull_request'
uses: docker/build-push-action@v5
with:
context: .
push: true
platforms: linux/amd64,linux/arm64,linux/arm/v7
tags: |
ghcr.io/qaiu/netdisk-fast-download:${{ steps.tag.outputs.tag }}
ghcr.io/qaiu/netdisk-fast-download:latest
+51
View File
@@ -29,6 +29,8 @@ target/
/src/logs/
*.zip
sdkTest.log
app.yml
app-local.yml
#some local files
@@ -38,3 +40,52 @@ gradlew
gradlew.bat
unused.txt
/web-service/src/main/generated/
/db
/webroot/nfd-front/
package-lock.json
# Maven generated files
.flattened-pom.xml
**/.flattened-pom.xml
# Test files
test-filelist.java
# Temporary files
*.tmp
*.temp
*.log
*.bak
*.swp
*.swo
*~
# Node.js (if any)
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Build artifacts
*.jar
*.war
*.ear
*.zip
*.tar.gz
*.rar
# IDE specific
.vscode/
.cursor/
*.iml
*.ipr
*.iws
# Build directories
**/target/
**/build/
**/classes/
**/out/
**/${project.build.directory}/
**/${project.basedir}/target/
**/${basedir}/target/
+117
View File
@@ -0,0 +1,117 @@
/*
* Copyright 2007-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.6";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
* use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
".mvn/wrapper/maven-wrapper.properties";
/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH =
".mvn/wrapper/maven-wrapper.jar";
/**
* Name of the property which should be used to override the default download url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
public static void main(String args[]) {
System.out.println("- Downloader started");
File baseDirectory = new File(args[0]);
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
// If the maven-wrapper.properties exists, read it and check if it contains a custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if(mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
} catch (IOException e) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if(mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
// Ignore ...
}
}
}
System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if(!outputFile.getParentFile().exists()) {
if(!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
try {
downloadFileFromURL(url, outputFile);
System.out.println("Done");
System.exit(0);
} catch (Throwable e) {
System.out.println("- Error downloading");
e.printStackTrace();
System.exit(1);
}
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
String username = System.getenv("MVNW_USERNAME");
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}
}
BIN
View File
Binary file not shown.
+2
View File
@@ -0,0 +1,2 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
+15
View File
@@ -0,0 +1,15 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="AppMain" type="Application" factoryName="Application" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="cn.qaiu.lz.AppMain" />
<module name="web-service" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="cn.qaiu.lz.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
+18
View File
@@ -0,0 +1,18 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "Current File",
"request": "launch",
"mainClass": "${file}"
},
{
"type": "java",
"name": "AppMain",
"request": "launch",
"mainClass": "cn.qaiu.lz.AppMain",
"projectName": "web-service"
}
]
}
+4
View File
@@ -0,0 +1,4 @@
{
"java.compile.nullAnalysis.mode": "automatic",
"java.configuration.updateBuildConfiguration": "interactive"
}
+17
View File
@@ -0,0 +1,17 @@
FROM eclipse-temurin:17-jre
WORKDIR /app
# 安装 unzip
RUN apt-get update && apt-get install -y unzip && rm -rf /var/lib/apt/lists/*
COPY ./web-service/target/netdisk-fast-download-bin.zip .
RUN unzip netdisk-fast-download-bin.zip && \
mv netdisk-fast-download/* ./ && \
rm netdisk-fast-download-bin.zip && \
chmod +x run.sh
EXPOSE 6400 6401
ENTRYPOINT ["sh", "run.sh"]
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 qaiu
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+516 -55
View File
@@ -1,73 +1,534 @@
# netdisk-fast-download
# 网盘快速下载器--直链解析
[![Java CI with Maven](https://github.com/qaiu/netdisk-fast-download/actions/workflows/maven.yml/badge.svg)](https://github.com/qaiu/netdisk-fast-download/actions/workflows/maven.yml)
## 网盘支持情况:
` 网盘名称(网盘标识): `
- 蓝奏云 (lz)
- [ ] 登录, 上传, 下载, 分享
- [x] 直链解析
- 奶牛快传 (cow)
- [ ] 登录, 上传, 下载, 分享
- [x] 直链解析
- 移动云空间 (ec)
- [ ] 登录, 上传, 下载, 分享
- [x] 直链解析
- UC网盘 (uc)
- [ ] 登录, 上传, 下载, 分享
- [x] 直链解析
- 夸克网盘 (qk)
- TODO
<p align="center">
<img src="https://github.com/user-attachments/assets/87401aae-b0b6-4ffb-bbeb-44756404d26f" alt="项目预览图" />
</p>
技术栈:
Jdk17+Vert.x4.4.1+Jsoup
Core模块集成Vert.x实现类spring的注解式路由API
<p align="center">
<a href="https://github.com/qaiu/netdisk-fast-download/actions/workflows/maven.yml"><img src="https://img.shields.io/github/actions/workflow/status/qaiu/netdisk-fast-download/maven.yml?branch=v0.1.9b8a&style=flat"></a>
<a href="https://www.oracle.com/cn/java/technologies/downloads"><img src="https://img.shields.io/badge/jdk-%3E%3D17-blue"></a>
<a href="https://vertx-china.github.io"><img src="https://img.shields.io/badge/vert.x-4.5.22-blue?style=flat"></a>
<a href="https://raw.githubusercontent.com/qaiu/netdisk-fast-download/master/LICENSE"><img src="https://img.shields.io/github/license/qaiu/netdisk-fast-download?style=flat"></a>
<a href="https://github.com/qaiu/netdisk-fast-download/releases/"><img src="https://img.shields.io/github/v/release/qaiu/netdisk-fast-download?style=flat"></a>
</p>
API接口
# netdisk-fast-download 网盘分享链接云解析服务
QQ交流群:1017480890
netdisk-fast-download网盘直链云解析(nfd云解析)能把网盘分享下载链接转化为直链,支持多款云盘,已支持蓝奏云/蓝奏云优享/奶牛快传/移动云云空间/小飞机盘/亿方云/123云盘/Cloudreve等,支持加密分享,以及部分网盘文件夹分享。
## 快速开始
命令行下载分享文件:
```shell
(括号内表示可选内容)
1. 解析并自动302跳转 :
http(s)://you_host/parser?url=分享链接
http(s)://you_host/网盘标识/分享id(#分享密码)
2. 获取解析后的直链--JSON格式
http(s)://you_host/json/网盘标识/分享id(#分享密码)
curl -LOJ "https://lz.qaiu.top/parser?url=https://share.feijipan.com/s/nQOaNRPW&pwd=1234"
```
或者使用wget:
```shell
wget -O bilibili.mp4 "https://lz.qaiu.top/parser?url=https://share.feijipan.com/s/nQOaNRPW&pwd=1234"
```
或者使用浏览器[直接访问](https://nfd-parser.github.io/nfd-preview/preview.html?src=https%3A%2F%2Flz.qaiu.top%2Fparser%3Furl%3Dhttps%3A%2F%2Fshare.feijipan.com%2Fs%2FnQOaNRPW&name=bilibili.mp4&ext=mp4):
```
### 调用演示站下载:
https://lz.qaiu.top/parser?url=https://share.feijipan.com/s/nQOaNRPW&pwd=1234
### 调用演示站预览:
https://nfd-parser.github.io/nfd-preview/preview.html?src=https%3A%2F%2Flz.qaiu.top%2Fparser%3Furl%3Dhttps%3A%2F%2Fshare.feijipan.com%2Fs%2FnQOaNRPW&name=bilibili.mp4&ext=mp4
```
**解析器模块文档:** [parser/README.md](parser/README.md)
示例:
**JavaScript解析器文档:** [JavaScript解析器开发指南](parser/doc/JAVASCRIPT_PARSER_GUIDE.md) | [自定义解析器扩展指南](parser/doc/CUSTOM_PARSER_GUIDE.md) | [快速开始](parser/doc/CUSTOM_PARSER_QUICKSTART.md)
**Playground功能:** [JS解析器演练场密码保护说明](web-service/doc/PLAYGROUND_PASSWORD_PROTECTION.md)
## 预览地址
[预览地址1](https://lz.qaiu.top)
[预览地址2](https://lz0.qaiu.top)
[天翼云盘/移动云盘限时体验版](https://189.qaiu.top)
main分支依赖JDK17, 提供了JDK11分支[main-jdk11](https://github.com/qaiu/netdisk-fast-download/tree/main-jdk11)
**0.1.8及以上版本json接口格式有调整 参考json返回数据格式示例**
**小飞机解析有IP限制,多数云服务商的大陆IP会被拦截(可以自行配置代理),和本程序无关**
**注意: 请不要过度依赖lz.qaiu.top预览地址服务,建议本地搭建或者云服务器自行搭建。解析次数过多IP会被部分网盘厂商限制,不推荐做公共解析。**
## 网盘支持情况:
> 20230905 奶牛云直链做了防盗链,需加入请求头:Referer: https://cowtransfer.com/
> 20230824 123云盘解析大文件(>100MB)失效,需要登录
> 20230722 UC网盘解析失效,需要登录
网盘名称-网盘标识:
- [蓝奏云-lz](https://pc.woozooo.com/)
- [蓝奏云优享-iz](https://www.ilanzou.com/)
- [奶牛快传-cow](https://cowtransfer.com/)
- [移动云云空间-ec](https://www.ecpan.cn/web)
- [小飞机网盘-fj](https://www.feijipan.com/)
- [亿方云-fc](https://www.fangcloud.com/)
- [123云盘-ye](https://www.123pan.com/)
- ~[115网盘(失效)-p115](https://115.com/)~
- ~[118网盘(已停服)-p118](https://www.118pan.com/)~
- [文叔叔-ws](https://www.wenshushu.cn/)
- [联想乐云-le](https://lecloud.lenovo.com/)
- [QQ邮箱云盘-qqw](https://mail.qq.com/)
- [QQ闪传-qqsc](https://nutty.qq.com/nutty/ssr/26797.html)
- [城通网盘-ct](https://www.ctfile.com)
- [网易云音乐分享链接-mnes](https://music.163.com)
- [酷狗音乐分享链接-mkgs](https://www.kugou.com)
- [酷我音乐分享链接-mkws](https://kuwo.cn)
- [QQ音乐分享链接-mqqs](https://y.qq.com)
- [Cloudreve自建网盘-ce](https://github.com/cloudreve/Cloudreve)
- ~[微雨云存储-pvvy](https://www.vyuyun.com/)~
- [超星云盘(需要referer: https://pan-yz.chaoxing.com)-pcx](https://pan-yz.chaoxing.com)
- [WPS云文档-pwps](https://www.kdocs.cn/)
- [汽水音乐-qishui_music](https://music.douyin.com/qishui/)
- [咪咕音乐-migu](https://music.migu.cn/)
- [一刻相册-baidu_photo](https://photo.baidu.com/)
- Google云盘-pgd
- Onedrive-pod
- Dropbox-pdp
- iCloud-pic
### 专属版提供
- [夸克云盘-qk](https://pan.quark.cn/)
- [UC云盘-uc](https://fast.uc.cn/)
- [移动云盘-p139](https://yun.139.com/)
- [联通云盘-pwo](https://pan.wo.cn/)
- [天翼云盘-p189](https://cloud.189.cn/)
## API接口
[api接口文档](https://nfdparser.apifox.cn/)
### 服务端口
- **6400**: API 服务端口(建议使用 Nginx 代理)
- **6401**: 内置 Web 解析工具(个人使用可直接开放此端口)
### 接口说明
#### 1. 302 自动跳转下载
**通用接口**
```
GET /parser?url={分享链接}&pwd={密码}
```
// 解析并重定向到直链
###
# @no-redirect
GET http://127.0.0.1:6400/parser?url=https://lanzoux.com/ia2cntg
###
# @no-redirect
GET http://127.0.0.1:6400/parser?url=https://cowtransfer.com/s/9a644fe3e3a748
// Rest请求(只提供共享文件Id):
###
# @no-redirect
GET http://127.0.0.1:6400/cow/9a644fe3e3a748
**标志短链**
```
GET /d/{网盘标识}/{分享key}@{密码}
```
// 解析返回json直链
###
GET http://127.0.0.1:6400/json/cow/9a644fe3e3a748
###
GET http://127.0.0.1:6400/json/lz/ia2cntg
#### 2. 获取直链 JSON
**通用接口**
```
GET /json/parser?url={分享链接}&pwd={密码}
```
**标志短链**
```
GET /json/{网盘标识}/{分享key}@{密码}
```
#### 3. 文件夹解析(v0.1.8fixed3+)
```
GET /json/getFileList?url={分享链接}&pwd={密码}
```
### 使用规则
- `{分享链接}` 建议使用 URL 编码
- `{密码}` 无密码时省略 `&pwd=` 或 `@密码` 部分
- `{网盘标识}` 参考支持的网盘列表
- `your_host` 替换为您的域名或 IP
### 认证参数(v0.2.1+)
部分网盘(如夸克、UC)需要登录后的 Cookie 才能解析和下载。可通过 `auth` 参数传递认证信息:
**参数格式**:`auth` 参数值为 AES 加密后的 JSON 字符串,经过 Base64 编码和 URL 编码
**加密方式**:
- 算法:AES/ECB/PKCS5Padding
- 密钥:`nfd_auth_key2026`(16字节)
- 流程:JSON → AES加密 → Base64 → URL编码
**JSON 结构**:
```json
{
"authType": "cookie", // 认证类型: cookie/accesstoken/authorization/password/custom
"token": "your_cookie_here", // Cookie 或 Token 内容
"username": "", // 用户名(password 类型时使用)
"password": "", // 密码(password 类型时使用)
"ext1": "", // 扩展字段1(custom 类型时使用)
"ext2": "" // 扩展字段2(custom 类型时使用)
}
```
**网盘认证要求**:
| 网盘 | 认证要求 | 说明 |
|------|---------|------|
| 夸克网盘(QK) | **必须** | 必须配置 Cookie 才能解析 |
| UC网盘(UC) | **必须** | 必须配置 Cookie 才能解析 |
| 小飞机网盘(FJ) | 可选 | 大文件(>100MB)需要认证 |
| 蓝奏优享(IZ) | 可选 | 大文件需要认证 |
**使用示例**:
```
GET /parser?url={分享链接}&pwd={密码}&auth={加密后的认证参数}
```
> 💡 提示:Web 界面已内置认证配置功能,可自动处理加密过程,无需手动构造参数。
### 特殊说明
- 移动云云空间的 `分享key` 取分享链接中的 `data` 参数值
- 移动云云空间、小飞机网盘的加密分享可忽略密码参数
### 示例
```bash
# 302 跳转(通用接口 - 有密码)
http://your_host/parser?url=https%3A%2F%2Fwww.ilanzou.com%2Fs%2FlGFndCM&pwd=KMnv
# 302 跳转(标志短链 - 有密码)
http://your_host/d/iz/lGFndCM@KMnv
# 获取 JSON(通用接口 - 无密码)
http://your_host/json/parser?url=https%3A%2F%2Fwww.ilanzou.com%2Fs%2FLEBZySxF
# 获取 JSON(标志短链 - 无密码)
http://your_host/json/iz/LEBZySxF
```
TODO:
解析蓝奏云加密链接
---
### json接口详细说明
#### 1. 文件解析:/json/parser?url=分享链接&pwd=xxx
json返回数据格式示例:
`shareKey`: 全局分享key
`directLink`: 下载链接
`cacheHit`: 是否为缓存链接
`expires`: 缓存到期时间
```json
{
"code": 200,
"msg": "success",
"success": true,
"count": 0,
"data": {
"shareKey": "lz:xxx",
"directLink": "下载直链",
"cacheHit": true,
"expires": "2024-09-18 01:48:02",
"expiration": 1726638482825
},
"timestamp": 1726637151902
}
```
#### 2. 分享链接详情接口 /v2/linkInfo?url=分享链接
```json
{
"code": 200,
"msg": "success",
"success": true,
"count": 0,
"data": {
"downLink": "https://lz.qaiu.top/d/fj/xx",
"apiLink": "https://lz.qaiu.top/json/fj/xx",
"cacheHitTotal": 5,
"parserTotal": 2,
"sumTotal": 7,
"shareLinkInfo": {
"shareKey": "xx",
"panName": "小飞机网盘",
"type": "fj",
"sharePassword": "",
"shareUrl": "https://share.feijipan.com/s/xx",
"standardUrl": "https://www.feijix.com/s/xx",
"otherParam": {
"UA": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0"
},
"cacheKey": "fj:xx"
}
},
"timestamp": 1736489219402
}
```
#### 3. 文件夹解析(仅支持蓝奏云/蓝奏优享/小飞机网盘)
/v2/getFileList?url=分享链接&pwd=分享密码
```json
{
"code": 200,
"msg": "success",
"success": true,
"data": [
{
"fileName": "xxx",
"fileId": "xxx",
"fileIcon": null,
"size": 999,
"sizeStr": "999 M",
"fileType": "file/folder",
"filePath": null,
"createTime": "17 小时前",
"updateTime": null,
"createBy": null,
"description": null,
"downloadCount": "下载次数",
"panType": "lz",
"parserUrl": "下载链接/文件夹链接",
"extParameters": null
}
]
}
```
#### 4. 解析次数统计接口 /v2/statisticsInfo
```json
{
"code": 200,
"msg": "success",
"success": true,
"count": 0,
"data": {
"parserTotal": 320508,
"cacheTotal": 5957910,
"total": 6278418
},
"timestamp": 1736489378770
}
```
# 网盘对比
| 网盘名称 | 可直接下载分享 | 加密分享 | 初始网盘空间 | 单文件大小限制 | 登录接口 |
|-------|-------------|----------|----------|----------------|------|
| 蓝奏云 | √ | √ | 不限空间 | 100M | TODO |
| 奶牛快传 | √ | X | 10G | 不限大小 | TODO |
| 移动云空间 | √ | √(密码可忽略) | 5G(个人) | 不限大小 | TODO |
| UC网盘 | √ | √ | 10G | 不限大小 | TODO |
| 夸克网盘 | √(>10M需要登录) | √ | 10G(20G) | 不限大小(>10M需要登录) | X |
| 网盘名称 | 免登陆下载分享 | 加密分享 | 初始网盘空间 | 单文件大小限制 |
|-------------|---------|----------|-----------|-----------------|
| 蓝奏云 | √ | √ | 不限空间 | 100M |
| 奶牛快传 | √ | X | 10G | 不限大小 |
| 移动云云空间(个人版) | √ | √(密码可忽略) | 5G(个人) | 不限大小 |
| 小飞机网盘 | √ | √(密码可忽略) | 10G | 不限大小 |
| 360亿方云 | √ | √(密码可忽略) | 100G(须实名) | 不限大小 |
| 123云盘 | √ | √ | 2T | 100G(>100M需要登录) |
| 文叔叔 | √ | √ | 10G | 5GB |
| WPS云文档 | √ | X | 5G(免费) | 10M(免费)/2G(会员) |
| 夸克网盘 | x | √ | 10G | 不限大小 |
| UC网盘 | x | √ | 10G | 不限大小 |
# 打包部署
## JDK下载(lz.qaiu.top提供直链云解析服务)
- [阿里jdk17(Dragonwell17-windows-x86)](https://lz.qaiu.top/d/ec/e957acef36ce89e1053979672a90d219n)
- [阿里jdk17(Dragonwell17-linux-x86)](https://lz.qaiu.top/d/ec/6ebc9f2e0bbd53b4c4d5b11013f40a80NHvcYU)
- [阿里jdk17(Dragonwell17-linux-aarch64)](https://lz.qaiu.top/d/ec/d14c2d06296f61b52a876b525265e0f8tzxTc5)
- [解析有效性测试-移动云云空间-阿里jdk17-linux-x86](https://lz.qaiu.top/json/ec/6ebc9f2e0bbd53b4c4d5b11013f40a80NHvcYU)
## 开发和打包
```shell
# 环境要求: Jdk17 + maven;
mvn clean
mvn package -DskipTests
```
打包好的文件位于 web-service/target/netdisk-fast-download-bin.zip
## 🚀 快速部署
[![通过雨云一键部署](https://rainyun-apps.cn-nb1.rains3.com/materials/deploy-on-rainyun-cn.svg)](https://app.rainyun.com/apps/rca/store/7273/ssl_?s=ndf)
## Linux服务部署
### Docker 部署(Main分支)
#### 海外服务器Docker部署
```shell
# 创建目录
mkdir -p netdisk-fast-download
cd netdisk-fast-download
# 拉取镜像
docker pull ghcr.io/qaiu/netdisk-fast-download:latest
# 复制配置文件(或下载仓库web-service\src\main\resources)
docker create --name netdisk-fast-download ghcr.io/qaiu/netdisk-fast-download:latest
docker cp netdisk-fast-download:/app/resources ./resources
docker rm netdisk-fast-download
# 启动容器
docker run -d -it --name netdisk-fast-download -p 6401:6401 --restart unless-stopped -e TZ=Asia/Shanghai -v ./resources:/app/resources -v ./db:/app/db -v ./logs:/app/logs ghcr.io/qaiu/netdisk-fast-download:latest
# 反代6401端口
# 升级容器
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower --cleanup --run-once netdisk-fast-download
```
#### 国内Docker部署
```shell
# 创建目录
mkdir -p netdisk-fast-download
cd netdisk-fast-download
# 拉取镜像
docker pull ghcr.nju.edu.cn/qaiu/netdisk-fast-download:latest
# 复制配置文件(或下载仓库web-service\src\main\resources)
docker create --name netdisk-fast-download ghcr.nju.edu.cn/qaiu/netdisk-fast-download:latest
docker cp netdisk-fast-download:/app/resources ./resources
docker rm netdisk-fast-download
# 启动容器
docker run -d -it --name netdisk-fast-download -p 6401:6401 --restart unless-stopped -e TZ=Asia/Shanghai -v ./resources:/app/resources -v ./db:/app/db -v ./logs:/app/logs ghcr.nju.edu.cn/qaiu/netdisk-fast-download:latest
# 反代6401端口
# 升级容器
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower --cleanup --run-once netdisk-fast-download
```
### 宝塔部署指引 -> [点击进入宝塔部署教程](https://blog.qaiu.top/archives/netdisk-fast-download-bao-ta-an-zhuang-jiao-cheng)
### Linux命令行部署
> 注意: netdisk-fast-download.service中的ExecStart的路径改为实际路径
```shell
cd ~
wget -O netdisk-fast-download.zip https://github.com/qaiu/netdisk-fast-download/releases/download/v0.1.9b7/netdisk-fast-download-bin.zip
unzip netdisk-fast-download-bin.zip
cd netdisk-fast-download
bash service-install.sh
```
服务相关命令:
查看服务状态
`systemctl status netdisk-fast-download.service`
启动服务
`systemctl start netdisk-fast-download.service`
重启服务
`systemctl restart netdisk-fast-download.service`
停止服务
`systemctl stop netdisk-fast-download.service`
开机启动服务
`systemctl enable netdisk-fast-download.service`
停止开机启动
`systemctl disable netdisk-fast-download.service`
## Windows服务部署
1. 下载并解压releases版本netdisk-fast-download-bin.zip
2. 进入netdisk-fast-download下的bin目录
3. 使用管理员权限运行nfd-service-install.bat
如果不想使用服务运行可以直接运行run.bat
> 注意: 如果jdk环境变量的java版本不是17请修改nfd-service-template.xml中的java命令的路径改为实际路径
## 相关配置说明
resources目录下包含服务端配置文件 配置文件自带说明,具体请查看配置文件内容,
app-dev.yml 可以配置解析服务相关信息, 包括端口,域名,缓存时长等
server-proxy.yml 可以配置代理服务运行的相关信息, 包括前端反向代理端口,路径等
### ip代理配置说明
有时候解析量很大,IP容易被ban,这时候可以使用其他服务器搭建nfd-proxy代理服务。
修改配置文件:
app-dev.yml
```yaml
proxy:
- panTypes: pgd,pdb,pod # 网盘标识
type: http # 支持http/socks4/socks5
host: 127.0.0.1 # 代理IP
port: 7890 # 端口
username: # 用户名
password: # 密码
```
nfd-proxy搭建http代理服务器
参考https://github.com/nfd-parser/nfd-proxy
### 认证信息配置说明
部分网盘(如123)解析大文件时需要登录认证,可以在配置文件中添加认证信息。
修改配置文件:
app-dev.yml
```yaml
### 解析认证相关
auths:
# 123:配置用户名密码
ye:
username: 你的用户名
password: 你的密码
```
**注意:** 目前仅支持 123(ye)的认证配置。
## 开发计划
### v0.1.8~v0.1.9 ✓
- API添加文件信息(专属版/开源版)
- 目录解析(专属版/开源版)
- 文件预览功能(专属版/开源版)
- 文件夹预览功能(开源版)
- 友好的错误提示和一键反馈功能(开源版)
- 带cookie/token/username/pwd参数解析大文件(专属版)
### v0.2.x
- web后台管理--认证配置/分享链接管理(开源版/专属版)
- 123/小飞机/蓝奏优享等大文件解析(开源版)
- 直链分享(开源版/专属版)
- aria2/idm+/curl/wget链接生成(开源版/专属版)
- IP限流配置(开源版/专属版)
- refere防盗链,API鉴权防盗链(专属版)
- 123/小飞机/蓝奏优享/蓝奏文件夹解析API,天翼云盘/移动云盘文件夹解析API(专属版)
- 用户管理面板--营销推广系统(专属版)
**技术栈:**
Jdk17+Vert.x4
Core模块集成Vert.x实现类似spring的注解式路由API
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=qaiu/netdisk-fast-download&type=Date)](https://star-history.com/#qaiu/netdisk-fast-download&Date)
## **免责声明**
- 用户在使用本项目时,应自行承担风险,并确保其行为符合当地法律法规。开发者不对用户因使用本项目而导致的任何后果负责。
## 支持该项目
开源不易,用爱发电,本项目长期维护如果觉得有帮助, 可以请作者喝杯咖啡, 感谢支持
本项目的服务器由林枫云提供赞助<br>
</a>
<a href="https://www.dkdun.cn/aff/WDBRYKGH" target="_blank">
<img src="https://www.dkdun.cn/themes/web/www/upload/local68c2dbb2ab148.png" width="200">
</a>
</p>
### 关于赞助定制专属版
1. 专属版提供对小飞机,蓝奏优享大文件解析的支持, 提供天翼云盘/移动云盘/联通云盘的解析支持。
2. 可提供托管服务:包含部署服务和云服务器环境。
3. 可提供功能定制开发。
您可能需要提供一定的资金赞助支持定制专属版, 请添加以下任意一个联系方式详谈赞助模式:
<p>qq: 197575894</p>
<p>wechat: imcoding_</p>
<!--
![image](https://github.com/qaiu/netdisk-fast-download/assets/29825328/54276aee-cc3f-4ebd-8973-2e15f6295819)
[手机端支付宝打赏跳转链接](https://qr.alipay.com/fkx01882dnoxxtjenhlxt53)
-->
+2 -1
View File
@@ -7,7 +7,8 @@ Wants=network-online.target
[Service]
Type=simple
# User=USER
ExecStart=/usr/bin/java -server -Xmx128m -jar /root/java/netdisk-fast-download/netdisk-fast-download-0.0.1.jar
# 需要JDK17及以上版本 注意修改为自己的路径
ExecStart=/root/java/jdk-17.0.2/bin/java -server -Xmx128m -jar /root/java/netdisk-fast-download/netdisk-fast-download.jar
ExecStop=/bin/kill -s QUIT $MAINPID
Restart=always
StandOutput=syslog
+86
View File
@@ -0,0 +1,86 @@
#!/bin/bash
set -e
# ----------- 配置区域 ------------
# JRE 下载目录
JRE_DIR="/opt/custom-jre17"
# 使用阿里云镜像下载 JRE(OpenJDK 17)
JRE_TARBALL_URL="https://mirrors.tuna.tsinghua.edu.cn/Adoptium/17/jre/x64/linux/OpenJDK17U-jre_x64_linux_hotspot_17.0.15_6.tar.gz"
# ZIP 文件下载相关
ZIP_URL="http://www.722shop.top:6401/parser?url="
ZIP_DEST_DIR="/opt/target-zip"
ZIP_FILE_NAME="nfd.zip"
# --------------------------------
# 创建目录
mkdir -p "$JRE_DIR"
mkdir -p "$ZIP_DEST_DIR"
# -------- 检查 unzip 是否存在 --------
if ! command -v unzip >/dev/null 2>&1; then
echo "unzip 未安装,正在安装..."
if command -v apt-get >/dev/null 2>&1; then
apt-get update && apt-get install -y unzip
elif command -v yum >/dev/null 2>&1; then
yum install -y unzip
elif command -v dnf >/dev/null 2>&1; then
dnf install -y unzip
else
echo "不支持的包管理器,无法自动安装 unzip,请手动安装后重试。"
exit 1
fi
else
echo "unzip 已安装"
fi
# -------- 下载并解压 JRE --------
echo "下载 JRE 17 到 $JRE_DIR..."
curl -L "$JRE_TARBALL_URL" -o "$JRE_DIR/jre17.tar.gz"
echo "解压 JRE..."
tar -xzf "$JRE_DIR/jre17.tar.gz" -C "$JRE_DIR" --strip-components=1
rm "$JRE_DIR/jre17.tar.gz"
echo "JRE 解压完成"
# -------- 下载 ZIP 文件 --------
ZIP_PATH="$ZIP_DEST_DIR/$ZIP_FILE_NAME"
echo "下载 ZIP 文件到 $ZIP_PATH..."
curl -L "$ZIP_URL" -o "$ZIP_PATH"
# -------- 解压 ZIP 文件 --------
echo "解压 ZIP 文件到 $ZIP_DEST_DIR..."
unzip -o "$ZIP_PATH" -d "$ZIP_DEST_DIR"
echo "解压完成"
# -------- 启动 JAR 程序 --------
echo "进入 JAR 目录并后台运行程序..."
JAR_DIR="/opt/target-zip/netdisk-fast-download"
JAR_FILE="netdisk-fast-download.jar"
JAVA_BIN="$JRE_DIR/bin/java"
LOG_FILE="$JAR_DIR/app.log"
if [ ! -d "$JAR_DIR" ]; then
echo "[错误] 找不到 JAR 目录: $JAR_DIR"
exit 1
fi
cd "$JAR_DIR"
if [ ! -f "$JAR_FILE" ]; then
echo "[错误] 找不到 JAR 文件: $JAR_FILE"
exit 1
fi
if [ ! -x "$JAVA_BIN" ]; then
echo "[错误] 找不到可执行的 java: $JAVA_BIN"
exit 1
fi
# 后台运行,日志记录
nohup "$JAVA_BIN" -jar "$JAR_FILE" > "$LOG_FILE" 2>&1 &
echo "程序已在后台启动 ✅"
echo "日志路径: $LOG_FILE"
+27
View File
@@ -0,0 +1,27 @@
::
:: generate service xml file
::
@echo off
pushd %~dp0
set MY_DIR=%~dp0
set MY_DIR=%MY_DIR:~0,-1%
for /f "delims=X" %%i in ('dir /b %MY_DIR%\netdisk-fast-download.jar') do (
set LAUNCH_JAR=%MY_DIR%\%%i
)
(for /f "delims=" %%a in (nfd-service-template.xml) do (
set "str=%%a"
setlocal enabledelayedexpansion
set "str=!str:${dd}=%MY_DIR%!"
set "str=!str:${jar}=%LAUNCH_JAR%!"
echo,!str!
endlocal
))>"nfd-service.xml"
sc delete netdisk-fast-download
nfd-service install
sc start netdisk-fast-download
pause
+12
View File
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<service>
<id>netdisk-fast-download</id>
<name>netdisk-fast-download</name>
<description>netdisk fast download service</description>
<executable>java</executable>
<arguments> -server -Xmx128m -Dfile.encoding=utf8 -jar ${jar} </arguments>
<logpath>${dd}\logs</logpath>
<log mode="roll-by-time">
<pattern>yyyyMMdd</pattern>
</log>
</service>
Binary file not shown.
+7 -1
View File
@@ -1,5 +1,11 @@
@echo off && @chcp 65001 > nul
pushd %~dp0
set LIB_DIR=%~dp0
for /f "delims=X" %%i in ('dir /b %LIB_DIR%\netdisk-fast-download-*.jar') do set LAUNCH_JAR=%LIB_DIR%\%%i
for /f "delims=X" %%i in ('dir /b %LIB_DIR%\netdisk-fast-download.jar') do (
set LAUNCH_JAR=%LIB_DIR%%%i
)
set "JAVA_HOME=D:\App\dragonwell-17.0.3.0.3+7-GA"
"%JAVA_HOME%\bin\java.exe" -Xmx512M -Dfile.encoding=utf8 -jar %LAUNCH_JAR% %*
pause
+3 -2
View File
@@ -1,5 +1,6 @@
#!/bin/sh
#!/bin/bash
# set -x
LAUNCH_JAR="netdisk-fast-download-*.jar"
LAUNCH_JAR="netdisk-fast-download.jar"
nohup java -Xmx512M -jar "$LAUNCH_JAR" "$@" >startup.log 2>&1 &
tail -f startup.log
+14
View File
@@ -0,0 +1,14 @@
#!/bin/bash
# set -x
# 找到运行中的 Java 进程的 PID
PID=$(ps -ef | grep 'netdisk-fast-download.jar' | grep -v grep | awk '{print $2}')
if [ -z "$PID" ]; then
echo "未找到正在运行的进程 netdisk-fast-download.jar"
exit 1
else
# 杀掉进程
echo "停止 netdisk-fast-download.jar (PID: $PID)..."
kill -9 "$PID"
fi
+15 -7
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>netdisk-fast-download</artifactId>
<groupId>cn.qaiu</groupId>
<version>0.1.3</version>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -14,23 +14,19 @@
<properties>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<slf4j.version>2.0.5</slf4j.version>
<commons-lang3.version>3.12.0</commons-lang3.version>
<vertx.version>4.4.1</vertx.version>
</properties>
<dependencies>
<dependency>
<groupId>cn.qaiu</groupId>
<artifactId>core</artifactId>
<version>1.0.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.h2database/h2 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.1.214</version>
<version>2.2.220</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.zaxxer/HikariCP -->
@@ -42,7 +38,7 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
<version>3.18.0</version>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
@@ -60,6 +56,18 @@
<artifactId>vertx-jdbc-client</artifactId>
<version>${vertx.version}</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>9.2.0</version>
</dependency>
<!-- PG驱动-->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.3</version>
</dependency>
</dependencies>
</project>
@@ -1,7 +1,7 @@
package cn.qaiu;
public class StartH2DatabaseServer {
public static void main(String[] args) {
System.out.println("Hello world!");
}
}
@@ -21,7 +21,6 @@ public @interface Constraint {
boolean notNull() default false;
/**
* 唯一键约束 TODO 待实现
* @return 唯一键约束
*/
String uniqueKey() default "";
@@ -32,7 +31,7 @@ public @interface Constraint {
*/
String defaultValue() default "";
/**
* 默认值是否是函数
* 默认值是否是函数 like value=NOW()
* @return false 不是函数
*/
boolean defaultValueIsFunction() default false;
@@ -0,0 +1,67 @@
package cn.qaiu.db.ddl;
import cn.qaiu.db.pool.JDBCPoolInit;
import io.vertx.core.json.JsonObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CreateDatabase {
private static final Logger LOGGER = LoggerFactory.getLogger(JDBCPoolInit.class);
/**
* 解析数据库URL,获取数据库名
* @param url 数据库URL
* @return 数据库名
*/
public static String getDatabaseName(String url) {
// 正则表达式匹配数据库名
String regex = "jdbc:mysql://[^/]+/(\\w+)(\\?.*)?";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(url);
if (matcher.find()) {
return matcher.group(1);
} else {
throw new IllegalArgumentException("Invalid database URL: " + url);
}
}
/**
* 使用JDBC原生方法创建数据库
* @param url 数据库连接URL
* @param user 数据库用户名
* @param password 数据库密码
*/
public static void createDatabase(String url, String user, String password) {
String dbName = getDatabaseName(url);
LOGGER.info(">>>>>>>>>>> 创建数据库:'{}' <<<<<<<<<<<< ", dbName);
// 去掉数据库名,构建不带数据库名的URL
String baseUrl = url.substring(0, url.lastIndexOf("/") + 1) + "?characterEncoding=UTF-8&useUnicode=true";
try (Connection conn = DriverManager.getConnection(baseUrl, user, password);
Statement stmt = conn.createStatement()) {
// 创建数据库
stmt.executeUpdate("CREATE DATABASE IF NOT EXISTS " + dbName + " CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
LOGGER.info(">>>>>>>>>>> 数据库'{}'创建成功 <<<<<<<<<<<<", dbName);
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void createDatabase(JsonObject dbConfig) {
createDatabase(
dbConfig.getString("jdbcUrl"),
dbConfig.getString("username"),
dbConfig.getString("password")
);
}
}
@@ -1,11 +1,14 @@
package cn.qaiu.db.ddl;
import cn.qaiu.db.pool.JDBCType;
import cn.qaiu.vx.core.util.ReflectionUtil;
import io.vertx.codegen.format.CamelCase;
import io.vertx.codegen.format.Case;
import io.vertx.codegen.format.LowerCamelCase;
import io.vertx.codegen.format.SnakeCase;
import io.vertx.jdbcclient.JDBCPool;
import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.sqlclient.Pool;
import io.vertx.sqlclient.templates.annotations.Column;
import io.vertx.sqlclient.templates.annotations.RowMapped;
import org.apache.commons.lang3.StringUtils;
@@ -13,9 +16,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.*;
/**
* 创建表
@@ -23,148 +24,312 @@ import java.util.Set;
* @author <a href="https://qaiu.top">QAIU</a>
*/
public class CreateTable {
public static Map<Class<?>, String> javaProperty2SqlColumnMap = new HashMap<>();
public static Map<Class<?>, String> javaProperty2SqlColumnMap = new HashMap<>() {{
// Java类型到SQL类型的映射
put(Integer.class, "INT");
put(Short.class, "SMALLINT");
put(Byte.class, "TINYINT");
put(Long.class, "BIGINT");
put(java.math.BigDecimal.class, "DECIMAL");
put(Double.class, "DOUBLE");
put(Float.class, "REAL");
put(Boolean.class, "BOOLEAN");
put(String.class, "VARCHAR");
put(Date.class, "TIMESTAMP");
put(java.time.LocalDateTime.class, "TIMESTAMP");
put(java.sql.Timestamp.class, "TIMESTAMP");
put(java.sql.Date.class, "DATE");
put(java.sql.Time.class, "TIME");
// 基本数据类型
put(int.class, "INT");
put(short.class, "SMALLINT");
put(byte.class, "TINYINT");
put(long.class, "BIGINT");
put(double.class, "DOUBLE");
put(float.class, "REAL");
put(boolean.class, "BOOLEAN");
}};
private static final Logger LOGGER = LoggerFactory.getLogger(CreateTable.class);
static {
javaProperty2SqlColumnMap.put(Integer.class, "INT");
javaProperty2SqlColumnMap.put(Short.class, "SMALLINT");
javaProperty2SqlColumnMap.put(Byte.class, "TINYINT");
javaProperty2SqlColumnMap.put(Long.class, "BIGINT");
javaProperty2SqlColumnMap.put(java.math.BigDecimal.class, "DECIMAL");
javaProperty2SqlColumnMap.put(Double.class, "DOUBLE");
javaProperty2SqlColumnMap.put(Float.class, "REAL");
javaProperty2SqlColumnMap.put(Boolean.class, "BOOLEAN");
javaProperty2SqlColumnMap.put(String.class, "VARCHAR");
javaProperty2SqlColumnMap.put(java.util.Date.class, "TIMESTAMP");
javaProperty2SqlColumnMap.put(java.sql.Timestamp.class, "TIMESTAMP");
javaProperty2SqlColumnMap.put(java.sql.Date.class, "DATE");
javaProperty2SqlColumnMap.put(java.sql.Time.class, "TIME");
javaProperty2SqlColumnMap.put(int.class, "INT");
javaProperty2SqlColumnMap.put(short.class, "SMALLINT");
javaProperty2SqlColumnMap.put(byte.class, "TINYINT");
javaProperty2SqlColumnMap.put(long.class, "BIGINT");
javaProperty2SqlColumnMap.put(double.class, "DOUBLE");
javaProperty2SqlColumnMap.put(float.class, "REAL");
javaProperty2SqlColumnMap.put(boolean.class, "BOOLEAN");
}
public static String UNIQUE_PREFIX = "idx_";
private static Case getCase(Class<?> clz) {
switch (clz.getName()) {
case "io.vertx.codegen.format.CamelCase":
return CamelCase.INSTANCE;
case "io.vertx.codegen.format.SnakeCase":
return SnakeCase.INSTANCE;
case "io.vertx.codegen.format.LowerCamelCase":
return LowerCamelCase.INSTANCE;
default:
throw new UnsupportedOperationException();
}
return switch (clz.getName()) {
case "io.vertx.codegen.format.CamelCase" -> CamelCase.INSTANCE;
case "io.vertx.codegen.format.SnakeCase" -> SnakeCase.INSTANCE;
case "io.vertx.codegen.format.LowerCamelCase" -> LowerCamelCase.INSTANCE;
default -> throw new UnsupportedOperationException();
};
}
public static String getCreateTableSQL(Class<?> clz) {
// 判断类上是否有次注解
String primaryKey = null; // 主键
String tableName = null; // 表名
public static List<String> getCreateTableSQL(Class<?> clz, JDBCType type) {
// 获取表名和主键
TableInfo tableInfo = extractTableInfo(clz, type);
// 构建表的SQL语句
List<String> sqlList = new ArrayList<>();
StringBuilder sb = new StringBuilder(50);
sb.append("CREATE TABLE IF NOT EXISTS ")
.append(tableInfo.quotationMarks).append(tableInfo.tableName).append(tableInfo.quotationMarks)
.append(" ( \r\n ");
// 处理字段并生成列定义
List<String> indexSQLs = new ArrayList<>();
processFields(clz, tableInfo, sb, indexSQLs);
// 去掉最后一个逗号并添加表尾部信息
String tableSQL = sb.substring(0, sb.lastIndexOf(",")) + tableInfo.endStr;
sqlList.add(tableSQL);
// 添加索引SQL
sqlList.addAll(indexSQLs);
return sqlList;
}
// 修改extractTableInfo方法,处理没有Table注解时默认使用id字段作为主键
private static TableInfo extractTableInfo(Class<?> clz, JDBCType type) {
String quotationMarks;
String endStr;
if (type == JDBCType.MySQL) {
quotationMarks = "`";
endStr = ")ENGINE=InnoDB DEFAULT CHARSET=utf8;";
} else {
quotationMarks = "\"";
endStr = ");";
}
String primaryKey = null;
String tableName = null;
Case caseFormat = SnakeCase.INSTANCE;
// 判断类上是否有RowMapped注解
if (clz.isAnnotationPresent(RowMapped.class)) {
RowMapped annotation = clz.getAnnotation(RowMapped.class);
Class<? extends Case> formatter = annotation.formatter();
caseFormat = getCase(formatter);
caseFormat = getCase(annotation.formatter());
}
// 判断类上是否有Table注解
if (clz.isAnnotationPresent(Table.class)) {
// 获取类上的注解
Table annotation = clz.getAnnotation(Table.class);
// 输出注解上的类名
String tableNameAnnotation = annotation.value();
if (StringUtils.isNotEmpty(tableNameAnnotation)) {
tableName = tableNameAnnotation;
} else {
tableName = LowerCamelCase.INSTANCE.to(caseFormat, clz.getSimpleName());
}
tableName = StringUtils.isNotEmpty(annotation.value())
? annotation.value()
: LowerCamelCase.INSTANCE.to(caseFormat, clz.getSimpleName());
primaryKey = annotation.keyFields();
}
// 如果表名仍为null,使用类名转下划线命名作为表名
if (StringUtils.isEmpty(tableName)) {
tableName = LowerCamelCase.INSTANCE.to(SnakeCase.INSTANCE, clz.getSimpleName());
}
// 如果主键为空,默认使用id字段作为主键
if (StringUtils.isEmpty(primaryKey)) {
try {
clz.getDeclaredField("id");
primaryKey = "id";
} catch (NoSuchFieldException e) {
// 如果没有id字段,不设置主键
primaryKey = null;
}
}
return new TableInfo(tableName, quotationMarks, endStr, primaryKey, caseFormat, type);
}
// 修改processFields方法,处理索引
private static void processFields(Class<?> clz, TableInfo tableInfo, StringBuilder sb, List<String> indexSQLs) {
Field[] fields = clz.getDeclaredFields();
String column;
int[] decimalSize = {22, 2};
int varcharSize = 255;
StringBuilder sb = new StringBuilder(50);
sb.append("CREATE TABLE IF NOT EXISTS \"").append(tableName).append("\" ( \r\n ");
boolean firstId = true;
for (Field f : fields) {
Class<?> paramType = f.getType();
String sqlType = javaProperty2SqlColumnMap.get(paramType);
if (f.getName().equals("serialVersionUID") || StringUtils.isEmpty(sqlType) || f.isAnnotationPresent(TableGenIgnore.class)) {
for (Field field : fields) {
// 跳过无效字段
if (isIgnoredField(field)) {
continue;
}
column = LowerCamelCase.INSTANCE.to(caseFormat, f.getName());
if (f.isAnnotationPresent(Column.class)) {
Column columnAnnotation = f.getAnnotation(Column.class);
//输出注解属性
// 获取字段名和SQL类型
String column = LowerCamelCase.INSTANCE.to(tableInfo.caseFormat, field.getName());
String sqlType = javaProperty2SqlColumnMap.get(field.getType());
// 处理字段注解
column = processColumnAnnotation(field, column);
int[] decimalSize = {22, 2};
int varcharSize = 255;
if (field.isAnnotationPresent(Length.class)) {
Length length = field.getAnnotation(Length.class);
decimalSize = length.decimalSize();
varcharSize = length.varcharSize();
}
// 构建列定义
sb.append(tableInfo.quotationMarks).append(column).append(tableInfo.quotationMarks)
.append(" ").append(sqlType);
appendTypeLength(sqlType, sb, decimalSize, varcharSize);
appendConstraints(field, sb, tableInfo);
appendPrimaryKey(tableInfo.primaryKey, column, sb);
// 添加索引
appendIndex(tableInfo, indexSQLs, field);
sb.append(",\n ");
}
}
// 判断是否忽略字段
private static boolean isIgnoredField(Field field) {
return field.getName().equals("serialVersionUID")
|| StringUtils.isEmpty(javaProperty2SqlColumnMap.get(field.getType()))
|| field.isAnnotationPresent(TableGenIgnore.class);
}
// 处理Column注解
private static String processColumnAnnotation(Field field, String column) {
if (field.isAnnotationPresent(Column.class)) {
Column columnAnnotation = field.getAnnotation(Column.class);
if (StringUtils.isNotBlank(columnAnnotation.name())) {
column = columnAnnotation.name();
}
}
if (f.isAnnotationPresent(Length.class)) {
Length fieldAnnotation = f.getAnnotation(Length.class);
decimalSize = fieldAnnotation.decimalSize();
varcharSize = fieldAnnotation.varcharSize();
return column;
}
sb.append("\"").append(column).append("\"");
sb.append(" ").append(sqlType);
// 添加类型长度
if (sqlType.equals("DECIMAL")) {
private static void appendTypeLength(String sqlType, StringBuilder sb, int[] decimalSize, int varcharSize) {
if ("DECIMAL".equals(sqlType)) {
sb.append("(").append(decimalSize[0]).append(",").append(decimalSize[1]).append(")");
}
if (sqlType.equals("VARCHAR")) {
} else if ("VARCHAR".equals(sqlType)) {
sb.append("(").append(varcharSize).append(")");
}
if (f.isAnnotationPresent(Constraint.class)) {
Constraint constraintAnnotation = f.getAnnotation(Constraint.class);
if (constraintAnnotation.notNull()) {
//非空约束
}
// 添加约束
private static void appendConstraints(Field field, StringBuilder sb, TableInfo tableInfo) {
JDBCType type = tableInfo.dbType;
if (field.isAnnotationPresent(Constraint.class)) {
Constraint constraint = field.getAnnotation(Constraint.class);
if (constraint.notNull()) {
sb.append(" NOT NULL");
}
String apostrophe = constraintAnnotation.defaultValueIsFunction() ? "" : "'";
if (StringUtils.isNotEmpty(constraintAnnotation.defaultValue())) {
//默认值约束
sb.append(" DEFAULT ").append(apostrophe).append(constraintAnnotation.defaultValue()).append(apostrophe);
String apostrophe = constraint.defaultValueIsFunction() ? "" : "'";
if (StringUtils.isNotEmpty(constraint.defaultValue())) {
sb.append(" DEFAULT ").append(apostrophe).append(constraint.defaultValue()).append(apostrophe);
}
if (constraintAnnotation.autoIncrement() && paramType.equals(Integer.class) || paramType.equals(Long.class)) {
////自增
if (constraint.autoIncrement()) {
if (type == JDBCType.PostgreSQL) {
// 需要移除字段类型(最后一个单词)
if (field.getType().equals(Integer.class)) {
sb.delete(sb.lastIndexOf(" "), sb.length());
sb.append(" SERIAL");
} else if (field.getType().equals(Long.class)) {
sb.delete(sb.lastIndexOf(" "), sb.length());
sb.append(" BIGSERIAL");
}
} else if (field.getType().equals(Integer.class) || field.getType().equals(Long.class)) {
sb.append(" AUTO_INCREMENT");
}
}
if (StringUtils.isEmpty(primaryKey)) {
if (firstId) {//类型转换
sb.append(" PRIMARY KEY");
firstId = false;
}
} else {
if (primaryKey.equals(column.toLowerCase())) {
sb.append(" PRIMARY KEY");
}
}
sb.append(",\n ");
}
String sql = sb.toString();
//去掉最后一个逗号
int lastIndex = sql.lastIndexOf(",");
sql = sql.substring(0, lastIndex) + sql.substring(lastIndex + 1);
return sql.substring(0, sql.length() - 1) + ");\r\n";
}
public static void createTable(JDBCPool pool, String tableClassPath) {
Set<Class<?>> tableClassList = ReflectionUtil.getReflections(tableClassPath).getTypesAnnotatedWith(Table.class);
if (tableClassList.isEmpty()) LOGGER.info("Table model class not fount");
tableClassList.forEach(clazz -> {
String createTableSQL = getCreateTableSQL(clazz);
pool.query(createTableSQL).execute().onSuccess(
rs -> LOGGER.info("\n" + createTableSQL + "create table --> ok")
).onFailure(Throwable::printStackTrace);
});
// 添加主键
private static void appendPrimaryKey(String primaryKey, String column, StringBuilder sb) {
if (StringUtils.isEmpty(primaryKey)) {
return;
}
if (primaryKey.equalsIgnoreCase(column)) {
sb.append(" PRIMARY KEY");
}
}
private static void appendIndex(TableInfo tableInfo, List<String> indexSQLs, Field field) {
if (!field.isAnnotationPresent(Constraint.class)) {
return;
}
Constraint constraint = field.getAnnotation(Constraint.class);
if (StringUtils.isEmpty(constraint.uniqueKey())) {
return;
}
String indexName = UNIQUE_PREFIX + tableInfo.tableName + "_" + constraint.uniqueKey();
String columnName = field.getName();
// 检查是否已有相同索引名称的索引
Optional<String> existingIndex = indexSQLs.stream()
.filter(sql -> sql.contains(tableInfo.quotationMarks + indexName + tableInfo.quotationMarks))
.findFirst();
if (existingIndex.isPresent()) {
// 如果存在相同索引名称,追加字段到索引定义中
String updatedIndex = existingIndex.get().replaceFirst(
"\\(([^)]+)\\)", // 匹配索引字段列表
"($1, " + tableInfo.quotationMarks + columnName + tableInfo.quotationMarks + ")"
);
indexSQLs.remove(existingIndex.get());
indexSQLs.add(updatedIndex);
} else {
// 如果不存在相同索引名称,创建新的索引
String indexSQL = String.format(
"CREATE UNIQUE INDEX %s %s%s%s ON %s%s%s (%s%s%s);",
tableInfo.dbType == JDBCType.MySQL ? "" : "IF NOT EXISTS",
tableInfo.quotationMarks, indexName, tableInfo.quotationMarks,
tableInfo.quotationMarks, tableInfo.tableName, tableInfo.quotationMarks,
tableInfo.quotationMarks, columnName, tableInfo.quotationMarks
);
indexSQLs.add(indexSQL);
}
}
// 表信息类
private record TableInfo(
String tableName, // 表名
String quotationMarks, // 引号或反引号
String endStr, // 表尾部信息
String primaryKey, // 主键字段
Case caseFormat, // 命名格式
JDBCType dbType // 数据库类型
) {
}
public static Future<Void> createTable(Pool pool, JDBCType type) {
Promise<Void> promise = Promise.promise();
Set<Class<?>> tableClasses = ReflectionUtil.getReflections().getTypesAnnotatedWith(Table.class);
if (tableClasses.isEmpty()) {
LOGGER.warn("Table model class not found");
promise.complete();
return promise.future();
}
List<Future<Object>> futures = new ArrayList<>();
for (Class<?> clazz : tableClasses) {
List<String> sqlList = getCreateTableSQL(clazz, type);
LOGGER.info("Class `{}` auto-generate table", clazz.getName());
for (String sql : sqlList) {
try {
pool.query(sql).execute().toCompletionStage().toCompletableFuture().join();
futures.add(Future.succeededFuture());
LOGGER.debug("Executed SQL:\n{}", sql);
} catch (Exception e) {
String message = e.getMessage();
if (message != null && message.contains("Duplicate key name")) {
LOGGER.warn("Ignoring duplicate key error: {}", message);
futures.add(Future.succeededFuture());
} else {
LOGGER.error("SQL Error: {}\nSQL: {}", message, sql);
futures.add(Future.failedFuture(e));
throw new RuntimeException(e); // Stop execution for other exceptions
}
}
}
}
Future.all(futures).onSuccess(r -> promise.complete()).onFailure(promise::fail);
return promise.future();
}
}
@@ -1,20 +1,16 @@
package cn.qaiu.db.pool;
import cn.qaiu.db.ddl.CreateTable;
import cn.qaiu.db.server.H2ServerHolder;
import cn.qaiu.db.ddl.CreateDatabase;
import cn.qaiu.vx.core.util.VertxHolder;
import io.vertx.core.Promise;
import io.vertx.core.Future;
import io.vertx.core.Vertx;
import io.vertx.core.json.JsonObject;
import io.vertx.jdbcclient.JDBCPool;
import org.h2.tools.Server;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
/**
* 初始化JDBC
* <br>Create date 2021/8/10 12:04
@@ -24,16 +20,29 @@ import java.sql.SQLException;
public class JDBCPoolInit {
private static final Logger LOGGER = LoggerFactory.getLogger(JDBCPoolInit.class);
private static final String providerClass = io.vertx.ext.jdbc.spi.impl.HikariCPDataSourceProvider.class.getName();
private JDBCPool pool = null;
JsonObject dbConfig;
Vertx vertx = VertxHolder.getVertxInstance();
String url;
private final JDBCType type;
private static JDBCPoolInit instance;
public JDBCType getType() {
return type;
}
public JDBCPoolInit(Builder builder) {
this.dbConfig = builder.dbConfig;
this.url = builder.url;
this.type = JDBCType.getJDBCTypeByURL(builder.url);
if (StringUtils.isBlank(builder.dbConfig.getString("provider_class"))) {
builder.dbConfig.put("provider_class", providerClass);
}
}
public static Builder builder() {
@@ -62,86 +71,34 @@ public class JDBCPoolInit {
}
}
/**
* init h2db<br>
* 这个方法只允许调用一次
*/
public void initPool() {
synchronized public Future<Void> initPool() {
if (pool != null) {
LOGGER.error("pool 重复初始化");
return;
return null;
}
// 异步启动H2服务
vertx.createSharedWorkerExecutor("h2-server", 1, Long.MAX_VALUE)
.executeBlocking(this::h2serverExecute)
.onSuccess(res->{
LOGGER.info(res);
// 初始化数据库连接
vertx.createSharedWorkerExecutor("sql-pool-init")
.executeBlocking(this::poolInitExecute)
.onSuccess(LOGGER::info)
.onFailure(Throwable::printStackTrace);
})
.onFailure(Throwable::printStackTrace);
}
private void poolInitExecute(Promise<String> promise) {
// 初始化连接池
if (type == JDBCType.MySQL) {
CreateDatabase.createDatabase(dbConfig);
}
pool = JDBCPool.pool(vertx, dbConfig);
CreateTable.createTable(pool, dbConfig.getString("tableClassPath"));
promise.complete("init jdbc pool success");
LOGGER.info("数据库连接初始化: URL=" + url);
return CreateTable.createTable(pool, type);
}
private void checkOrCreateDBFile() {
LOGGER.info("init sql start");
String[] path = url.split("\\./");
path[1] = path[1].split(";")[0];
path[1] += ".mv.db";
File file = new File(path[1]);
if (!file.exists()) {
if (!file.getParentFile().exists()) {
if (file.getParentFile().mkdirs()) {
LOGGER.info("mkdirs -> {}", file.getParentFile().getAbsolutePath());
}
}
try {
if (file.createNewFile()) {
LOGGER.info("create file -> {}", file.getAbsolutePath());
}
} catch (IOException e) {
LOGGER.error(e.getMessage());
throw new RuntimeException("file create failed");
}
}
}
private void h2serverExecute(Promise<String> promise) {
// 初始化H2db, 创建本地db文件
checkOrCreateDBFile();
try {
String url = dbConfig.getString("jdbcUrl");
String[] portStr = url.split(":");
String port = portStr[portStr.length - 1].split("[/\\\\]")[0];
LOGGER.info("H2server listen port to {}", port);
H2ServerHolder.init(Server.createTcpServer("-tcp", "-tcpAllowOthers", "-tcpPort", port).start());
promise.complete("Start h2Server success");
} catch (SQLException e) {
throw new RuntimeException("Start h2Server failed: " + e.getMessage());
}
}
/**
* 获取连接池
*
* @return pool
*/
public JDBCPool getPool() {
synchronized public JDBCPool getPool() {
return pool;
}
}
@@ -0,0 +1,35 @@
package cn.qaiu.db.pool;
import org.apache.commons.lang3.StringUtils;
/**
* @author <a href="https://qaiu.top">QAIU</a>
* @since 2023/10/10 14:06
*/
public enum JDBCType {
// 添加驱动类型字段
MySQL("jdbc:mysql:"),
H2DB("jdbc:h2:"),
PostgreSQL("jdbc:postgresql:");
private final String urlPrefix; // JDBC URL 前缀
// 构造函数
JDBCType(String urlPrefix) {
this.urlPrefix = urlPrefix;
}
// 获取 JDBC URL 前缀
public String getUrlPrefix() {
return urlPrefix;
}
// 根据 JDBC URL 获取 JDBC 类型
public static JDBCType getJDBCTypeByURL(String jdbcURL) {
for (JDBCType jdbcType : values()) {
if (StringUtils.startsWithIgnoreCase(jdbcURL, jdbcType.getUrlPrefix())) {
return jdbcType;
}
}
throw new RuntimeException("不支持的SQL类型: " + jdbcURL);
}
}
+25 -30
View File
@@ -5,41 +5,22 @@
<parent>
<artifactId>netdisk-fast-download</artifactId>
<groupId>cn.qaiu</groupId>
<version>0.1.3</version>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<version>1.0.8</version>
<artifactId>core</artifactId>
<properties>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<vertx.version>4.4.1</vertx.version>
<org.reflections.version>0.10.2</org.reflections.version>
<lombok.version>1.18.12</lombok.version>
<slf4j.version>2.0.5</slf4j.version>
<commons-lang3.version>3.12.0</commons-lang3.version>
<jackson.version>2.14.2</jackson.version>
<maven.build.timestamp.format>yyMMdd_HHmm</maven.build.timestamp.format>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-dependencies</artifactId>
<version>${vertx.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!--logback日志实现-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.6</version>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
@@ -80,28 +61,42 @@
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson.version}</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<version>3.13.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<release>${java.version}</release>
<!-- 代码生成器 -->
<annotationProcessors>
<annotationProcessor>io.vertx.codegen.CodeGenProcessor</annotationProcessor>
</annotationProcessors>
<generatedSourcesDirectory>
${project.basedir}/src/main/generated
</generatedSourcesDirectory>
</configuration>
</plugin>
</plugins>
+46 -19
View File
@@ -1,12 +1,14 @@
package cn.qaiu.vx.core;
import cn.qaiu.vx.core.util.ConfigConstant;
import cn.qaiu.vx.core.util.CommonUtil;
import cn.qaiu.vx.core.util.ConfigUtil;
import cn.qaiu.vx.core.util.VertxHolder;
import cn.qaiu.vx.core.verticle.ReverseProxyVerticle;
import cn.qaiu.vx.core.verticle.RouterVerticle;
import cn.qaiu.vx.core.verticle.ServiceVerticle;
import io.vertx.core.*;
import io.vertx.core.dns.AddressResolverOptions;
import io.vertx.core.impl.launcher.commands.VersionCommand;
import io.vertx.core.json.JsonObject;
import io.vertx.core.shareddata.LocalMap;
import org.slf4j.Logger;
@@ -17,6 +19,8 @@ import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.locks.LockSupport;
import static cn.qaiu.vx.core.util.ConfigConstant.*;
/**
* vertx启动类 需要在主启动类完成回调
* <br>Create date 2021-05-07 10:26:54
@@ -42,12 +46,17 @@ public final class Deploy {
return INSTANCE;
}
/**
*
* @param args 启动参数
* @param handle 启动完成后回调处理函数
*/
public void start(String[] args, Handler<JsonObject> handle) {
this.mainThread = Thread.currentThread();
this.handle = handle;
if (args.length > 0) {
if (args.length > 0 && args[0].startsWith("app-")) {
// 启动参数dev或者prod
path.append("-").append(args[0]);
path.append("-").append(args[0].replace("app-",""));
}
// 读取yml配置
@@ -63,7 +72,7 @@ public final class Deploy {
var activeMode = conf.getString("active");
if ("dev".equals(activeMode)) {
LOGGER.info("---------------> development environment <--------------\n");
System.setProperty("vertxweb.environment","dev");
System.setProperty("vertxweb.environment", "dev");
} else {
LOGGER.info("---------------> Production environment <--------------\n");
}
@@ -80,7 +89,7 @@ public final class Deploy {
var calendar = Calendar.getInstance();
calendar.setTime(new Date());
var year = calendar.get(Calendar.YEAR);
var logoTemplete = """
var logoTemplate = """
Web Server powered by:\s
____ ____ _ _ _ \s
@@ -93,9 +102,9 @@ public final class Deploy {
""";
System.out.printf(logoTemplete,
conf.getString("version_app"),
conf.getString("version_vertx"),
System.out.printf(logoTemplate,
CommonUtil.getAppVersion(),
VersionCommand.getVersion(),
conf.getString("copyright"),
year
);
@@ -107,29 +116,47 @@ public final class Deploy {
private void deployVerticle() {
tempVertx.close();
LOGGER.info("配置读取成功");
customConfig = globalConfig.getJsonObject(ConfigConstant.CUSTOM);
customConfig = globalConfig.getJsonObject(CUSTOM);
var vertxOptions = new VertxOptions(globalConfig.getJsonObject(ConfigConstant.VERTX));
JsonObject vertxConfig = globalConfig.getJsonObject(VERTX);
Integer vertxConfigELPS = vertxConfig.getInteger(EVENT_LOOP_POOL_SIZE);
var vertxOptions = vertxConfigELPS == 0 ?
new VertxOptions() : new VertxOptions(vertxConfig);
vertxOptions.setAddressResolverOptions(
new AddressResolverOptions().
addServer("114.114.114.114").
addServer("114.114.115.115").
addServer("8.8.8.8").
addServer("8.8.4.4"));
LOGGER.info("vertxConfigEventLoopPoolSize: {}, eventLoopPoolSize: {}, workerPoolSize: {}", vertxConfigELPS,
vertxOptions.getEventLoopPoolSize(),
vertxOptions.getWorkerPoolSize());
var vertx = Vertx.vertx(vertxOptions);
VertxHolder.init(vertx);
//配置保存在共享数据中
var sharedData = vertx.sharedData();
LocalMap<String, Object> localMap = sharedData.getLocalMap(ConfigConstant.LOCAL);
localMap.put(ConfigConstant.GLOBAL_CONFIG, globalConfig);
localMap.put(ConfigConstant.CUSTOM_CONFIG, customConfig);
localMap.put(ConfigConstant.SERVER, globalConfig.getJsonObject(ConfigConstant.SERVER));
var future0 = vertx.createSharedWorkerExecutor("other-handle").executeBlocking(bch -> {
LocalMap<String, Object> localMap = sharedData.getLocalMap(LOCAL);
localMap.put(GLOBAL_CONFIG, globalConfig);
localMap.put(CUSTOM_CONFIG, customConfig);
localMap.put(SERVER, globalConfig.getJsonObject(SERVER));
var future0 = vertx.createSharedWorkerExecutor("other-handle")
.executeBlocking(() -> {
handle.handle(globalConfig);
bch.complete("other handle complete");
return "Other handle complete";
});
future0.onSuccess(res -> {
LOGGER.info(res);
// 部署 路由、异步service、反向代理 服务
var future1 = vertx.deployVerticle(RouterVerticle.class, getWorkDeploymentOptions("Router"));
var future2 = vertx.deployVerticle(ServiceVerticle.class, getWorkDeploymentOptions("Service"));
var future3 = vertx.deployVerticle(ReverseProxyVerticle.class, getWorkDeploymentOptions("proxy"));
CompositeFuture.all(future1, future2, future3, future0)
Future.all(future1, future2, future3)
.onSuccess(this::deployWorkVerticalSuccess)
.onFailure(this::deployVerticalFailed);
}).onFailure(e -> LOGGER.error("Other handle error", e));
}
/**
@@ -160,13 +187,13 @@ public final class Deploy {
* @return Deployment Options
*/
private DeploymentOptions getWorkDeploymentOptions(String name) {
return getWorkDeploymentOptions(name, customConfig.getInteger(ConfigConstant.ASYNC_SERVICE_INSTANCES));
return getWorkDeploymentOptions(name, customConfig.getInteger(ASYNC_SERVICE_INSTANCES));
}
private DeploymentOptions getWorkDeploymentOptions(String name, int ins) {
return new DeploymentOptions()
.setWorkerPoolName(name)
.setWorker(true)
.setThreadingModel(ThreadingModel.WORKER)
.setInstances(ins);
}
@@ -0,0 +1,15 @@
package cn.qaiu.vx.core.annotaions;
import java.lang.annotation.*;
@Documented
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface HandleSortFilter {
/**
* 注册顺序,数字越大越先注册<br>
* 值<0时会过滤掉该处理器
*/
int value() default 0;
}
@@ -0,0 +1,23 @@
package cn.qaiu.vx.core.annotaions;
import java.lang.annotation.*;
/**
* 拦截器配置注解
* 正则匹配拦截途径
*
* @author <a href="https://qaiu.top">QAIU</a>
*/
@Documented
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface InterceptorConfig {
String pattern() default "";
/**
* 注册顺序,数字越大越先注册
*/
int order() default 0;
}
@@ -1,9 +1,16 @@
package cn.qaiu.vx.core.base;
import cn.qaiu.vx.core.interceptor.AfterInterceptor;
import cn.qaiu.vx.core.model.JsonResult;
import cn.qaiu.vx.core.util.CommonUtil;
import cn.qaiu.vx.core.util.ReflectionUtil;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
import org.reflections.Reflections;
import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE;
import java.util.Set;
import static cn.qaiu.vx.core.util.ResponseUtil.*;
/**
* 统一响应处理
@@ -13,22 +20,43 @@ import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE;
*/
public interface BaseHttpApi {
default void fireJsonResponse(RoutingContext ctx, JsonObject jsonResult) {
ctx.response().putHeader(CONTENT_TYPE, "application/json; charset=utf-8")
.setStatusCode(200)
.end(jsonResult.encode());
// 需要扫描注册的Router路径
Reflections reflections = ReflectionUtil.getReflections();
default void doFireJsonObjectResponse(RoutingContext ctx, JsonObject jsonObject) {
if (!ctx.response().ended()) {
fireJsonObjectResponse(ctx, jsonObject);
}
handleAfterInterceptor(ctx, jsonObject);
}
default <T> void fireJsonResponse(RoutingContext ctx, T jsonResult) {
JsonObject jsonObject = JsonObject.mapFrom(jsonResult);
fireJsonResponse(ctx, jsonObject);
default <T> void doFireJsonResultResponse(RoutingContext ctx, JsonResult<T> jsonResult) {
if (!ctx.response().ended()) {
fireJsonResultResponse(ctx, jsonResult);
}
handleAfterInterceptor(ctx, jsonResult.toJsonObject());
}
default void fireTextResponse(RoutingContext ctx, String text) {
ctx.response().putHeader("content-type", "text/html; charset=utf-8").end(text);
default Set<AfterInterceptor> getAfterInterceptor() {
Set<Class<? extends AfterInterceptor>> afterInterceptorClassSet =
reflections.getSubTypesOf(AfterInterceptor.class);
if (afterInterceptorClassSet == null) {
return null;
}
return CommonUtil.sortClassSet(afterInterceptorClassSet);
}
default void sendError(int statusCode, RoutingContext ctx) {
ctx.response().setStatusCode(statusCode).end();
default void handleAfterInterceptor(RoutingContext ctx, JsonObject jsonObject) {
Set<AfterInterceptor> afterInterceptor = getAfterInterceptor();
if (afterInterceptor != null) {
afterInterceptor.forEach(ai -> ai.handle(ctx, jsonObject));
}
if (!ctx.response().ended()) {
fireTextResponse(ctx, "handleAfterInterceptor: response not end");
}
}
}
@@ -5,9 +5,10 @@ import cn.qaiu.vx.core.annotaions.RouteHandler;
import cn.qaiu.vx.core.annotaions.RouteMapping;
import cn.qaiu.vx.core.annotaions.SockRouteMapper;
import cn.qaiu.vx.core.base.BaseHttpApi;
import cn.qaiu.vx.core.enums.MIMEType;
import cn.qaiu.vx.core.interceptor.BeforeInterceptor;
import cn.qaiu.vx.core.model.JsonResult;
import cn.qaiu.vx.core.util.*;
import io.netty.handler.codec.http.HttpHeaderValues;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.MultiMap;
@@ -19,25 +20,29 @@ import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.Route;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.handler.BodyHandler;
import io.vertx.ext.web.handler.CorsHandler;
import io.vertx.ext.web.handler.*;
import io.vertx.ext.web.handler.sockjs.SockJSHandler;
import io.vertx.ext.web.handler.sockjs.SockJSHandlerOptions;
import io.vertx.ext.web.sstore.LocalSessionStore;
import io.vertx.ext.web.sstore.SessionStore;
import javassist.CtClass;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.reflections.Reflections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static cn.qaiu.vx.core.util.ConfigConstant.ROUTE_TIME_OUT;
import static cn.qaiu.vx.core.verticle.ReverseProxyVerticle.REROUTE_PATH_PREFIX;
import static io.vertx.core.http.HttpHeaders.*;
import static java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME;
/**
* 路由映射, 参数绑定
@@ -56,15 +61,11 @@ public class RouterHandlerFactory implements BaseHttpApi {
add(HttpMethod.DELETE);
add(HttpMethod.HEAD);
}};
// 需要扫描注册的Router路径
private static volatile Reflections reflections;
private final String gatewayPrefix;
public RouterHandlerFactory(String routerScanAddress, String gatewayPrefix) {
Objects.requireNonNull(routerScanAddress, "The router package address scan is empty.");
public RouterHandlerFactory(String gatewayPrefix) {
Objects.requireNonNull(gatewayPrefix, "The gateway prefix is empty.");
reflections = ReflectionUtil.getReflections(routerScanAddress);
this.gatewayPrefix = gatewayPrefix;
}
@@ -72,22 +73,47 @@ public class RouterHandlerFactory implements BaseHttpApi {
* 开始扫描并注册handler
*/
public Router createRouter() {
Router router = Router.router(VertxHolder.getVertxInstance());
router.route().handler(ctx -> {
// 主路由
Router mainRouter = Router.router(VertxHolder.getVertxInstance());
mainRouter.route().handler(ctx -> {
String realPath = ctx.request().uri();;
if (realPath.startsWith(REROUTE_PATH_PREFIX)) {
// vertx web proxy暂不支持rewrite, 所以这里进行手动替换, 请求地址中的请求path前缀替换为originPath
String rePath = realPath.substring(REROUTE_PATH_PREFIX.length());
ctx.reroute(rePath);
return;
}
LOGGER.debug("The HTTP service request address information ===>path:{}, uri:{}, method:{}",
ctx.request().path(), ctx.request().absoluteURI(), ctx.request().method());
ctx.response().headers().add(ACCESS_CONTROL_ALLOW_ORIGIN, "*");
ctx.response().headers().add(DATE, LocalDateTime.now().format(ISO_LOCAL_DATE_TIME));
ctx.response().headers().add(ACCESS_CONTROL_ALLOW_METHODS, "POST, GET, OPTIONS, PUT, DELETE, HEAD");
ctx.response().headers().add(ACCESS_CONTROL_ALLOW_HEADERS, "X-PINGOTHER, Origin,Content-Type, Accept, X-Requested-With, Dev, Authorization, Version, Token");
ctx.response().headers().add(ACCESS_CONTROL_ALLOW_HEADERS, "X-PINGOTHER, Origin,Content-Type, Accept, " +
"X-Requested-With, Dev, Authorization, Version, Token");
ctx.response().headers().add(ACCESS_CONTROL_MAX_AGE, "1728000");
ctx.next();
});
// 添加跨域的方法
router.route().handler(CorsHandler.create().addRelativeOrigin(".*").allowCredentials(true).allowedMethods(httpMethods));
mainRouter.route().handler(CorsHandler.create().addRelativeOrigin(".*").allowCredentials(true).allowedMethods(httpMethods));
// 配置文件上传路径
router.route().handler(BodyHandler.create().setUploadsDirectory("uploads"));
mainRouter.route().handler(BodyHandler.create().setUploadsDirectory("uploads"));
// 配置Session管理 - 用于演练场登录状态持久化
// 30天过期时间(毫秒)
SessionStore sessionStore = LocalSessionStore.create(VertxHolder.getVertxInstance());
SessionHandler sessionHandler = SessionHandler.create(sessionStore)
.setSessionTimeout(30L * 24 * 60 * 60 * 1000) // 30天
.setSessionCookieName("SESSIONID") // Cookie名称
.setCookieHttpOnlyFlag(true) // 防止XSS攻击
.setCookieSecureFlag(false); // 非HTTPS环境设置为false
mainRouter.route().handler(sessionHandler);
// 拦截器
Set<Handler<RoutingContext>> interceptorSet = getInterceptorSet();
Route route0 = mainRouter.route("/*");
interceptorSet.forEach(route0::handler);
try {
Set<Class<?>> handlers = reflections.getTypesAnnotatedWith(RouteHandler.class);
@@ -101,7 +127,7 @@ public class RouterHandlerFactory implements BaseHttpApi {
for (Class<?> handler : sortedHandlers) {
try {
// 注册请求处理方法
registerNewHandler(router, handler);
registerNewHandler(mainRouter, handler);
} catch (Throwable e) {
LOGGER.error("Error register {}, Error details:", handler, e.getCause());
@@ -111,11 +137,12 @@ public class RouterHandlerFactory implements BaseHttpApi {
LOGGER.error("Manually Register Handler Fail, Error details:" + e.getMessage());
}
// 错误请求处理
router.errorHandler(405, ctx -> fireJsonResponse(ctx, JsonResult
mainRouter.errorHandler(405, ctx -> doFireJsonResultResponse(ctx, JsonResult
.error("Method Not Allowed", 405)));
router.errorHandler(404, ctx -> ctx.response().setStatusCode(404).setChunked(true)
mainRouter.errorHandler(404, ctx -> ctx.response().setStatusCode(404).setChunked(true)
.end("Internal server error: 404 not found"));
return router;
return mainRouter;
}
/**
@@ -139,15 +166,13 @@ public class RouterHandlerFactory implements BaseHttpApi {
method -> method.isAnnotationPresent(SockRouteMapper.class)
).toList());
// 拦截器
Handler<RoutingContext> interceptor = getInterceptor();
// 依次注册处理方法
for (Method method : methodList) {
if (method.isAnnotationPresent(RouteMapping.class)) {
// 普通路由
RouteMapping mapping = method.getAnnotation(RouteMapping.class);
HttpMethod routeMethod = HttpMethod.valueOf(mapping.method().name());
String routeUrl = getRouteUrl(method.getName(), mapping.value());
String routeUrl = getRouteUrl(mapping.value());
String url = root.concat(routeUrl);
// 匹配方法
Route route = router.route(routeMethod, url);
@@ -157,17 +182,23 @@ public class RouterHandlerFactory implements BaseHttpApi {
route.consumes(mineType);
}
// 先执行拦截方法, 再进入业务请求
route.handler(interceptor);
// 设置默认超时
route.handler(TimeoutHandler.create(SharedDataUtil.getCustomConfig().getInteger(ROUTE_TIME_OUT)));
route.handler(ResponseTimeHandler.create());
route.handler(ctx -> handlerMethod(instance, method, ctx)).failureHandler(ctx -> {
if (ctx.response().ended()) return;
// 超时处理器状态码503
if (ctx.statusCode() == 503 || ctx.failure() == null) {
doFireJsonResultResponse(ctx, JsonResult.error("未知异常, 请联系管理员", 500));
} else {
ctx.failure().printStackTrace();
fireJsonResponse(ctx, JsonResult.error(ctx.failure().getMessage(), 500));
doFireJsonResultResponse(ctx, JsonResult.error(ctx.failure().getMessage(), 500));
}
});
} else if (method.isAnnotationPresent(SockRouteMapper.class)) {
// websocket 基于sockJs
SockRouteMapper mapping = method.getAnnotation(SockRouteMapper.class);
String routeUrl = getRouteUrl(method.getName(), mapping.value());
String routeUrl = getRouteUrl(mapping.value());
String url = root.concat(routeUrl);
LOGGER.info("Register New Websocket Handler -> {}", url);
SockJSHandlerOptions options = new SockJSHandlerOptions()
@@ -194,13 +225,12 @@ public class RouterHandlerFactory implements BaseHttpApi {
/**
* 获取并处理路由URL分隔符
*
* @param methodName 路由method
* @return String
*/
private String getRouteUrl(String methodName, String mapperValue) {
private String getRouteUrl(String mapperValue) {
String routeUrl;
if (mapperValue.startsWith("/:") || "/".equals(mapperValue)) {
routeUrl = (methodName + mapperValue);
if ("/".equals(mapperValue)) {
routeUrl = mapperValue;
} else if (mapperValue.startsWith("/")) {
routeUrl = mapperValue.substring(1);
} else {
@@ -213,15 +243,10 @@ public class RouterHandlerFactory implements BaseHttpApi {
* 配置拦截
*
* @return Handler
* @throws Throwable Throwable
*/
private Handler<RoutingContext> getInterceptor() throws Throwable {
private Set<Handler<RoutingContext>> getInterceptorSet() {
// 配置拦截
Class<?> interceptorClass = Class.forName(SharedDataUtil.getValueForCustomConfig("interceptorClassPath"));
Object handleInstance = ReflectionUtil.newWithNoParam(interceptorClass);
Method doHandle = interceptorClass.getMethod("doHandle");
// 反射调用
return CastUtil.cast(ReflectionUtil.invoke(doHandle, handleInstance));
return getBeforeInterceptor().stream().map(BeforeInterceptor::doHandle).collect(Collectors.toSet());
}
/**
@@ -243,7 +268,7 @@ public class RouterHandlerFactory implements BaseHttpApi {
if (handler.isAnnotationPresent(RouteHandler.class)) {
RouteHandler routeHandler = handler.getAnnotation(RouteHandler.class);
String value = routeHandler.value();
root += ("/".equals(value) ? "" : value);
root += (value.startsWith("/") ? value.substring(1) : value);
}
if (!root.endsWith("/")) {
root = root + "/";
@@ -286,37 +311,15 @@ public class RouterHandlerFactory implements BaseHttpApi {
});
}
final MultiMap queryParams = ctx.queryParams();
if ("POST".equals(ctx.request().method().name())) {
queryParams.addAll(ctx.request().params());
}
JsonArray entityPackagesReg = SharedDataUtil.getJsonArrayForCustomConfig("entityPackagesReg");
// 绑定get或post请求头的请求参数
methodParametersTemp.forEach((k, v) -> {
if (ReflectionUtil.isBasicType(v.getRight())) {
String fmt = getFmt(v.getLeft(), v.getRight());
String value = queryParams.get(k);
parameterValueList.put(k, ReflectionUtil.conversion(v.getRight(), value, fmt));
} else if (RoutingContext.class.getName().equals(v.getRight().getName())) {
parameterValueList.put(k, ctx);
} else if (HttpServerRequest.class.getName().equals(v.getRight().getName())) {
parameterValueList.put(k, ctx.request());
} else if (HttpServerResponse.class.getName().equals(v.getRight().getName())) {
parameterValueList.put(k, ctx.response());
} else if (CommonUtil.matchRegList(entityPackagesReg.getList(), v.getRight().getName())) {
// 绑定实体类
try {
Class<?> aClass = Class.forName(v.getRight().getName());
Object entity = ParamUtil.multiMapToEntity(queryParams, aClass);
parameterValueList.put(k, entity);
} catch (Exception e) {
e.printStackTrace();
}
}
});
final MultiMap queryParams = ctx.queryParams();
// 解析body-json参数
if ("application/json".equals(ctx.parsedHeaders().contentType().value()) && ctx.body().asJsonObject() != null) {
// 只处理POST/PUT/PATCH等有body的请求方法,避免GET请求读取body导致"Request has already been read"错误
String httpMethod = ctx.request().method().name();
if (("POST".equals(httpMethod) || "PUT".equals(httpMethod) || "PATCH".equals(httpMethod))
&& HttpHeaderValues.APPLICATION_JSON.toString().equals(ctx.parsedHeaders().contentType().value())
&& ctx.body() != null && ctx.body().asJsonObject() != null) {
JsonObject body = ctx.body().asJsonObject();
if (body != null) {
methodParametersTemp.forEach((k, v) -> {
@@ -336,26 +339,67 @@ public class RouterHandlerFactory implements BaseHttpApi {
}
});
}
} else if (("POST".equals(httpMethod) || "PUT".equals(httpMethod) || "PATCH".equals(httpMethod))
&& ctx.body() != null) {
queryParams.addAll(ParamUtil.paramsToMap(ctx.body().asString()));
}
// 解析其他参数
if ("POST".equals(ctx.request().method().name())) {
queryParams.addAll(ctx.request().params());
}
// 绑定get或post请求头的请求参数
methodParametersTemp.forEach((k, v) -> {
if (ReflectionUtil.isBasicType(v.getRight())) {
String fmt = getFmt(v.getLeft(), v.getRight());
String value = queryParams.get(k);
parameterValueList.put(k, ReflectionUtil.conversion(v.getRight(), value, fmt));
} else if (RoutingContext.class.getName().equals(v.getRight().getName())) {
parameterValueList.put(k, ctx);
} else if (HttpServerRequest.class.getName().equals(v.getRight().getName())) {
parameterValueList.put(k, ctx.request());
} else if (HttpServerResponse.class.getName().equals(v.getRight().getName())) {
parameterValueList.put(k, ctx.response());
} else if (parameterValueList.get(k) == null
&& CommonUtil.matchRegList(entityPackagesReg.getList(), v.getRight().getName())) {
// 绑定实体类
try {
Class<?> aClass = Class.forName(v.getRight().getName());
Object entity = ParamUtil.multiMapToEntity(queryParams, aClass);
parameterValueList.put(k, entity);
} catch (Exception e) {
e.printStackTrace();
}
}
});
// 调用handle 获取响应对象
Object[] parameterValueArray = parameterValueList.values().toArray(new Object[0]);
try {
// 反射调用
Object data = ReflectionUtil.invokeWithArguments(method, instance, parameterValueArray);
if (data != null) {
if (data instanceof JsonResult) {
fireJsonResponse(ctx, data);
doFireJsonResultResponse(ctx, (JsonResult<?>) data);
}
if (data instanceof JsonObject) {
doFireJsonObjectResponse(ctx, ((JsonObject) data));
} else if (data instanceof Future) { // 处理异步响应
((Future<?>) data).onSuccess(res -> {
if (res instanceof JsonObject) {
fireJsonResponse(ctx, res);
} else if (res != null){
fireJsonResponse(ctx, JsonResult.data(res));
if (res instanceof JsonResult) {
doFireJsonResultResponse(ctx, (JsonResult<?>) res);
}
}).onFailure(e -> fireJsonResponse(ctx, JsonResult.error(e.getMessage())));
if (res instanceof JsonObject) {
doFireJsonObjectResponse(ctx, ((JsonObject) res));
} else if (res != null) {
doFireJsonResultResponse(ctx, JsonResult.data(res));
} else {
ctx.response().headers().set(CONTENT_TYPE, MIMEType.TEXT_HTML.getValue());
ctx.end(data.toString());
handleAfterInterceptor(ctx, null);
}
}).onFailure(e -> doFireJsonResultResponse(ctx, JsonResult.error(e.getMessage())));
} else {
doFireJsonResultResponse(ctx, JsonResult.data(data));
}
}
} catch (Throwable e) {
@@ -363,12 +407,12 @@ public class RouterHandlerFactory implements BaseHttpApi {
String err = e.getMessage();
if (e.getCause() != null) {
if (e.getCause() instanceof InvocationTargetException) {
err = ((InvocationTargetException)e.getCause()).getTargetException().getMessage();
err = ((InvocationTargetException) e.getCause()).getTargetException().getMessage();
} else {
err = e.getCause().getMessage();
}
}
fireJsonResponse(ctx, JsonResult.error(err));
doFireJsonResultResponse(ctx, JsonResult.error(err));
}
}
@@ -386,4 +430,13 @@ public class RouterHandlerFactory implements BaseHttpApi {
}
return fmt;
}
private Set<BeforeInterceptor> getBeforeInterceptor() {
Set<Class<? extends BeforeInterceptor>> interceptorClassSet =
reflections.getSubTypesOf(BeforeInterceptor.class);
if (interceptorClassSet == null) {
return new HashSet<>();
}
return CommonUtil.sortClassSet(interceptorClassSet);
}
}
@@ -0,0 +1,15 @@
package cn.qaiu.vx.core.interceptor;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
/**
* 后置拦截器接口
*
* @author <a href="https://qaiu.top">QAIU</a>
*/
public interface AfterInterceptor {
void handle(RoutingContext ctx, JsonObject responseData);
}
@@ -0,0 +1,41 @@
package cn.qaiu.vx.core.interceptor;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
import static cn.qaiu.vx.core.util.ResponseUtil.sendError;
/**
* 前置拦截器接口
*
* @author <a href="https://qaiu.top">QAIU</a>
*/
public interface BeforeInterceptor extends Handler<RoutingContext> {
String IS_NEXT = "RoutingContextIsNext";
default Handler<RoutingContext> doHandle() {
return ctx -> {
// 加同步锁
synchronized (BeforeInterceptor.class) {
ctx.put(IS_NEXT, false);
BeforeInterceptor.this.handle(ctx);
if (!(Boolean) ctx.get(IS_NEXT) && !ctx.response().ended()) {
sendError(ctx, 403);
}
}
};
}
default void doNext(RoutingContext context) {
// 设置上下文状态为可以继续执行
// 添加同步锁保障多线程下执行时序
synchronized (BeforeInterceptor.class) {
context.put(IS_NEXT, true);
context.next();
}
}
void handle(RoutingContext context);
}
@@ -1,19 +0,0 @@
package cn.qaiu.vx.core.interceptor;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
/**
* 拦截器接口
* <br>Create date 2021-05-06 09:20:37
*
* @author <a href="https://qaiu.top">QAIU</a>
*/
public interface Interceptor {
default Handler<RoutingContext> doHandle() {
return this::handle;
}
void handle(RoutingContext context);
}
@@ -1,8 +1,12 @@
package cn.qaiu.vx.core.model;
import cn.qaiu.vx.core.util.CastUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.vertx.core.json.JsonObject;
import org.apache.commons.lang3.StringUtils;
import java.io.Serial;
import java.io.Serializable;
/**
@@ -13,6 +17,7 @@ import java.io.Serializable;
*/
public class JsonResult<T> implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private static final int SUCCESS_CODE = 200;
@@ -25,12 +30,10 @@ public class JsonResult<T> implements Serializable {
private int code = SUCCESS_CODE;//状态码
private String msg = SUCCESS_MESSAGE;//消息
private String msg = SUCCESS_MESSAGE; //消息
private boolean success = true; //是否成功
private int count;
private T data;
private long timestamp = System.currentTimeMillis(); //时间戳
@@ -49,20 +52,6 @@ public class JsonResult<T> implements Serializable {
this.success = success;
}
public JsonResult(int code, String msg, boolean success, T data, int count) {
this(code, msg, success, data);
this.count = count;
}
public int getCount() {
return count;
}
public JsonResult<T> setCount(int count) {
this.count = count;
return this;
}
public int getCode() {
return code;
}
@@ -131,20 +120,9 @@ public class JsonResult<T> implements Serializable {
return new JsonResult<>(SUCCESS_CODE, msg, true, data);
}
// 响应成功消息和数据实体
public static <T> JsonResult<T> data(String msg, T data, int count) {
if (StringUtils.isEmpty(msg)) msg = SUCCESS_MESSAGE;
return new JsonResult<>(SUCCESS_CODE, msg, true, data, count);
}
// 响应数据实体
public static <T> JsonResult<T> data(T data) {
return new JsonResult<>(SUCCESS_CODE, SUCCESS_MESSAGE, true, data, 0);
}
// 响应数据实体
public static <T> JsonResult<T> data(T data, int count) {
return new JsonResult<>(SUCCESS_CODE, SUCCESS_MESSAGE, true, data, count);
return new JsonResult<>(SUCCESS_CODE, SUCCESS_MESSAGE, true, data);
}
// 响应成功消息
@@ -157,4 +135,16 @@ public class JsonResult<T> implements Serializable {
public static <T> JsonResult<T> success() {
return new JsonResult<>(SUCCESS_CODE, SUCCESS_MESSAGE, true, null);
}
// 转为json对象
public JsonObject toJsonObject() {
return JsonObject.mapFrom(this);
}
private static final ObjectMapper mapper = new ObjectMapper();
// 转为json对象
public static JsonResult<?> toJsonResult(JsonObject json) {
return CastUtil.cast(json.mapTo(JsonResult.class));
}
}
@@ -0,0 +1,7 @@
/**
* ModuleGen cn.qaiu.vx.core
*/
@ModuleGen(name = "vertx-http-proxy", groupPackage = "cn.qaiu.vx.core", useFutures = true)
package cn.qaiu.vx.core;
import io.vertx.codegen.annotations.ModuleGen;
@@ -5,7 +5,7 @@ import io.vertx.serviceproxy.ServiceProxyBuilder;
/**
* @author Xu Haidong
* @date 2018/8/15
* Create at 2018/8/15
*/
public final class AsyncServiceUtil {
@@ -1,9 +1,8 @@
package cn.qaiu.vx.core.util;
import cn.qaiu.vx.core.annotaions.HandleSortFilter;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.json.JsonObject;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -15,6 +14,9 @@ import java.net.URL;
import java.net.UnknownHostException;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;
/**
* CommonUtil
@@ -70,10 +72,11 @@ public class CommonUtil {
} catch (UnknownHostException e) {
return false;
}
try(Socket ignored = new Socket(Address, port)) {
try (Socket ignored = new Socket(Address, port)) {
//建立一个Socket连接
flag = true;
} catch (IOException ignoredException) {}
} catch (IOException ignoredException) {
}
return flag;
}
@@ -95,23 +98,6 @@ public class CommonUtil {
return data;
}
/**
* 注册枚举转换器
*
* @param enums 枚举类
*/
@SafeVarargs
@SuppressWarnings({"unchecked", "rawtypes"})
public static void enumConvert(Class<? extends Enum>... enums) {
for (Class<? extends Enum> anEnum : enums) {
ConvertUtils.register(new Converter() {
public Object convert(Class type, Object value) {
return Enum.valueOf(anEnum, (String) value);
}
}, anEnum);
}
}
/**
* 处理其他配置
*
@@ -126,4 +112,49 @@ public class CommonUtil {
LocalConstant.put(configName, map);
LOGGER.info("读取配置{}成功", configName);
}
public static <T> Set<T> sortClassSet(Set<Class<? extends T>> set) {
return set.stream().filter(c1 -> {
HandleSortFilter s1 = c1.getAnnotation(HandleSortFilter.class);
if (s1 != null) {
return s1.value() > 0;
} else {
return true;
}
}).sorted((c1, c2) -> {
HandleSortFilter s1 = c1.getAnnotation(HandleSortFilter.class);
HandleSortFilter s2 = c2.getAnnotation(HandleSortFilter.class);
int n1 = 0, n2 = 0;
if (s1 != null) {
n1 = s1.value();
}
if (s2 != null) {
n2 = s2.value();
}
return n1 - n2;
}).map(c -> {
try {
return ReflectionUtil.newWithNoParam(c);
} catch (Exception e) {
throw new RuntimeException(e);
}
}).collect(Collectors.toSet());
}
private static String appVersion;
public static String getAppVersion() {
if (null == appVersion) {
Properties properties = new Properties();
try {
properties.load(CommonUtil.class.getClassLoader().getResourceAsStream("app.properties"));
if (!properties.isEmpty()) {
appVersion = properties.getProperty("app.version") + "build" + properties.getProperty("build");
}
} catch (IOException e) {
e.printStackTrace();
}
}
return appVersion;
}
}
@@ -3,9 +3,21 @@ package cn.qaiu.vx.core.util;
public interface ConfigConstant {
String CUSTOM = "custom";
String VERTX = "vertx";
String EVENT_LOOP_POOL_SIZE = "eventLoopPoolSize";
String LOCAL = "local";
String SERVER = "server";
String CACHE = "cache";
String PROXY_SERVER = "proxy-server";
String PROXY = "proxy";
String AUTHS = "auths";
String GLOBAL_CONFIG = "globalConfig";
String CUSTOM_CONFIG = "customConfig";
String ASYNC_SERVICE_INSTANCES = "asyncServiceInstances";
String IGNORES_REG="ignoresReg";
String BASE_LOCATIONS="baseLocations";
String ROUTE_TIME_OUT="routeTimeOut";
}
@@ -0,0 +1,46 @@
package cn.qaiu.vx.core.util;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import io.vertx.core.json.jackson.DatabindCodec;
import org.slf4j.LoggerFactory;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
/**
* @author <a href="https://qaiu.top">QAIU</a>
* Create at 2023/10/14 9:07
*/
public class JacksonConfig {
static {
// 通过该方法对mapper对象进行设置,所有序列化的对象都将按改规则进行系列化
// Include.Include.ALWAYS 默认
// Include.NON_DEFAULT 属性为默认值不序列化
// Include.NON_EMPTY 属性为 空("") 或者为 NULL 都不序列化,则返回的json是没有这个字段的。这样对移动端会更省流量
// Include.NON_NULL 属性为NULL 不序列化,就是为null的字段不参加序列化
// objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
ObjectMapper objectMapper = DatabindCodec.mapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addDeserializer(LocalDateTime.class,
new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
javaTimeModule.addDeserializer(LocalDate.class,
new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
javaTimeModule.addDeserializer(LocalTime.class,
new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
objectMapper.registerModule(javaTimeModule);
LoggerFactory.getLogger(JacksonConfig.class).info("Global JacksonConfig complete.");
}
public static void nothing() {}
}
@@ -1,11 +1,10 @@
package cn.qaiu.vx.core.util;
import io.vertx.core.MultiMap;
import org.apache.commons.beanutils.BeanUtils;
import io.vertx.core.json.JsonObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
@@ -18,28 +17,37 @@ import java.util.Map;
public final class ParamUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(ParamUtil.class);
public static Map<String, String> multiMapToMap(MultiMap multiMap) {
public static Map<String, Object> multiMapToMap(MultiMap multiMap) {
if (multiMap == null) return null;
Map<String, String> map = new HashMap<>();
Map<String, Object> map = new HashMap<>();
for (Map.Entry<String, String> entry : multiMap.entries()) {
map.put(entry.getKey(), entry.getValue());
}
return map;
}
public static <T> T multiMapToEntity(MultiMap multiMap,Class<T> tClass) throws NoSuchMethodException {
Map<String,String> map = multiMapToMap(multiMap);
T obj = null;
try {
obj = tClass.getDeclaredConstructor().newInstance();
BeanUtils.populate(obj,map);
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
LOGGER.error("实例化异常");
} catch (InvocationTargetException e2) {
e2.printStackTrace();
LOGGER.error("map2bean转换异常");
public static <T> T multiMapToEntity(MultiMap multiMap, Class<T> tClass) {
Map<String, Object> map = multiMapToMap(multiMap);
if (map == null) {
return null;
}
return obj;
return new JsonObject(map).mapTo(tClass);
}
public static MultiMap paramsToMap(String paramString) {
MultiMap entries = MultiMap.caseInsensitiveMultiMap();
if (paramString == null) return entries;
String[] params = paramString.split("&");
if (params.length == 0) return entries;
for (String param : params) {
String[] kv = param.split("=");
if (kv.length == 2) {
entries.set(kv[0], kv[1]);
} else {
entries.set(kv[0], "");
}
}
return entries;
}
}
@@ -5,12 +5,13 @@ import javassist.bytecode.AccessFlag;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.LocalVariableAttribute;
import javassist.bytecode.MethodInfo;
import org.apache.commons.beanutils.ConversionException;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.reflections.Reflections;
import org.reflections.scanners.*;
import org.reflections.scanners.MemberUsageScanner;
import org.reflections.scanners.MethodParameterNamesScanner;
import org.reflections.scanners.Scanners;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import org.reflections.util.FilterBuilder;
@@ -24,6 +25,8 @@ import java.net.URL;
import java.text.ParseException;
import java.util.*;
import static cn.qaiu.vx.core.util.ConfigConstant.BASE_LOCATIONS;
/**
* 基于org.reflection和javassist的反射工具包
* 通过包扫描实现路由地址的注解映射
@@ -33,6 +36,16 @@ import java.util.*;
*/
public final class ReflectionUtil {
/**
* 以默认配置的基础包路径获取反射器
*
* @return Reflections object
*/
public static Reflections getReflections() {
return getReflections(SharedDataUtil.getStringForCustomConfig(BASE_LOCATIONS));
}
/**
* 获取反射器
*
@@ -48,6 +61,7 @@ public final class ReflectionUtil {
} else {
packageAddressList = Collections.singletonList(packageAddress);
}
return getReflections(packageAddressList);
}
@@ -70,11 +84,12 @@ public final class ReflectionUtil {
// 发现注解api层 没有继承父类时 这里反射一直有问题(Scanner SubTypesScanner was not configured)
// 因此这里需要手动配置各种Scanner扫描器 -- https://blog.csdn.net/qq_29499107/article/details/106889781
configurationBuilder.setScanners(
new SubTypesScanner(false), //允许getAllTypes获取所有Object的子类, 不设置为false则 getAllTypes 会报错.默认为true.
Scanners.SubTypes.filterResultsBy(s -> true), //允许getAllTypes获取所有Object的子类, 不设置为false则 getAllTypes
// 会报错.默认为true.
new MethodParameterNamesScanner(), //设置方法参数名称 扫描器,否则调用getConstructorParamNames 会报错
new MethodAnnotationsScanner(), //设置方法注解 扫描器, 否则getConstructorsAnnotatedWith,getMethodsAnnotatedWith 会报错
new MemberUsageScanner(), //设置 member 扫描器,否则 getMethodUsage 会报错, 不推荐使用,有可能会报错 Caused by: java.lang.ClassCastException: javassist.bytecode.InterfaceMethodrefInfo cannot be cast to javassist.bytecode.MethodrefInfo
new TypeAnnotationsScanner() //设置类注解 扫描器 ,否则 getTypesAnnotatedWith 会报错
Scanners.MethodsAnnotated, //设置方法注解 扫描器, 否则getConstructorsAnnotatedWith,getMethodsAnnotatedWith 会报错
new MemberUsageScanner(), //设置 member 扫描器,否则 getMethodUsage 会报错
Scanners.TypesAnnotated //设置类注解 扫描器 ,否则 getTypesAnnotatedWith 会报错
);
configurationBuilder.filterInputsBy(filterBuilder);
@@ -98,7 +113,8 @@ public final class ReflectionUtil {
MethodInfo methodInfo = cm.getMethodInfo();
CtClass[] parameterTypes = cm.getParameterTypes();
CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
LocalVariableAttribute attr =
(LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
boolean flag = true;
boolean flag2 = cm.getModifiers() - 1 != AccessFlag.STATIC;
@@ -110,7 +126,8 @@ public final class ReflectionUtil {
continue;
}
flag = false;
paramMap.put(attr.variableName(j + (flag2 ? 1 : 0)), Pair.of(parameterAnnotations[j - k], parameterTypes[j - k]));
paramMap.put(attr.variableName(j + (flag2 ? 1 : 0)), Pair.of(parameterAnnotations[j - k],
parameterTypes[j - k]));
}
} catch (NotFoundException e) {
e.printStackTrace();
@@ -169,10 +186,10 @@ public final class ReflectionUtil {
return DateUtils.parseDate(value, fmt);
} catch (ParseException e) {
e.printStackTrace();
throw new ConversionException("无法将格式化日期");
throw new RuntimeException("无法将格式化日期");
}
default:
throw new ConversionException("无法将String类型" + value + "转为[" + name + "]");
throw new RuntimeException("无法将String类型" + value + "转为[" + name + "]");
}
}
@@ -184,7 +201,7 @@ public final class ReflectionUtil {
* @return Array
*/
public static Object conversionArray(CtClass ctClass, String value) {
if (!isBasicTypeArray(ctClass)) throw new ConversionException("无法解析数组");
if (!isBasicTypeArray(ctClass)) throw new RuntimeException("无法解析数组");
String[] strArr = value.split(",");
List<Object> obj = new ArrayList<>();
Arrays.stream(strArr).forEach(v -> obj.add(conversion(ctClass, v, null)));
@@ -214,7 +231,8 @@ public final class ReflectionUtil {
if (ctClass.isPrimitive() || "java.util.Date".equals(ctClass.getName())) {
return true;
}
return ctClass.getName().matches("^java\\.lang\\.((Boolean)|(Character)|(Byte)|(Short)|(Integer)|(Long)|(Float)|(Double)|(String))$");
return ctClass.getName().matches("^java\\.lang\\.((Boolean)|(Character)|(Byte)|(Short)|(Integer)|(Long)|" +
"(Float)|(Double)|(String))$");
}
/**
@@ -238,7 +256,8 @@ public final class ReflectionUtil {
* @throws InstantiationException InstantiationException
* @throws IllegalAccessException IllegalAccessException
*/
public static <T> T newWithNoParam(Class<T> handler) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
public static <T> T newWithNoParam(Class<T> handler) throws NoSuchMethodException, InvocationTargetException,
InstantiationException, IllegalAccessException {
return handler.getConstructor().newInstance();
}
@@ -0,0 +1,51 @@
package cn.qaiu.vx.core.util;
import cn.qaiu.vx.core.model.JsonResult;
import io.vertx.core.Promise;
import io.vertx.core.http.HttpHeaders;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE;
public class ResponseUtil {
public static void redirect(HttpServerResponse response, String url) {
response.putHeader(CONTENT_TYPE, "text/html; charset=utf-8")
.putHeader(HttpHeaders.LOCATION, url).setStatusCode(302).end();
}
public static void redirect(HttpServerResponse response, String url, Promise<?> promise) {
redirect(response, url);
promise.complete();
}
public static void fireJsonObjectResponse(RoutingContext ctx, JsonObject jsonObject) {
ctx.response().putHeader(CONTENT_TYPE, "application/json; charset=utf-8")
.setStatusCode(200)
.end(jsonObject.encode());
}
public static void fireJsonObjectResponse(HttpServerResponse ctx, JsonObject jsonObject) {
ctx.putHeader(CONTENT_TYPE, "application/json; charset=utf-8")
.setStatusCode(200)
.end(jsonObject.encode());
}
public static <T> void fireJsonResultResponse(RoutingContext ctx, JsonResult<T> jsonResult) {
fireJsonObjectResponse(ctx, jsonResult.toJsonObject());
}
public static <T> void fireJsonResultResponse(HttpServerResponse ctx, JsonResult<T> jsonResult) {
fireJsonObjectResponse(ctx, jsonResult.toJsonObject());
}
public static void fireTextResponse(RoutingContext ctx, String text) {
ctx.response().putHeader(CONTENT_TYPE, "text/html; charset=utf-8").end(text);
}
public static void sendError(RoutingContext ctx, int statusCode) {
ctx.response().setStatusCode(statusCode).end();
}
}
@@ -32,11 +32,11 @@ public class SharedDataUtil {
return (JsonObject) localMap.get(key);
}
public static JsonObject getJsonObjectForCustomConfig(String key) {
return getJsonConfig("customConfig").getJsonObject(key);
public static JsonObject getCustomConfig() {
return getJsonConfig("customConfig");
}
public static String getJsonStringForCustomConfig(String key) {
public static String getStringForCustomConfig(String key) {
return getJsonConfig("customConfig").getString(key);
}
@@ -0,0 +1,184 @@
package cn.qaiu.vx.core.verticle;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions;
import io.vertx.core.dns.AddressResolverOptions;
import io.vertx.core.http.*;
import io.vertx.core.net.NetClient;
import io.vertx.core.net.NetClientOptions;
import io.vertx.core.net.NetSocket;
import io.vertx.core.net.ProxyOptions;
import java.util.Base64;
/**
*
*/
public class HttpProxyVerticle extends AbstractVerticle {
private HttpClient httpClient;
private NetClient netClient;
@Override
public void start() {
ProxyOptions proxyOptions = new ProxyOptions().setHost("127.0.0.1").setPort(7890);
// 初始化 HTTP 客户端,用于向目标服务器发送 HTTP 请求
HttpClientOptions httpClientOptions = new HttpClientOptions();
httpClient = vertx.createHttpClient(httpClientOptions.setProxyOptions(proxyOptions));
// 创建并启动 HTTP 代理服务器,监听指定端口
HttpServer server = vertx.createHttpServer(new HttpServerOptions().setClientAuth(ClientAuth.REQUIRED));
server.requestHandler(this::handleClientRequest);
// 初始化 NetClient,用于在 CONNECT 请求中建立 TCP 连接隧道
netClient = vertx.createNetClient(new NetClientOptions()
.setProxyOptions(proxyOptions)
.setConnectTimeout(15000)
.setTrustAll(true));
// 启动 HTTP 代理服务器
server.listen(7891, ar -> {
if (ar.succeeded()) {
System.out.println("HTTP Proxy server started on port 7891");
} else {
System.err.println("Failed to start HTTP Proxy server: " + ar.cause());
}
});
}
// 处理 HTTP CONNECT 请求,用于代理 HTTPS 流量
private void handleConnectRequest(HttpServerRequest clientRequest) {
String[] uriParts = clientRequest.uri().split(":");
if (uriParts.length != 2) {
clientRequest.response().setStatusCode(400).end("Bad Request: Invalid URI format");
return;
}
// 解析目标主机和端口
String targetHost = uriParts[0];
int targetPort;
try {
targetPort = Integer.parseInt(uriParts[1]);
} catch (NumberFormatException e) {
clientRequest.response().setStatusCode(400).end("Bad Request: Invalid port");
return;
}
clientRequest.pause();
// 通过 NetClient 连接目标服务器并创建隧道
netClient.connect(targetPort, targetHost, connectionAttempt -> {
if (connectionAttempt.succeeded()) {
NetSocket targetSocket = connectionAttempt.result();
// 升级客户端连接到 NetSocket 并实现双向数据流
clientRequest.toNetSocket().onComplete(clientSocketAttempt -> {
if (clientSocketAttempt.succeeded()) {
NetSocket clientSocket = clientSocketAttempt.result();
// 设置双向数据流转发
clientSocket.handler(targetSocket::write);
targetSocket.handler(clientSocket::write);
// 关闭其中一方时关闭另一方
clientSocket.closeHandler(v -> targetSocket.close());
targetSocket.closeHandler(v -> clientSocket.close());
} else {
System.err.println("Failed to upgrade client connection to socket: " + clientSocketAttempt.cause().getMessage());
targetSocket.close();
clientRequest.response().setStatusCode(500).end("Internal Server Error");
}
});
} else {
System.err.println("Failed to connect to target: " + connectionAttempt.cause().getMessage());
clientRequest.response().setStatusCode(502).end("Bad Gateway: Unable to connect to target");
}
});
}
// 处理客户端的 HTTP 请求
private void handleClientRequest(HttpServerRequest clientRequest) {
String s = clientRequest.headers().get("Proxy-Authorization");
if (s == null) {
clientRequest.response().setStatusCode(403).end();
return;
}
String[] split = new String(Base64.getDecoder().decode(s.replace("Basic ", ""))).split(":");
if (split.length > 1) {
System.out.println(split[0]);
System.out.println(split[1]);
// TODO
}
if (clientRequest.method() == HttpMethod.CONNECT) {
// 处理 CONNECT 请求
handleConnectRequest(clientRequest);
} else {
// 处理普通的 HTTP 请求
handleHttpRequest(clientRequest);
}
}
// 处理 HTTP 请求,转发至目标服务器并返回响应
private void handleHttpRequest(HttpServerRequest clientRequest) {
// 获取目标主机
String hostHeader = clientRequest.getHeader("Host");
if (hostHeader == null) {
clientRequest.response().setStatusCode(400).end("Host header is missing");
return;
}
String targetHost = hostHeader.split(":")[0];
int targetPort = 80; // 默认为 HTTP 的端口
clientRequest.pause(); // 暂停客户端请求的读取,避免数据丢失
httpClient.request(clientRequest.method(), targetPort, targetHost, clientRequest.uri())
.onSuccess(request -> {
clientRequest.resume(); // 恢复客户端请求的读取
// 逐个设置请求头
clientRequest.headers().forEach(header -> request.putHeader(header.getKey(), header.getValue()));
// 将客户端请求的 body 转发给目标服务器
clientRequest.bodyHandler(body -> request.send(body, ar -> {
if (ar.succeeded()) {
var response = ar.result();
clientRequest.response().setStatusCode(response.statusCode());
clientRequest.response().headers().setAll(response.headers());
response.body().onSuccess(b-> clientRequest.response().end(b));
} else {
clientRequest.response().setStatusCode(502).end("Bad Gateway: Unable to reach target");
}
}));
})
.onFailure(err -> {
err.printStackTrace();
clientRequest.response().setStatusCode(502).end("Bad Gateway: Request failed");
});
}
@Override
public void stop() {
// 停止 HTTP 客户端以释放资源
if (httpClient != null) {
httpClient.close();
}
}
/**
* TODO add Deploy
* @param args
*/
public static void main(String[] args) {
// 配置 DNS 解析器,使用多个 DNS 服务器来提升解析速度
Vertx vertx = Vertx.vertx(new VertxOptions()
.setAddressResolverOptions(new AddressResolverOptions()
.addServer("114.114.114.114")
.addServer("114.114.115.115")
.addServer("8.8.8.8")
.addServer("8.8.4.4")));
// 部署 Verticle 并启动动态 HTTP 代理服务器
vertx.deployVerticle(new HttpProxyVerticle());
}
}
@@ -6,13 +6,13 @@ import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.WebSocket;
import io.vertx.core.http.HttpServerOptions;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.core.net.PemKeyCertOptions;
import io.vertx.ext.web.Route;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.handler.StaticHandler;
import io.vertx.ext.web.handler.sockjs.SockJSHandler;
import io.vertx.ext.web.handler.sockjs.SockJSHandlerOptions;
import io.vertx.ext.web.proxy.handler.ProxyHandler;
import io.vertx.httpproxy.HttpProxy;
import org.apache.commons.lang3.StringUtils;
@@ -40,14 +40,17 @@ public class ReverseProxyVerticle extends AbstractVerticle {
.getJsonConfig(ConfigConstant.GLOBAL_CONFIG)
.getString("proxyConf");
private static final Future<JsonObject> CONFIG = ConfigUtil.readYamlConfig(PATH_PROXY_CONFIG);
private static final String DEFAULT_PATH_404 = "webroot/err/404.html";
private static final String DEFAULT_PATH_404 = "webroot/err/page404.html";
private static String serverName = "Vert.x-proxy-server"; //Server name in Http response header
public static String REROUTE_PATH_PREFIX = "/__rrvpspp"; //re_route_vert_proxy_server_path_prefix 硬编码
@Override
public void start(Promise<Void> startPromise) throws Exception {
public void start(Promise<Void> startPromise) {
CONFIG.onSuccess(this::handleProxyConfList);
// createFileListener
startPromise.complete();
}
@@ -74,22 +77,24 @@ public class ReverseProxyVerticle extends AbstractVerticle {
* @param proxyConf 代理配置
*/
private void handleProxyConf(JsonObject proxyConf) {
// 404 path
if (proxyConf.containsKey("404")) {
// page404 path
if (proxyConf.containsKey(
"page404")) {
System.getProperty("user.dir");
String path = proxyConf.getString("404");
String path = proxyConf.getString("page404");
if (StringUtils.isEmpty(path)) {
proxyConf.put("404", DEFAULT_PATH_404);
proxyConf.put("page404", DEFAULT_PATH_404);
} else {
if (!path.startsWith("/")) {
path = "/" + path;
}
if (!new File(System.getProperty("user.dir") + path).exists()) {
proxyConf.put("404", DEFAULT_PATH_404);
proxyConf.put("page404", DEFAULT_PATH_404);
}
}
} else {
proxyConf.put("404", DEFAULT_PATH_404);
proxyConf.put("page404", DEFAULT_PATH_404);
}
final HttpClient httpClient = VertxHolder.getVertxInstance().createHttpClient();
@@ -111,17 +116,10 @@ public class ReverseProxyVerticle extends AbstractVerticle {
handleStatic(proxyConf.getJsonObject("static"), proxyRouter);
}
// static server
if (proxyConf.containsKey("sock")) {
handleSock(proxyConf.getJsonArray("sock"), httpClient, proxyRouter);
}
// Send page404 page
proxyRouter.errorHandler(404, ctx -> ctx.response().sendFile(proxyConf.getString("page404")));
// Send 404 page
proxyRouter.errorHandler(404, ctx -> {
ctx.response().sendFile(proxyConf.getString("404"));
});
HttpServer server = vertx.createHttpServer();
HttpServer server = getHttpsServer(proxyConf);
server.requestHandler(proxyRouter);
Integer port = proxyConf.getInteger("listen");
@@ -129,6 +127,40 @@ public class ReverseProxyVerticle extends AbstractVerticle {
server.listen(port);
}
private HttpServer getHttpsServer(JsonObject proxyConf) {
HttpServerOptions httpServerOptions = new HttpServerOptions()
.setCompressionSupported(true);
if (proxyConf.containsKey("ssl")) {
JsonObject sslConfig = proxyConf.getJsonObject("ssl");
URL sslUrl = this.getClass().getClassLoader().getResource("");
if (sslUrl == null) {
throw new RuntimeException("SSL url not exist...");
}
if (sslConfig.containsKey("enable") && sslConfig.getBoolean("enable")) {
String sslCertificatePath = sslUrl.getPath() + sslConfig.getString("ssl_certificate");
String sslCertificateKeyPath = sslUrl.getPath() + sslConfig.getString("ssl_certificate_key");
LOGGER.info("enable ssl config. ");
httpServerOptions
.setSsl(true)
.setKeyCertOptions(
new PemKeyCertOptions()
.setKeyPath(sslCertificateKeyPath)
.setCertPath(sslCertificatePath)
).addEnabledSecureTransportProtocol(sslConfig.getString("ssl_protocols"));
String sslCiphers = sslConfig.getString("ssl_ciphers");
if (sslCiphers != null && !sslCiphers.isEmpty()) {
for (String s : sslCiphers.split(":")) {
httpServerOptions.addEnabledCipherSuite(s);
}
}
}
}
return vertx.createHttpServer(httpServerOptions);
}
/**
* 处理静态资源配置
*
@@ -145,10 +177,14 @@ public class ReverseProxyVerticle extends AbstractVerticle {
ctx.next();
});
final StaticHandler staticHandler = StaticHandler.create();
StaticHandler staticHandler;
if (staticConf.containsKey("root")) {
staticHandler.setWebRoot(staticConf.getString("root"));
staticHandler = StaticHandler.create(staticConf.getString("root"));
} else {
staticHandler = StaticHandler.create();
}
if (staticConf.containsKey("directory-listing")) {
staticHandler.setDirectoryListing(staticConf.getBoolean("directory-listing"));
} else if (staticConf.containsKey("index")) {
@@ -178,7 +214,7 @@ public class ReverseProxyVerticle extends AbstractVerticle {
port = 80;
}
String originPath = url.getPath();
LOGGER.debug("Conf(path, originPath, host, port) ----> {},{},{},{}", path, originPath, host, port);
LOGGER.info("path {}, originPath {}, to {}:{}", path, originPath, host, port);
// 注意这里不能origin多个代理地址, 一个实例只能代理一个origin
final HttpProxy httpProxy = HttpProxy.reverseProxy(httpClient);
@@ -189,14 +225,21 @@ public class ReverseProxyVerticle extends AbstractVerticle {
// 代理目标路径为空 就像nginx一样路径穿透 (相对路径)
if (StringUtils.isEmpty(originPath) || path.equals(originPath)) {
proxyRouter.route(path + "*").handler(ProxyHandler.create(httpProxy));
Route route = path.startsWith("~") ? proxyRouter.routeWithRegex(path.substring(1))
: proxyRouter.route(path);
route.handler(ProxyHandler.create(httpProxy));
} else {
proxyRouter.route(originPath + "*").handler(ProxyHandler.create(httpProxy));
proxyRouter.route(path + "*").handler(ctx -> {
String realPath = ctx.request().path();
if (realPath.startsWith(path)) {
// 配置 /api/, / => 请求 /api/test 代理后 /test
// 配置 /api/, /xxx => 请求 /api/test 代理后 /xxx/test
final String path0 = path;
final String originPath0 = REROUTE_PATH_PREFIX + originPath;
proxyRouter.route(originPath0 + "*").handler(ProxyHandler.create(httpProxy));
proxyRouter.route(path0 + "*").handler(ctx -> {
String realPath = ctx.request().uri();
if (realPath.startsWith(path0)) {
// vertx web proxy暂不支持rewrite, 所以这里进行手动替换, 请求地址中的请求path前缀替换为originPath
String rePath = realPath.replaceAll("^" + path, originPath);
String rePath = realPath.replaceAll("^" + path0, originPath0);
ctx.reroute(rePath);
} else {
ctx.next();
@@ -210,54 +253,4 @@ public class ReverseProxyVerticle extends AbstractVerticle {
});
}
/**
* 处理websocket
*
* @param confList sock配置
* @param httpClient 客户端
* @param proxyRouter 代理路由
*/
private void handleSock(JsonArray confList, HttpClient httpClient, Router proxyRouter) {
// 代理规则
confList.stream().map(e -> (JsonObject) e).forEach(conf -> {
String origin = conf.getString("origin");
String path = conf.getString("path");
LOGGER.info("websocket proxy: {}, {}",origin,path);
SockJSHandlerOptions options = new SockJSHandlerOptions()
.setHeartbeatInterval(2000)
.setRegisterWriteHandler(true);
SockJSHandler sockJSHandler = SockJSHandler.create(VertxHolder.getVertxInstance(), options);
if (!path.startsWith("/")) {
path = "/" + path;
}
Router route = sockJSHandler.socketHandler(sock -> {
sock.handler(buffer -> {
Future<WebSocket> webSocketFuture = httpClient.webSocket(8086,"127.0.0.1",sock.uri());
webSocketFuture.onSuccess(s -> {
System.out.println(buffer.toString());
s.write(buffer).onSuccess(v -> {
s.handler(w->{
System.out.println("--------"+w.toString());
});
});
});
});
sock.endHandler(v -> {
});
sock.closeHandler(v -> {
});
});
proxyRouter.mountSubRouter("/real/serverApi/test", route);
});
}
}
@@ -2,6 +2,7 @@ package cn.qaiu.vx.core.verticle;
import cn.qaiu.vx.core.handlerfactory.RouterHandlerFactory;
import cn.qaiu.vx.core.util.CommonUtil;
import cn.qaiu.vx.core.util.JacksonConfig;
import cn.qaiu.vx.core.util.SharedDataUtil;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Promise;
@@ -23,7 +24,6 @@ public class RouterVerticle extends AbstractVerticle {
private static final int port = SharedDataUtil.getValueForServerConfig("port");
private static final Router router = new RouterHandlerFactory(
SharedDataUtil.getJsonStringForCustomConfig("routerLocations"),
SharedDataUtil.getJsonStringForServerConfig("contextPath")).createRouter();
private static final JsonObject globalConfig = SharedDataUtil.getJsonConfig("globalConfig");
@@ -31,6 +31,8 @@ public class RouterVerticle extends AbstractVerticle {
private HttpServer