更新
This commit is contained in:
@@ -42,6 +42,7 @@ func (s *Server) Start() error {
|
|||||||
mux.HandleFunc("/api/stats", s.handleStats)
|
mux.HandleFunc("/api/stats", s.handleStats)
|
||||||
mux.HandleFunc("/api/shield", s.handleShield)
|
mux.HandleFunc("/api/shield", s.handleShield)
|
||||||
mux.HandleFunc("/api/shield/hosts", s.handleShieldHosts)
|
mux.HandleFunc("/api/shield/hosts", s.handleShieldHosts)
|
||||||
|
mux.HandleFunc("/api/shield/blacklists", s.handleShieldBlacklists)
|
||||||
mux.HandleFunc("/api/query", s.handleQuery)
|
mux.HandleFunc("/api/query", s.handleQuery)
|
||||||
mux.HandleFunc("/api/status", s.handleStatus)
|
mux.HandleFunc("/api/status", s.handleStatus)
|
||||||
mux.HandleFunc("/api/config", s.handleConfig)
|
mux.HandleFunc("/api/config", s.handleConfig)
|
||||||
@@ -194,14 +195,21 @@ func (s *Server) handleHourlyStats(w http.ResponseWriter, r *http.Request) {
|
|||||||
func (s *Server) handleShield(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) handleShield(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
// 处理hosts管理子路由
|
// 返回屏蔽规则的基本配置信息
|
||||||
if strings.HasPrefix(r.URL.Path, "/api/shield/hosts") {
|
switch r.Method {
|
||||||
s.handleShieldHosts(w, r)
|
case http.MethodGet:
|
||||||
return
|
shieldInfo := map[string]interface{}{
|
||||||
|
"updateInterval": s.globalConfig.Shield.UpdateInterval,
|
||||||
|
"blockMethod": s.globalConfig.Shield.BlockMethod,
|
||||||
|
"blacklistCount": len(s.globalConfig.Shield.Blacklists),
|
||||||
|
}
|
||||||
|
json.NewEncoder(w).Encode(shieldInfo)
|
||||||
|
default:
|
||||||
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理远程黑名单管理子路由
|
// 处理远程黑名单管理子路由
|
||||||
if strings.HasPrefix(r.URL.Path, "/api/shield/blacklists") {
|
if strings.HasPrefix(r.URL.Path, "/shield/blacklists") {
|
||||||
s.handleShieldBlacklists(w, r)
|
s.handleShieldBlacklists(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -268,21 +276,26 @@ func (s *Server) handleShieldBlacklists(w http.ResponseWriter, r *http.Request)
|
|||||||
// 处理更新单个黑名单
|
// 处理更新单个黑名单
|
||||||
if strings.Contains(r.URL.Path, "/update") {
|
if strings.Contains(r.URL.Path, "/update") {
|
||||||
if r.Method == http.MethodPost {
|
if r.Method == http.MethodPost {
|
||||||
// 提取黑名单ID
|
// 提取黑名单URL或Name
|
||||||
parts := strings.Split(r.URL.Path, "/")
|
parts := strings.Split(r.URL.Path, "/")
|
||||||
var id string
|
var targetURLOrName string
|
||||||
for i, part := range parts {
|
for i, part := range parts {
|
||||||
if part == "blacklists" && i+1 < len(parts) && parts[i+1] != "update" {
|
if part == "blacklists" && i+1 < len(parts) && parts[i+1] != "update" {
|
||||||
id = parts[i+1]
|
targetURLOrName = parts[i+1]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if targetURLOrName == "" {
|
||||||
|
http.Error(w, "黑名单标识不能为空", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 获取黑名单列表
|
// 获取黑名单列表
|
||||||
blacklists := s.shieldManager.GetBlacklists()
|
blacklists := s.shieldManager.GetBlacklists()
|
||||||
var targetIndex = -1
|
var targetIndex = -1
|
||||||
for i, list := range blacklists {
|
for i, list := range blacklists {
|
||||||
if list.URL == id || list.Name == id {
|
if list.URL == targetURLOrName || list.Name == targetURLOrName {
|
||||||
targetIndex = i
|
targetIndex = i
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -293,18 +306,13 @@ func (s *Server) handleShieldBlacklists(w http.ResponseWriter, r *http.Request)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 尝试更新该黑名单
|
// 更新时间戳
|
||||||
if err := s.shieldManager.fetchRemoteRules(blacklists[targetIndex].URL); err != nil {
|
|
||||||
// 更新失败,但不返回错误,而是更新状态
|
|
||||||
blacklists[targetIndex].LastUpdateTime = time.Now().Format(time.RFC3339)
|
blacklists[targetIndex].LastUpdateTime = time.Now().Format(time.RFC3339)
|
||||||
} else {
|
// 保存更新后的黑名单列表
|
||||||
// 更新成功
|
|
||||||
blacklists[targetIndex].LastUpdateTime = time.Now().Format(time.RFC3339)
|
|
||||||
// 重新加载规则
|
|
||||||
s.shieldManager.LoadRules()
|
|
||||||
}
|
|
||||||
|
|
||||||
s.shieldManager.UpdateBlacklist(blacklists)
|
s.shieldManager.UpdateBlacklist(blacklists)
|
||||||
|
// 重新加载规则以获取最新的远程规则
|
||||||
|
s.shieldManager.LoadRules()
|
||||||
|
|
||||||
json.NewEncoder(w).Encode(map[string]string{"status": "success"})
|
json.NewEncoder(w).Encode(map[string]string{"status": "success"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -372,8 +380,7 @@ func (s *Server) handleShieldBlacklists(w http.ResponseWriter, r *http.Request)
|
|||||||
blacklists = append(blacklists, newEntry)
|
blacklists = append(blacklists, newEntry)
|
||||||
s.shieldManager.UpdateBlacklist(blacklists)
|
s.shieldManager.UpdateBlacklist(blacklists)
|
||||||
|
|
||||||
// 尝试获取规则
|
// 重新加载规则以获取新添加的远程规则
|
||||||
s.shieldManager.fetchRemoteRules(req.URL)
|
|
||||||
s.shieldManager.LoadRules()
|
s.shieldManager.LoadRules()
|
||||||
|
|
||||||
json.NewEncoder(w).Encode(map[string]string{"status": "success"})
|
json.NewEncoder(w).Encode(map[string]string{"status": "success"})
|
||||||
@@ -382,8 +389,7 @@ func (s *Server) handleShieldBlacklists(w http.ResponseWriter, r *http.Request)
|
|||||||
// 更新所有远程黑名单
|
// 更新所有远程黑名单
|
||||||
blacklists := s.shieldManager.GetBlacklists()
|
blacklists := s.shieldManager.GetBlacklists()
|
||||||
for i := range blacklists {
|
for i := range blacklists {
|
||||||
// 尝试更新每个黑名单
|
// 更新每个黑名单的时间戳
|
||||||
s.shieldManager.fetchRemoteRules(blacklists[i].URL)
|
|
||||||
blacklists[i].LastUpdateTime = time.Now().Format(time.RFC3339)
|
blacklists[i].LastUpdateTime = time.Now().Format(time.RFC3339)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// 全局配置
|
// 全局配置
|
||||||
const API_BASE_URL = '/api';
|
const API_BASE_URL = '.';
|
||||||
|
|
||||||
// DOM 加载完成后执行
|
// DOM 加载完成后执行
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
@@ -65,7 +65,7 @@ if (typeof window.showNotification === 'undefined') {
|
|||||||
// 加载初始数据(主要用于服务器状态)
|
// 加载初始数据(主要用于服务器状态)
|
||||||
function loadInitialData() {
|
function loadInitialData() {
|
||||||
// 加载服务器状态
|
// 加载服务器状态
|
||||||
fetch(`${API_BASE_URL}/status`)
|
fetch(`${API_BASE_URL}/api/status`)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
// 更新服务器状态指示器
|
// 更新服务器状态指示器
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ function loadBlacklists() {
|
|||||||
const tbody = document.getElementById('blacklists-table').querySelector('tbody');
|
const tbody = document.getElementById('blacklists-table').querySelector('tbody');
|
||||||
showLoading(tbody);
|
showLoading(tbody);
|
||||||
|
|
||||||
apiRequest('/shield')
|
apiRequest('/api/shield/blacklists')
|
||||||
.then(data => {
|
.then(data => {
|
||||||
renderBlacklists(data);
|
renderBlacklists(data);
|
||||||
})
|
})
|
||||||
@@ -123,9 +123,9 @@ function addBlacklist() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
apiRequest('/shield', 'POST', { name: name, url: url })
|
apiRequest('/api/shield/blacklists', 'POST', { name: name, url: url })
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.success) {
|
if (data.status === 'success') {
|
||||||
window.showNotification('远程黑名单添加成功', 'success');
|
window.showNotification('远程黑名单添加成功', 'success');
|
||||||
nameInput.value = '';
|
nameInput.value = '';
|
||||||
urlInput.value = '';
|
urlInput.value = '';
|
||||||
@@ -142,9 +142,9 @@ function addBlacklist() {
|
|||||||
|
|
||||||
// 更新远程黑名单
|
// 更新远程黑名单
|
||||||
function updateBlacklist(id) {
|
function updateBlacklist(id) {
|
||||||
apiRequest(`/shield/${id}/update`, 'POST')
|
apiRequest(`/api/shield/blacklists/${id}/update`, 'POST')
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.success) {
|
if (data.status === 'success') {
|
||||||
window.showNotification('远程黑名单更新成功', 'success');
|
window.showNotification('远程黑名单更新成功', 'success');
|
||||||
loadBlacklists();
|
loadBlacklists();
|
||||||
} else {
|
} else {
|
||||||
@@ -162,9 +162,9 @@ function updateAllBlacklists() {
|
|||||||
confirmAction(
|
confirmAction(
|
||||||
'确定要更新所有远程黑名单吗?这可能需要一些时间。',
|
'确定要更新所有远程黑名单吗?这可能需要一些时间。',
|
||||||
() => {
|
() => {
|
||||||
apiRequest('/shield/update-all', 'POST')
|
apiRequest('/api/shield/blacklists', 'PUT')
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.success) {
|
if (data.status === 'success') {
|
||||||
window.showNotification('所有远程黑名单更新成功', 'success');
|
window.showNotification('所有远程黑名单更新成功', 'success');
|
||||||
loadBlacklists();
|
loadBlacklists();
|
||||||
} else {
|
} else {
|
||||||
@@ -181,9 +181,9 @@ function updateAllBlacklists() {
|
|||||||
|
|
||||||
// 删除远程黑名单
|
// 删除远程黑名单
|
||||||
function deleteBlacklist(id) {
|
function deleteBlacklist(id) {
|
||||||
apiRequest(`/shield/${id}`, 'DELETE')
|
apiRequest(`/api/shield/blacklists/${id}`, 'DELETE')
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.success) {
|
if (data.status === 'success') {
|
||||||
window.showNotification('远程黑名单删除成功', 'success');
|
window.showNotification('远程黑名单删除成功', 'success');
|
||||||
loadBlacklists();
|
loadBlacklists();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ function updateDomainRankings() {
|
|||||||
// 更新统计卡片数据
|
// 更新统计卡片数据
|
||||||
function updateStatCards() {
|
function updateStatCards() {
|
||||||
// 获取所有统计数据
|
// 获取所有统计数据
|
||||||
apiRequest('/stats')
|
apiRequest('/api/stats')
|
||||||
.then(data => {
|
.then(data => {
|
||||||
// 更新请求统计
|
// 更新请求统计
|
||||||
if (data && data.dns) {
|
if (data && data.dns) {
|
||||||
@@ -239,7 +239,7 @@ function updateStatCards() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 获取规则数
|
// 获取规则数
|
||||||
apiRequest('/shield')
|
apiRequest('/api/shield')
|
||||||
.then(data => {
|
.then(data => {
|
||||||
let rulesCount = 0;
|
let rulesCount = 0;
|
||||||
|
|
||||||
@@ -285,7 +285,7 @@ function updateStatCards() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 获取Hosts条目数量
|
// 获取Hosts条目数量
|
||||||
apiRequest('/shield/hosts')
|
apiRequest('/api/shield/hosts')
|
||||||
.then(data => {
|
.then(data => {
|
||||||
let hostsCount = 0;
|
let hostsCount = 0;
|
||||||
|
|
||||||
@@ -318,7 +318,7 @@ function updateStatCards() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 获取Hosts条目数
|
// 获取Hosts条目数
|
||||||
apiRequest('/shield/hosts')
|
apiRequest('/api/shield/hosts')
|
||||||
.then(data => {
|
.then(data => {
|
||||||
let hostsCount = 0;
|
let hostsCount = 0;
|
||||||
if (Array.isArray(data)) {
|
if (Array.isArray(data)) {
|
||||||
@@ -834,7 +834,7 @@ function loadTopBlockedDomains(isUpdate = false) {
|
|||||||
tbody.innerHTML = `<td colspan="100%" style="color: #7f8c8d; font-style: italic;">加载中...</td>`;
|
tbody.innerHTML = `<td colspan="100%" style="color: #7f8c8d; font-style: italic;">加载中...</td>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return apiRequest('/top-blocked')
|
return apiRequest('/api/top-blocked')
|
||||||
.then(data => {
|
.then(data => {
|
||||||
// 处理多种可能的数据格式,特别优化对用户提供格式的支持
|
// 处理多种可能的数据格式,特别优化对用户提供格式的支持
|
||||||
let processedData = [];
|
let processedData = [];
|
||||||
@@ -909,7 +909,7 @@ function loadTopResolvedDomains(isUpdate = false) {
|
|||||||
tbody.innerHTML = `<td colspan="100%" style="color: #7f8c8d; font-style: italic;">加载中...</td>`;
|
tbody.innerHTML = `<td colspan="100%" style="color: #7f8c8d; font-style: italic;">加载中...</td>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return apiRequest('/top-resolved')
|
return apiRequest('/api/top-resolved')
|
||||||
.then(data => {
|
.then(data => {
|
||||||
// 处理多种可能的数据格式
|
// 处理多种可能的数据格式
|
||||||
let processedData = [];
|
let processedData = [];
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ function loadHosts() {
|
|||||||
showLoading(tbody);
|
showLoading(tbody);
|
||||||
|
|
||||||
// 更新API路径,使用完整路径
|
// 更新API路径,使用完整路径
|
||||||
apiRequest('/shield/hosts', 'GET')
|
apiRequest('/api/shield/hosts', 'GET')
|
||||||
.then(data => {
|
.then(data => {
|
||||||
// 处理不同格式的响应数据
|
// 处理不同格式的响应数据
|
||||||
let hostsData;
|
let hostsData;
|
||||||
@@ -156,7 +156,7 @@ function addHostsEntry() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 修复重复API调用问题,只调用一次
|
// 修复重复API调用问题,只调用一次
|
||||||
apiRequest('/shield/hosts', 'POST', { ip: ip, domain: domain })
|
apiRequest('/api/shield/hosts', 'POST', { ip: ip, domain: domain })
|
||||||
.then(data => {
|
.then(data => {
|
||||||
// 处理不同的响应格式
|
// 处理不同的响应格式
|
||||||
if (data.success || data.status === 'success') {
|
if (data.success || data.status === 'success') {
|
||||||
@@ -209,7 +209,7 @@ function deleteHostsEntry(ip, domain) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 更新API路径
|
// 更新API路径
|
||||||
apiRequest('/shield/hosts', 'DELETE', { ip: ip, domain: domain })
|
apiRequest('/api/shield/hosts', 'DELETE', { ip: ip, domain: domain })
|
||||||
.then(data => {
|
.then(data => {
|
||||||
// 处理不同的响应格式
|
// 处理不同的响应格式
|
||||||
if (data.success || data.status === 'success') {
|
if (data.success || data.status === 'success') {
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ function runDnsQuery() {
|
|||||||
showQueryLoading();
|
showQueryLoading();
|
||||||
|
|
||||||
// 更新API路径,使用完整路径
|
// 更新API路径,使用完整路径
|
||||||
apiRequest('/query', 'GET', { domain: domain })
|
apiRequest('/api/query', 'GET', { domain: domain })
|
||||||
.then(data => {
|
.then(data => {
|
||||||
// 处理可能的不同响应格式
|
// 处理可能的不同响应格式
|
||||||
renderQueryResult(data);
|
renderQueryResult(data);
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ async function loadRules() {
|
|||||||
showLoading(rulesPanel);
|
showLoading(rulesPanel);
|
||||||
|
|
||||||
// 更新API路径,使用正确的API路径
|
// 更新API路径,使用正确的API路径
|
||||||
const data = await apiRequest('/shield', 'GET');
|
const data = await apiRequest('/api/shield', 'GET');
|
||||||
|
|
||||||
// 处理后端返回的复杂对象数据格式
|
// 处理后端返回的复杂对象数据格式
|
||||||
let allRules = [];
|
let allRules = [];
|
||||||
@@ -207,7 +207,7 @@ async function addNewRule() {
|
|||||||
const processedRule = preprocessRule(rule);
|
const processedRule = preprocessRule(rule);
|
||||||
|
|
||||||
// 使用正确的API路径
|
// 使用正确的API路径
|
||||||
const response = await apiRequest('/shield', 'POST', { rule: processedRule });
|
const response = await apiRequest('/api/shield', 'POST', { rule: processedRule });
|
||||||
|
|
||||||
// 处理不同的响应格式
|
// 处理不同的响应格式
|
||||||
if (response.success || response.status === 'success') {
|
if (response.success || response.status === 'success') {
|
||||||
@@ -258,7 +258,7 @@ async function deleteRule(index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 使用正确的API路径
|
// 使用正确的API路径
|
||||||
const response = await apiRequest('/shield', 'DELETE', { rule });
|
const response = await apiRequest('/api/shield', 'DELETE', { rule });
|
||||||
|
|
||||||
// 处理不同的响应格式
|
// 处理不同的响应格式
|
||||||
if (response.success || response.status === 'success') {
|
if (response.success || response.status === 'success') {
|
||||||
@@ -319,8 +319,8 @@ async function reloadRules() {
|
|||||||
const rulesPanel = document.getElementById('rules-panel');
|
const rulesPanel = document.getElementById('rules-panel');
|
||||||
showLoading(rulesPanel);
|
showLoading(rulesPanel);
|
||||||
|
|
||||||
// 使用正确的API路径和方法 - PUT请求到/shield
|
// 使用正确的API路径和方法 - PUT请求到/api/shield
|
||||||
await apiRequest('/shield', 'PUT');
|
await apiRequest('/api/shield', 'PUT');
|
||||||
|
|
||||||
// 重新加载规则列表
|
// 重新加载规则列表
|
||||||
await loadRules();
|
await loadRules();
|
||||||
|
|||||||
Reference in New Issue
Block a user