package cc.mrbird.febs.firewall.controller;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.firewall.entity.FirewallAccessLog;
import cc.mrbird.febs.firewall.service.IFirewallRuleService;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
/**
* 公开访问追踪API(无需登录)
*
* 前端 SPA 页面加载时调用此接口记录访问。
* Nginx 需配置 proxy_set_header 传递国家:
*
* proxy_set_header X-Real-IP $remote_addr;
* proxy_set_header X-Geo-Country $geoip_country_code;
*
*
* @author auto-generated
* @date 2026-07-31
*/
@Slf4j
@RestController
@RequestMapping("api/track")
@RequiredArgsConstructor
public class ApiTrackController {
private final IFirewallRuleService firewallRuleService;
/** ISO 3166-1 alpha-2 国家编码 → 国家名称 */
private static final Map COUNTRY_MAP = new HashMap<>();
static {
COUNTRY_MAP.put("CN", "中国");
COUNTRY_MAP.put("US", "美国");
COUNTRY_MAP.put("GB", "英国");
COUNTRY_MAP.put("JP", "日本");
COUNTRY_MAP.put("KR", "韩国");
COUNTRY_MAP.put("DE", "德国");
COUNTRY_MAP.put("FR", "法国");
COUNTRY_MAP.put("CA", "加拿大");
COUNTRY_MAP.put("AU", "澳大利亚");
COUNTRY_MAP.put("BR", "巴西");
COUNTRY_MAP.put("IN", "印度");
COUNTRY_MAP.put("RU", "俄罗斯");
COUNTRY_MAP.put("SG", "新加坡");
COUNTRY_MAP.put("MY", "马来西亚");
COUNTRY_MAP.put("TH", "泰国");
COUNTRY_MAP.put("VN", "越南");
COUNTRY_MAP.put("ID", "印度尼西亚");
COUNTRY_MAP.put("PH", "菲律宾");
COUNTRY_MAP.put("IT", "意大利");
COUNTRY_MAP.put("ES", "西班牙");
COUNTRY_MAP.put("NL", "荷兰");
COUNTRY_MAP.put("SE", "瑞典");
COUNTRY_MAP.put("CH", "瑞士");
COUNTRY_MAP.put("HK", "中国香港");
COUNTRY_MAP.put("TW", "中国台湾");
COUNTRY_MAP.put("MO", "中国澳门");
COUNTRY_MAP.put("AE", "阿联酋");
COUNTRY_MAP.put("SA", "沙特阿拉伯");
COUNTRY_MAP.put("TR", "土耳其");
COUNTRY_MAP.put("PK", "巴基斯坦");
COUNTRY_MAP.put("BD", "孟加拉国");
COUNTRY_MAP.put("NG", "尼日利亚");
COUNTRY_MAP.put("ZA", "南非");
COUNTRY_MAP.put("EG", "埃及");
COUNTRY_MAP.put("MX", "墨西哥");
COUNTRY_MAP.put("AR", "阿根廷");
COUNTRY_MAP.put("CL", "智利");
COUNTRY_MAP.put("CO", "哥伦比亚");
COUNTRY_MAP.put("PE", "秘鲁");
COUNTRY_MAP.put("PL", "波兰");
COUNTRY_MAP.put("UA", "乌克兰");
COUNTRY_MAP.put("BE", "比利时");
COUNTRY_MAP.put("AT", "奥地利");
COUNTRY_MAP.put("IE", "爱尔兰");
COUNTRY_MAP.put("NO", "挪威");
COUNTRY_MAP.put("DK", "丹麦");
COUNTRY_MAP.put("FI", "芬兰");
COUNTRY_MAP.put("PT", "葡萄牙");
COUNTRY_MAP.put("CZ", "捷克");
COUNTRY_MAP.put("RO", "罗马尼亚");
COUNTRY_MAP.put("GR", "希腊");
COUNTRY_MAP.put("HU", "匈牙利");
COUNTRY_MAP.put("IL", "以色列");
COUNTRY_MAP.put("IR", "伊朗");
COUNTRY_MAP.put("IQ", "伊拉克");
COUNTRY_MAP.put("MM", "缅甸");
COUNTRY_MAP.put("KH", "柬埔寨");
COUNTRY_MAP.put("LA", "老挝");
COUNTRY_MAP.put("NP", "尼泊尔");
COUNTRY_MAP.put("LK", "斯里兰卡");
COUNTRY_MAP.put("KZ", "哈萨克斯坦");
COUNTRY_MAP.put("UZ", "乌兹别克斯坦");
COUNTRY_MAP.put("NZ", "新西兰");
COUNTRY_MAP.put("KE", "肯尼亚");
COUNTRY_MAP.put("ET", "埃塞俄比亚");
COUNTRY_MAP.put("MA", "摩洛哥");
COUNTRY_MAP.put("DZ", "阿尔及利亚");
COUNTRY_MAP.put("TN", "突尼斯");
}
/**
* 根据国家编码获取名称
*/
public static String getCountryName(String code) {
if (StrUtil.isBlank(code)) {
return null;
}
return COUNTRY_MAP.getOrDefault(code.toUpperCase(), code);
}
@GetMapping("visit")
public FebsResponse trackVisit(HttpServletRequest request) {
try {
String countryCode = request.getHeader("X-Geo-Country");
FirewallAccessLog accessLog = new FirewallAccessLog();
accessLog.setIp(ServletUtil.getClientIP(request));
accessLog.setCountryCode(countryCode);
accessLog.setCountryName(getCountryName(countryCode));
accessLog.setUserAgent(request.getHeader("User-Agent"));
accessLog.setRequestUri(request.getHeader("Referer"));
accessLog.setIsBlocked(0);
firewallRuleService.recordAccess(accessLog);
return new FebsResponse().success();
} catch (Exception e) {
log.error("访问追踪记录失败", e);
return new FebsResponse().fail().message("记录失败");
}
}
}