From 69f7fb93b6cbb4e65ac1f9d358016be7daa981af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B9=85=E5=BF=86?= <2246991755@qq.com> Date: Sat, 18 Oct 2025 20:04:03 +0800 Subject: [PATCH] first commit --- .gitignore | 41 ++++++++++++ build.sh | 38 +++++++++++ go.mod | 3 + main.go | 185 +++++++++++++++++++++++++++++++++++++++++++++++++++++ users.json | 18 ++++++ 5 files changed, 285 insertions(+) create mode 100644 .gitignore create mode 100755 build.sh create mode 100644 go.mod create mode 100644 main.go create mode 100644 users.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..521bbef --- /dev/null +++ b/.gitignore @@ -0,0 +1,41 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib +api + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool +*.out + +# Go workspace file +go.work + +# Dependency directories +vendor/ + +# IDE files +.idea/ +.vscode/ +*.swp +*.swo +*~ + +# OS files +.DS_Store +Thumbs.db + +# Environment files +.env +*.env + +# Log files +*.log + +# Temporary files +tmp/ +temp/ \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..71b98b2 --- /dev/null +++ b/build.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# User Expiry API - Linux Build Script +# 用户到期API - Linux构建脚本 + +echo "开始构建Linux版本..." +echo "Building Linux version..." + +# 设置构建参数 +export GOOS=linux +export GOARCH=amd64 + +# 构建可执行文件 +echo "正在编译..." +go build -o api main.go + +if [ $? -eq 0 ]; then + echo "✅ 构建成功!" + echo "✅ Build successful!" + echo "" + echo "生成的文件: api" + echo "Generated file: api" + echo "" + echo "部署说明:" + echo "Deployment instructions:" + echo "1. 上传 api 和 users.json 到Linux服务器" + echo " Upload api and users.json to Linux server" + echo "2. 添加执行权限: chmod +x api" + echo " Add execute permission: chmod +x api" + echo "3. 运行: ./api" + echo " Run: ./api" + echo "" + ls -la api +else + echo "❌ 构建失败!" + echo "❌ Build failed!" + exit 1 +fi \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..fc60f6d --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module user-expiry-api + +go 1.21 \ No newline at end of file diff --git a/main.go b/main.go new file mode 100644 index 0000000..bb176e1 --- /dev/null +++ b/main.go @@ -0,0 +1,185 @@ +package main + +import ( + "encoding/json" + "flag" + "fmt" + "log" + "net" + "net/http" + "os" + "strings" + "time" +) + +// User 用户数据结构 +type User struct { + IP string `json:"ip"` + Username string `json:"username"` + ExpiryDate string `json:"expiryDate"` + Phone string `json:"phone"` +} + +// UserData 用户数据容器 +type UserData struct { + Users []User `json:"users"` +} + +// APIResponse API响应结构 +type APIResponse struct { + Expiry string `json:"expiry"` + ServerTime string `json:"serverTime"` +} + +// getClientIP 获取客户端真实IP地址 +func getClientIP(r *http.Request) string { + // 优先检查代理头 + if xForwardedFor := r.Header.Get("X-Forwarded-For"); xForwardedFor != "" { + // X-Forwarded-For 可能包含多个IP,取第一个 + ips := strings.Split(xForwardedFor, ",") + if len(ips) > 0 { + return strings.TrimSpace(ips[0]) + } + } + + if xRealIP := r.Header.Get("X-Real-IP"); xRealIP != "" { + return xRealIP + } + + if xClientIP := r.Header.Get("X-Client-IP"); xClientIP != "" { + return xClientIP + } + + // 从RemoteAddr获取IP + ip, _, err := net.SplitHostPort(r.RemoteAddr) + if err != nil { + return r.RemoteAddr + } + + // 处理IPv6回环地址 + if ip == "::1" { + return "127.0.0.1" + } + + // 移除IPv6前缀 + if strings.HasPrefix(ip, "::ffff:") { + return strings.TrimPrefix(ip, "::ffff:") + } + + return ip +} + +// loadUserData 加载用户数据 +func loadUserData() ([]User, error) { + data, err := os.ReadFile("users.json") + if err != nil { + return nil, err + } + + var userData UserData + err = json.Unmarshal(data, &userData) + if err != nil { + return nil, err + } + + return userData.Users, nil +} + +// findUserByIP 根据IP查找用户 +func findUserByIP(users []User, ip string) *User { + for _, user := range users { + if user.IP == ip { + return &user + } + } + return nil +} + +// setCORSHeaders 设置CORS头 +func setCORSHeaders(w http.ResponseWriter) { + w.Header().Set("Access-Control-Allow-Origin", "*") + w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS") + w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization") +} + +// healthHandler 健康检查处理器 +func healthHandler(w http.ResponseWriter, r *http.Request) { + setCORSHeaders(w) + + if r.Method == "OPTIONS" { + w.WriteHeader(http.StatusOK) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + response := map[string]interface{}{ + "status": "ok", + "time": time.Now().Format(time.RFC3339), + } + + json.NewEncoder(w).Encode(response) +} + +// checkExpiryHandler 检查到期时间处理器 +func checkExpiryHandler(w http.ResponseWriter, r *http.Request) { + setCORSHeaders(w) + + if r.Method == "OPTIONS" { + w.WriteHeader(http.StatusOK) + return + } + + // 获取客户端IP + clientIP := getClientIP(r) + log.Printf("收到来自 %s 的请求", clientIP) + + // 获取当前服务器时间 + serverTime := time.Now().Format(time.RFC3339) + + // 加载用户数据 + users, err := loadUserData() + if err != nil { + log.Printf("读取用户数据失败: %v", err) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(map[string]interface{}{}) + return + } + + // 查找用户 + user := findUserByIP(users, clientIP) + if user == nil { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(map[string]interface{}{}) + return + } + + // 找到用户,返回到期时间 + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(APIResponse{ + Expiry: user.ExpiryDate, + ServerTime: serverTime, + }) +} + +func main() { + // 定义命令行参数 + portFlag := flag.String("port", "3763", "服务器端口号") + flag.Parse() + + // 设置路由 + http.HandleFunc("/health", healthHandler) + http.HandleFunc("/api/check-expiry", checkExpiryHandler) + + port := ":" + *portFlag + fmt.Printf("服务器运行在端口 %s\n", port) + fmt.Printf("健康检查: http://localhost%s/health\n", port) + fmt.Printf("API接口: http://localhost%s/api/check-expiry\n", port) + + // 启动服务器 + log.Fatal(http.ListenAndServe(port, nil)) +} diff --git a/users.json b/users.json new file mode 100644 index 0000000..cb8981b --- /dev/null +++ b/users.json @@ -0,0 +1,18 @@ +{ + "users": [ + { + "ip": "118.114.191.136", + "expiryDate": "2025-12-17T00:48:38+08:00", + "username": "user1", + "phone": "13800138000", + "versions": "旗舰版" + }, + { + "ip": "127.0.0.1", + "expiryDate": "2025-12-17T00:48:38+08:00", + "username": "user1", + "phone": "13800138000", + "versions": "旗舰版" + } + ] +}