package web
import (
"encoding/json"
"fmt"
"net/http"
"strconv"
"github.com/miaomint/port-manager/internal/scanner"
"github.com/miaomint/port-manager/internal/service"
)
// Server Web服务器
type Server struct {
scanner *scanner.PortScanner
identifier *service.ServiceIdentifier
}
// NewServer 创建新的Web服务器
func NewServer() *Server {
return &Server{
scanner: scanner.NewPortScanner(true, false), // 只显示监听端口
identifier: service.NewServiceIdentifier(),
}
}
// Start 启动Web服务器
func (s *Server) Start(port int) error {
mux := http.NewServeMux()
// 静态文件路由
mux.HandleFunc("/", s.indexHandler)
mux.HandleFunc("/api/ports", s.portsAPIHandler)
mux.HandleFunc("/api/random-port", s.randomPortHandler)
mux.HandleFunc("/api/scan-range", s.scanRangeHandler)
fmt.Printf("端口管理器启动在: http://localhost:%d\n", port)
return http.ListenAndServe(fmt.Sprintf(":%d", port), mux)
}
// indexHandler 主页处理器
func (s *Server) indexHandler(w http.ResponseWriter, r *http.Request) {
tmpl := `
端口管理器
`
w.Header().Set("Content-Type", "text/html; charset=utf-8")
fmt.Fprint(w, tmpl)
}
// portsAPIHandler 端口API处理器
func (s *Server) portsAPIHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
result, err := s.scanner.ScanPorts()
if err != nil {
http.Error(w, fmt.Sprintf(`{"error": "%s"}`, err.Error()), http.StatusInternalServerError)
return
}
// 识别服务
for i := range result.Ports {
identified := s.identifier.IdentifyService(&result.Ports[i])
result.Ports[i] = *identified
}
json.NewEncoder(w).Encode(result)
}
// randomPortHandler 随机端口处理器
func (s *Server) randomPortHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
minPort := 8000
maxPort := 9999
if min := r.URL.Query().Get("min"); min != "" {
if p, err := strconv.Atoi(min); err == nil {
minPort = p
}
}
if max := r.URL.Query().Get("max"); max != "" {
if p, err := strconv.Atoi(max); err == nil {
maxPort = p
}
}
port, err := s.scanner.GenerateRandomPort(minPort, maxPort)
if err != nil {
http.Error(w, fmt.Sprintf(`{"error": "%s"}`, err.Error()), http.StatusInternalServerError)
return
}
response := map[string]int{"port": port}
json.NewEncoder(w).Encode(response)
}
// scanRangeHandler 扫描端口范围处理器
func (s *Server) scanRangeHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
startStr := r.URL.Query().Get("start")
endStr := r.URL.Query().Get("end")
if startStr == "" || endStr == "" {
http.Error(w, `{"error": "需要提供start和end参数"}`, http.StatusBadRequest)
return
}
start, err := strconv.Atoi(startStr)
if err != nil {
http.Error(w, `{"error": "无效的start参数"}`, http.StatusBadRequest)
return
}
end, err := strconv.Atoi(endStr)
if err != nil {
http.Error(w, `{"error": "无效的end参数"}`, http.StatusBadRequest)
return
}
openPorts, err := s.scanner.ScanPortRange(start, end)
if err != nil {
http.Error(w, fmt.Sprintf(`{"error": "%s"}`, err.Error()), http.StatusInternalServerError)
return
}
response := map[string][]int{"openPorts": openPorts}
json.NewEncoder(w).Encode(response)
}