feat: 内容代理支持页面类型别名(sync/search/sign/detail)
This commit is contained in:
@@ -39,10 +39,14 @@ public class AccessResultController {
|
|||||||
* ctx.siteUrl 指向:http://par:9012/api/v1/admin/sites/{siteId}/content
|
* ctx.siteUrl 指向:http://par:9012/api/v1/admin/sites/{siteId}/content
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* 内容代理:根据路径和可选查询参数返回存储内容。
|
* 内容代理:支持两种方式调用 ——
|
||||||
* 匹配规则:URL 以请求路径结尾(含查询参数),返回最新匹配项。
|
* 1. 真实路径:GET /admin/sites/{siteId}/content/index.php?search=xxx
|
||||||
* GET /admin/sites/{siteId}/content/index.php
|
* 2. 页面类型:GET /admin/sites/{siteId}/content/sync
|
||||||
* GET /admin/sites/{siteId}/content/torrents.php?search=keyword
|
* 页面类型映射(按站点类型自动匹配):
|
||||||
|
* sync → index.php (或 api/member/profile)
|
||||||
|
* search → torrents.php (或 api/torrent/search)
|
||||||
|
* sign → attendance.php
|
||||||
|
* detail → details.php
|
||||||
*/
|
*/
|
||||||
@GetMapping("/api/v1/admin/sites/{siteId}/content/**")
|
@GetMapping("/api/v1/admin/sites/{siteId}/content/**")
|
||||||
public ResponseEntity<String> contentProxy(
|
public ResponseEntity<String> contentProxy(
|
||||||
@@ -50,8 +54,11 @@ public class AccessResultController {
|
|||||||
HttpServletRequest request) {
|
HttpServletRequest request) {
|
||||||
String fullPath = request.getRequestURI();
|
String fullPath = request.getRequestURI();
|
||||||
String prefix = "/api/v1/admin/sites/" + siteId + "/content";
|
String prefix = "/api/v1/admin/sites/" + siteId + "/content";
|
||||||
String relativePath = fullPath.substring(fullPath.indexOf(prefix) + prefix.length());
|
String rawPath = fullPath.substring(fullPath.indexOf(prefix) + prefix.length());
|
||||||
String query = request.getQueryString();
|
String query = request.getQueryString();
|
||||||
|
|
||||||
|
// 页面类型 → URL 模式映射
|
||||||
|
String relativePath = resolvePageType(rawPath, siteId);
|
||||||
String pathWithQuery = relativePath + (query != null ? "?" + query : "");
|
String pathWithQuery = relativePath + (query != null ? "?" + query : "");
|
||||||
if (pathWithQuery.isEmpty()) pathWithQuery = "/";
|
if (pathWithQuery.isEmpty()) pathWithQuery = "/";
|
||||||
|
|
||||||
@@ -61,16 +68,14 @@ public class AccessResultController {
|
|||||||
.orderByDesc(AccessResult::getId)
|
.orderByDesc(AccessResult::getId)
|
||||||
.last("limit 200"));
|
.last("limit 200"));
|
||||||
|
|
||||||
// 优先精确匹配(URL 以 pathWithQuery 结尾),否则模糊匹配
|
// 优先精确匹配,否则模糊匹配
|
||||||
AccessResult best = results.stream()
|
AccessResult best = results.stream()
|
||||||
.filter(r -> r.getUrl() != null && r.getStoragePath() != null &&
|
.filter(r -> r.getUrl() != null && r.getStoragePath() != null &&
|
||||||
(r.getUrl().endsWith(pathWithQuery) || r.getUrl().contains(pathWithQuery)))
|
(r.getUrl().endsWith(pathWithQuery) || r.getUrl().contains(pathWithQuery)))
|
||||||
.findFirst().orElse(null);
|
.findFirst().orElse(null);
|
||||||
if (best == null) {
|
if (best == null) {
|
||||||
// 回退:URL 包含相对路径(不含查询参数)
|
|
||||||
String pathOnly = relativePath;
|
|
||||||
best = results.stream()
|
best = results.stream()
|
||||||
.filter(r -> r.getUrl() != null && r.getStoragePath() != null && r.getUrl().contains(pathOnly))
|
.filter(r -> r.getUrl() != null && r.getStoragePath() != null && r.getUrl().contains(relativePath))
|
||||||
.findFirst().orElse(null);
|
.findFirst().orElse(null);
|
||||||
}
|
}
|
||||||
if (best == null) return ResponseEntity.notFound().build();
|
if (best == null) return ResponseEntity.notFound().build();
|
||||||
@@ -82,6 +87,18 @@ public class AccessResultController {
|
|||||||
return ResponseEntity.ok().contentType(MediaType.parseMediaType(contentType + ";charset=UTF-8")).body(content);
|
return ResponseEntity.ok().contentType(MediaType.parseMediaType(contentType + ";charset=UTF-8")).body(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 页面类型 → URL 模式 */
|
||||||
|
private String resolvePageType(String type, String siteId) {
|
||||||
|
return switch (type) {
|
||||||
|
case "/sync", "/sync/" -> ".php?file=index"; // 通用匹配 index.php
|
||||||
|
case "/search", "/search/" -> "torrents.php";
|
||||||
|
case "/sign", "/sign/" -> "attendance.php";
|
||||||
|
case "/detail", "/detail/" -> "details.php";
|
||||||
|
case "/profile", "/profile/" -> "api/member/profile";
|
||||||
|
default -> type; // 原样传递(真实路径)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// ==================== mediabot 提交接口(PSK 鉴权) ====================
|
// ==================== mediabot 提交接口(PSK 鉴权) ====================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user