mirror of
https://github.com/woodchen-ink/proxy-go.git
synced 2025-07-18 00:21:56 +08:00
更新Go版本至1.24,添加对github.com/woodchen-ink/go-web-utils的依赖,优化IP获取逻辑,统一使用iputil包获取客户端IP,提升代码一致性和可读性。
This commit is contained in:
parent
da3200c605
commit
f31c601c20
9
go.mod
9
go.mod
@ -1,10 +1,15 @@
|
||||
module proxy-go
|
||||
|
||||
go 1.23.1
|
||||
go 1.24
|
||||
|
||||
toolchain go1.24.4
|
||||
|
||||
require (
|
||||
github.com/andybalholm/brotli v1.1.1
|
||||
golang.org/x/net v0.40.0
|
||||
)
|
||||
|
||||
require golang.org/x/text v0.25.0 // indirect
|
||||
require (
|
||||
github.com/woodchen-ink/go-web-utils v1.0.0 // indirect
|
||||
golang.org/x/text v0.25.0 // indirect
|
||||
)
|
||||
|
4
go.sum
4
go.sum
@ -1,5 +1,9 @@
|
||||
github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA=
|
||||
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
|
||||
github.com/woodchen-ink/go-web-utils v0.0.0-20250621140947-08c57486fe2e h1:k/D90giyDyL5hDPJGGQexqZ423WmZqRUUxc/yQ6E8ws=
|
||||
github.com/woodchen-ink/go-web-utils v0.0.0-20250621140947-08c57486fe2e/go.mod h1:d+L8rZ7xekLnf679XRvfwqpl4M8RCNdWSViaB3GmpnI=
|
||||
github.com/woodchen-ink/go-web-utils v1.0.0 h1:Kybe0ZPhRI4w5FJ4bZdPcepNEKTmbw3to3xLR31e+ws=
|
||||
github.com/woodchen-ink/go-web-utils v1.0.0/go.mod h1:hpiT30rd5Egj2LqRwYBqbEtUXjhjh/Qary0S14KCZgw=
|
||||
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
||||
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||
|
@ -14,6 +14,8 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/woodchen-ink/go-web-utils/iputil"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -154,7 +156,7 @@ func (h *ProxyHandler) CheckAuth(token string) bool {
|
||||
func (h *ProxyHandler) LogoutHandler(w http.ResponseWriter, r *http.Request) {
|
||||
auth := r.Header.Get("Authorization")
|
||||
if auth == "" || !strings.HasPrefix(auth, "Bearer ") {
|
||||
log.Printf("[Auth] ERR %s %s -> 401 (%s) no token from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r))
|
||||
log.Printf("[Auth] ERR %s %s -> 401 (%s) no token from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), utils.GetRequestSource(r))
|
||||
http.Error(w, "Unauthorized", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
@ -162,7 +164,7 @@ func (h *ProxyHandler) LogoutHandler(w http.ResponseWriter, r *http.Request) {
|
||||
token := strings.TrimPrefix(auth, "Bearer ")
|
||||
h.auth.tokens.Delete(token)
|
||||
|
||||
log.Printf("[Auth] %s %s -> 200 (%s) logout success from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r))
|
||||
log.Printf("[Auth] %s %s -> 200 (%s) logout success from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), utils.GetRequestSource(r))
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(map[string]string{
|
||||
@ -175,14 +177,14 @@ func (h *ProxyHandler) AuthMiddleware(next http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
auth := r.Header.Get("Authorization")
|
||||
if auth == "" || !strings.HasPrefix(auth, "Bearer ") {
|
||||
log.Printf("[Auth] ERR %s %s -> 401 (%s) no token from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r))
|
||||
log.Printf("[Auth] ERR %s %s -> 401 (%s) no token from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), utils.GetRequestSource(r))
|
||||
http.Error(w, "Unauthorized", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
token := strings.TrimPrefix(auth, "Bearer ")
|
||||
if !h.auth.validateToken(token) {
|
||||
log.Printf("[Auth] ERR %s %s -> 401 (%s) invalid token from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r))
|
||||
log.Printf("[Auth] ERR %s %s -> 401 (%s) invalid token from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), utils.GetRequestSource(r))
|
||||
http.Error(w, "Invalid token", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
@ -253,14 +255,14 @@ func (h *ProxyHandler) OAuthCallbackHandler(w http.ResponseWriter, r *http.Reque
|
||||
// 验证 state
|
||||
if !h.auth.validateState(state) {
|
||||
log.Printf("[Auth] ERR %s %s -> 400 (%s) invalid state '%s' from %s",
|
||||
r.Method, r.URL.Path, utils.GetClientIP(r), state, utils.GetRequestSource(r))
|
||||
r.Method, r.URL.Path, iputil.GetClientIP(r), state, utils.GetRequestSource(r))
|
||||
http.Error(w, "Invalid state", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// 验证code参数
|
||||
if code == "" {
|
||||
log.Printf("[Auth] ERR %s %s -> 400 (%s) missing code parameter from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r))
|
||||
log.Printf("[Auth] ERR %s %s -> 400 (%s) missing code parameter from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), utils.GetRequestSource(r))
|
||||
http.Error(w, "Missing code parameter", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
@ -272,7 +274,7 @@ func (h *ProxyHandler) OAuthCallbackHandler(w http.ResponseWriter, r *http.Reque
|
||||
|
||||
// 验证OAuth配置
|
||||
if clientID == "" || clientSecret == "" {
|
||||
log.Printf("[Auth] ERR %s %s -> 500 (%s) missing OAuth credentials from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r))
|
||||
log.Printf("[Auth] ERR %s %s -> 500 (%s) missing OAuth credentials from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), utils.GetRequestSource(r))
|
||||
http.Error(w, "Server configuration error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
@ -290,7 +292,7 @@ func (h *ProxyHandler) OAuthCallbackHandler(w http.ResponseWriter, r *http.Reque
|
||||
"client_secret": {clientSecret},
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("[Auth] ERR %s %s -> 500 (%s) failed to get access token: %v from %s", r.Method, r.URL.Path, utils.GetClientIP(r), err, utils.GetRequestSource(r))
|
||||
log.Printf("[Auth] ERR %s %s -> 500 (%s) failed to get access token: %v from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), err, utils.GetRequestSource(r))
|
||||
http.Error(w, "Failed to get access token", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
@ -301,21 +303,21 @@ func (h *ProxyHandler) OAuthCallbackHandler(w http.ResponseWriter, r *http.Reque
|
||||
// 读取错误响应内容
|
||||
bodyBytes, _ := io.ReadAll(resp.Body)
|
||||
log.Printf("[Auth] ERR %s %s -> %d (%s) OAuth server returned error: %s, response: %s",
|
||||
r.Method, r.URL.Path, resp.StatusCode, utils.GetClientIP(r), resp.Status, string(bodyBytes))
|
||||
r.Method, r.URL.Path, resp.StatusCode, iputil.GetClientIP(r), resp.Status, string(bodyBytes))
|
||||
http.Error(w, "OAuth server error: "+resp.Status, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
var token OAuthToken
|
||||
if err := json.NewDecoder(resp.Body).Decode(&token); err != nil {
|
||||
log.Printf("[Auth] ERR %s %s -> 500 (%s) failed to parse token response: %v from %s", r.Method, r.URL.Path, utils.GetClientIP(r), err, utils.GetRequestSource(r))
|
||||
log.Printf("[Auth] ERR %s %s -> 500 (%s) failed to parse token response: %v from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), err, utils.GetRequestSource(r))
|
||||
http.Error(w, "Failed to parse token response", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// 验证访问令牌
|
||||
if token.AccessToken == "" {
|
||||
log.Printf("[Auth] ERR %s %s -> 500 (%s) received empty access token from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r))
|
||||
log.Printf("[Auth] ERR %s %s -> 500 (%s) received empty access token from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), utils.GetRequestSource(r))
|
||||
http.Error(w, "Received invalid token", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
@ -326,7 +328,7 @@ func (h *ProxyHandler) OAuthCallbackHandler(w http.ResponseWriter, r *http.Reque
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
userResp, err := client.Do(req)
|
||||
if err != nil {
|
||||
log.Printf("[Auth] ERR %s %s -> 500 (%s) failed to get user info: %v from %s", r.Method, r.URL.Path, utils.GetClientIP(r), err, utils.GetRequestSource(r))
|
||||
log.Printf("[Auth] ERR %s %s -> 500 (%s) failed to get user info: %v from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), err, utils.GetRequestSource(r))
|
||||
http.Error(w, "Failed to get user info", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
@ -335,7 +337,7 @@ func (h *ProxyHandler) OAuthCallbackHandler(w http.ResponseWriter, r *http.Reque
|
||||
// 检查用户信息响应状态码
|
||||
if userResp.StatusCode != http.StatusOK {
|
||||
log.Printf("[Auth] ERR %s %s -> %d (%s) userinfo endpoint returned error status: %s from %s",
|
||||
r.Method, r.URL.Path, userResp.StatusCode, utils.GetClientIP(r), userResp.Status, utils.GetRequestSource(r))
|
||||
r.Method, r.URL.Path, userResp.StatusCode, iputil.GetClientIP(r), userResp.Status, utils.GetRequestSource(r))
|
||||
http.Error(w, "Failed to get user info: "+userResp.Status, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
@ -344,7 +346,7 @@ func (h *ProxyHandler) OAuthCallbackHandler(w http.ResponseWriter, r *http.Reque
|
||||
bodyBytes, err := io.ReadAll(userResp.Body)
|
||||
if err != nil {
|
||||
log.Printf("[Auth] ERR %s %s -> 500 (%s) failed to read user info response body: %v from %s",
|
||||
r.Method, r.URL.Path, utils.GetClientIP(r), err, utils.GetRequestSource(r))
|
||||
r.Method, r.URL.Path, iputil.GetClientIP(r), err, utils.GetRequestSource(r))
|
||||
http.Error(w, "Failed to read user info response", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
@ -356,7 +358,7 @@ func (h *ProxyHandler) OAuthCallbackHandler(w http.ResponseWriter, r *http.Reque
|
||||
var rawUserInfo map[string]interface{}
|
||||
if err := json.Unmarshal(bodyBytes, &rawUserInfo); err != nil {
|
||||
log.Printf("[Auth] ERR %s %s -> 500 (%s) failed to parse raw user info: %v from %s",
|
||||
r.Method, r.URL.Path, utils.GetClientIP(r), err, utils.GetRequestSource(r))
|
||||
r.Method, r.URL.Path, iputil.GetClientIP(r), err, utils.GetRequestSource(r))
|
||||
http.Error(w, "Failed to parse user info", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
@ -391,7 +393,7 @@ func (h *ProxyHandler) OAuthCallbackHandler(w http.ResponseWriter, r *http.Reque
|
||||
// 验证用户信息
|
||||
if userInfo.Username == "" {
|
||||
log.Printf("[Auth] ERR %s %s -> 500 (%s) could not extract username from user info from %s",
|
||||
r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r))
|
||||
r.Method, r.URL.Path, iputil.GetClientIP(r), utils.GetRequestSource(r))
|
||||
http.Error(w, "Invalid user information: missing username", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
@ -400,7 +402,7 @@ func (h *ProxyHandler) OAuthCallbackHandler(w http.ResponseWriter, r *http.Reque
|
||||
internalToken := h.auth.generateToken()
|
||||
h.auth.addToken(internalToken, userInfo.Username, tokenExpiry)
|
||||
|
||||
log.Printf("[Auth] %s %s -> 200 (%s) login success for user %s from %s", r.Method, r.URL.Path, utils.GetClientIP(r), userInfo.Username, utils.GetRequestSource(r))
|
||||
log.Printf("[Auth] %s %s -> 200 (%s) login success for user %s from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), userInfo.Username, utils.GetRequestSource(r))
|
||||
|
||||
// 返回登录成功页面
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
|
@ -11,6 +11,8 @@ import (
|
||||
"proxy-go/internal/utils"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/woodchen-ink/go-web-utils/iputil"
|
||||
)
|
||||
|
||||
type MirrorProxyHandler struct {
|
||||
@ -56,7 +58,7 @@ func (h *MirrorProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
log.Printf("| %-6s | %3d | %12s | %15s | %10s | %-30s | CORS Preflight",
|
||||
r.Method, http.StatusOK, time.Since(startTime),
|
||||
utils.GetClientIP(r), "-", r.URL.Path)
|
||||
iputil.GetClientIP(r), "-", r.URL.Path)
|
||||
return
|
||||
}
|
||||
|
||||
@ -66,7 +68,7 @@ func (h *MirrorProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "Invalid URL", http.StatusBadRequest)
|
||||
log.Printf("| %-6s | %3d | %12s | %15s | %10s | %-30s | Invalid URL",
|
||||
r.Method, http.StatusBadRequest, time.Since(startTime),
|
||||
utils.GetClientIP(r), "-", r.URL.Path)
|
||||
iputil.GetClientIP(r), "-", r.URL.Path)
|
||||
return
|
||||
}
|
||||
|
||||
@ -80,7 +82,7 @@ func (h *MirrorProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "Invalid URL", http.StatusBadRequest)
|
||||
log.Printf("| %-6s | %3d | %12s | %15s | %10s | %-30s | Parse URL error: %v",
|
||||
r.Method, http.StatusBadRequest, time.Since(startTime),
|
||||
utils.GetClientIP(r), "-", actualURL, err)
|
||||
iputil.GetClientIP(r), "-", actualURL, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -98,7 +100,7 @@ func (h *MirrorProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "Error creating request", http.StatusInternalServerError)
|
||||
log.Printf("| %-6s | %3d | %12s | %15s | %10s | %-30s | Error creating request: %v",
|
||||
r.Method, http.StatusInternalServerError, time.Since(startTime),
|
||||
utils.GetClientIP(r), "-", actualURL, err)
|
||||
iputil.GetClientIP(r), "-", actualURL, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -131,7 +133,7 @@ func (h *MirrorProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
http.ServeFile(w, r, item.FilePath)
|
||||
collector.RecordRequest(r.URL.Path, http.StatusOK, time.Since(startTime), item.Size, utils.GetClientIP(r), r)
|
||||
collector.RecordRequest(r.URL.Path, http.StatusOK, time.Since(startTime), item.Size, iputil.GetClientIP(r), r)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -142,7 +144,7 @@ func (h *MirrorProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "Error forwarding request", http.StatusBadGateway)
|
||||
log.Printf("| %-6s | %3d | %12s | %15s | %10s | %-30s | Error forwarding request: %v",
|
||||
r.Method, http.StatusBadGateway, time.Since(startTime),
|
||||
utils.GetClientIP(r), "-", actualURL, err)
|
||||
iputil.GetClientIP(r), "-", actualURL, err)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
@ -183,9 +185,9 @@ func (h *MirrorProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
// 记录访问日志
|
||||
log.Printf("| %-6s | %3d | %12s | %15s | %10s | %-30s | %s",
|
||||
r.Method, resp.StatusCode, time.Since(startTime),
|
||||
utils.GetClientIP(r), utils.FormatBytes(written),
|
||||
iputil.GetClientIP(r), utils.FormatBytes(written),
|
||||
utils.GetRequestSource(r), actualURL)
|
||||
|
||||
// 记录统计信息
|
||||
collector.RecordRequest(r.URL.Path, resp.StatusCode, time.Since(startTime), written, utils.GetClientIP(r), r)
|
||||
collector.RecordRequest(r.URL.Path, resp.StatusCode, time.Since(startTime), written, iputil.GetClientIP(r), r)
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/woodchen-ink/go-web-utils/iputil"
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
||||
@ -232,7 +233,7 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path == "/" {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprint(w, "Welcome to CZL proxy.")
|
||||
log.Printf("[Proxy] %s %s -> %d (%s) from %s", r.Method, r.URL.Path, http.StatusOK, utils.GetClientIP(r), utils.GetRequestSource(r))
|
||||
log.Printf("[Proxy] %s %s -> %d (%s) from %s", r.Method, r.URL.Path, http.StatusOK, iputil.GetClientIP(r), utils.GetRequestSource(r))
|
||||
return
|
||||
}
|
||||
|
||||
@ -258,7 +259,7 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
// 检查是否需要进行302跳转
|
||||
if h.redirectHandler != nil && h.redirectHandler.HandleRedirect(w, r, pathConfig, decodedPath, h.client) {
|
||||
// 如果进行了302跳转,直接返回,不继续处理
|
||||
collector.RecordRequest(r.URL.Path, http.StatusFound, time.Since(start), 0, utils.GetClientIP(r), r)
|
||||
collector.RecordRequest(r.URL.Path, http.StatusFound, time.Since(start), 0, iputil.GetClientIP(r), r)
|
||||
return
|
||||
}
|
||||
|
||||
@ -342,7 +343,7 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// 设置最小必要的代理头部
|
||||
clientIP := utils.GetClientIP(r)
|
||||
clientIP := iputil.GetClientIP(r)
|
||||
proxyReq.Header.Set("X-Real-IP", clientIP)
|
||||
|
||||
// 添加或更新 X-Forwarded-For - 减少重复获取客户端IP
|
||||
@ -389,7 +390,7 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
http.ServeFile(w, r, item.FilePath)
|
||||
collector.RecordRequest(r.URL.Path, http.StatusOK, time.Since(start), item.Size, utils.GetClientIP(r), r)
|
||||
collector.RecordRequest(r.URL.Path, http.StatusOK, time.Since(start), item.Size, iputil.GetClientIP(r), r)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -399,10 +400,10 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if err != nil {
|
||||
if ctx.Err() == context.DeadlineExceeded {
|
||||
h.errorHandler(w, r, fmt.Errorf("request timeout after %v", proxyRespTimeout))
|
||||
log.Printf("[Proxy] ERR %s %s -> 408 (%s) timeout from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r))
|
||||
log.Printf("[Proxy] ERR %s %s -> 408 (%s) timeout from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), utils.GetRequestSource(r))
|
||||
} else {
|
||||
h.errorHandler(w, r, fmt.Errorf("proxy error: %v", err))
|
||||
log.Printf("[Proxy] ERR %s %s -> 502 (%s) proxy error from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r))
|
||||
log.Printf("[Proxy] ERR %s %s -> 502 (%s) proxy error from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), utils.GetRequestSource(r))
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -450,7 +451,7 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
written, err = io.CopyBuffer(w, resp.Body, buf)
|
||||
if err != nil && !isConnectionClosed(err) {
|
||||
log.Printf("[Proxy] ERR %s %s -> write error (%s) from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r))
|
||||
log.Printf("[Proxy] ERR %s %s -> write error (%s) from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), utils.GetRequestSource(r))
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -461,13 +462,13 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
written, err = io.CopyBuffer(w, resp.Body, buf)
|
||||
if err != nil && !isConnectionClosed(err) {
|
||||
log.Printf("[Proxy] ERR %s %s -> write error (%s) from %s", r.Method, r.URL.Path, utils.GetClientIP(r), utils.GetRequestSource(r))
|
||||
log.Printf("[Proxy] ERR %s %s -> write error (%s) from %s", r.Method, r.URL.Path, iputil.GetClientIP(r), utils.GetRequestSource(r))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 记录统计信息
|
||||
collector.RecordRequest(r.URL.Path, resp.StatusCode, time.Since(start), written, utils.GetClientIP(r), r)
|
||||
collector.RecordRequest(r.URL.Path, resp.StatusCode, time.Since(start), written, iputil.GetClientIP(r), r)
|
||||
}
|
||||
|
||||
func copyHeader(dst, src http.Header) {
|
||||
|
@ -8,6 +8,8 @@ import (
|
||||
"proxy-go/internal/service"
|
||||
"proxy-go/internal/utils"
|
||||
"strings"
|
||||
|
||||
"github.com/woodchen-ink/go-web-utils/iputil"
|
||||
)
|
||||
|
||||
// RedirectHandler 处理302跳转逻辑
|
||||
@ -99,7 +101,7 @@ func (rh *RedirectHandler) performRedirect(w http.ResponseWriter, r *http.Reques
|
||||
w.WriteHeader(http.StatusFound)
|
||||
|
||||
// 记录跳转日志
|
||||
clientIP := utils.GetClientIP(r)
|
||||
clientIP := iputil.GetClientIP(r)
|
||||
log.Printf("[Redirect] %s %s -> 302 %s (%s) from %s",
|
||||
r.Method, r.URL.Path, targetURL, clientIP, utils.GetRequestSource(r))
|
||||
}
|
||||
|
@ -4,8 +4,9 @@ import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"proxy-go/internal/security"
|
||||
"proxy-go/internal/utils"
|
||||
"time"
|
||||
|
||||
"github.com/woodchen-ink/go-web-utils/iputil"
|
||||
)
|
||||
|
||||
// SecurityHandler 安全管理处理器
|
||||
@ -109,7 +110,7 @@ func (sh *SecurityHandler) CheckIPStatus(w http.ResponseWriter, r *http.Request)
|
||||
ip := r.URL.Query().Get("ip")
|
||||
if ip == "" {
|
||||
// 如果没有指定IP,使用请求的IP
|
||||
ip = utils.GetClientIP(r)
|
||||
ip = iputil.GetClientIP(r)
|
||||
}
|
||||
|
||||
banned, banEndTime := sh.banManager.GetBanInfo(ip)
|
||||
|
@ -4,8 +4,9 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"proxy-go/internal/security"
|
||||
"proxy-go/internal/utils"
|
||||
"time"
|
||||
|
||||
"github.com/woodchen-ink/go-web-utils/iputil"
|
||||
)
|
||||
|
||||
// SecurityMiddleware 安全中间件
|
||||
@ -23,7 +24,7 @@ func NewSecurityMiddleware(banManager *security.IPBanManager) *SecurityMiddlewar
|
||||
// IPBanMiddleware IP封禁中间件
|
||||
func (sm *SecurityMiddleware) IPBanMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
clientIP := utils.GetClientIP(r)
|
||||
clientIP := iputil.GetClientIP(r)
|
||||
|
||||
// 检查IP是否被封禁
|
||||
if sm.banManager.IsIPBanned(clientIP) {
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
neturl "net/url"
|
||||
"path/filepath"
|
||||
@ -93,26 +92,6 @@ func GenerateRequestID() string {
|
||||
return hex.EncodeToString(b)
|
||||
}
|
||||
|
||||
func GetClientIP(r *http.Request) string {
|
||||
// 优先级1: Cloudflare 提供的原始客户端 IP(最准确)
|
||||
if ip := r.Header.Get("CF-Connecting-IP"); ip != "" {
|
||||
return ip
|
||||
}
|
||||
// 优先级2: 通用的真实 IP 头
|
||||
if ip := r.Header.Get("X-Real-IP"); ip != "" {
|
||||
return ip
|
||||
}
|
||||
// 优先级3: 标准的转发链头部(取第一个 IP,即原始客户端 IP)
|
||||
if ip := r.Header.Get("X-Forwarded-For"); ip != "" {
|
||||
return strings.Split(ip, ",")[0]
|
||||
}
|
||||
// 优先级4: 直连 IP(兜底方案)
|
||||
if ip, _, err := net.SplitHostPort(r.RemoteAddr); err == nil {
|
||||
return ip
|
||||
}
|
||||
return r.RemoteAddr
|
||||
}
|
||||
|
||||
// 获取请求来源
|
||||
func GetRequestSource(r *http.Request) string {
|
||||
referer := r.Header.Get("Referer")
|
||||
|
Loading…
x
Reference in New Issue
Block a user