proxy-go/internal/middleware/fixed_path_proxy.go

94 lines
2.4 KiB
Go

package middleware
import (
"io"
"log"
"net"
"net/http"
"proxy-go/internal/config"
"strings"
)
type FixedPathConfig struct {
Path string `json:"Path"`
TargetHost string `json:"TargetHost"`
TargetURL string `json:"TargetURL"`
}
func FixedPathProxyMiddleware(configs []config.FixedPathConfig) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 检查是否匹配任何固定路径
for _, cfg := range configs {
if strings.HasPrefix(r.URL.Path, cfg.Path) {
// 创建新的请求
targetPath := strings.TrimPrefix(r.URL.Path, cfg.Path)
targetURL := cfg.TargetURL + targetPath
proxyReq, err := http.NewRequest(r.Method, targetURL, r.Body)
if err != nil {
http.Error(w, "Error creating proxy request", http.StatusInternalServerError)
return
}
// 复制原始请求的 header
for key, values := range r.Header {
for _, value := range values {
proxyReq.Header.Add(key, value)
}
}
// 设置必要的头部
proxyReq.Host = cfg.TargetHost
proxyReq.Header.Set("Host", cfg.TargetHost)
proxyReq.Header.Set("X-Real-IP", getClientIP(r))
proxyReq.Header.Set("X-Scheme", r.URL.Scheme)
// 发送代理请求
client := &http.Client{}
resp, err := client.Do(proxyReq)
if err != nil {
http.Error(w, "Error forwarding request", http.StatusBadGateway)
return
}
defer resp.Body.Close()
// 复制响应头
for key, values := range resp.Header {
for _, value := range values {
w.Header().Add(key, value)
}
}
// 设置响应状态码
w.WriteHeader(resp.StatusCode)
// 复制响应体
if _, err := io.Copy(w, resp.Body); err != nil {
// 已经发送了响应头,只能记录错误
log.Printf("Error copying response: %v", err)
}
return
}
}
// 如果没有匹配的固定路径,继续下一个处理器
next.ServeHTTP(w, r)
})
}
}
// getClientIP 获取客户端IP
func getClientIP(r *http.Request) string {
if ip := r.Header.Get("X-Real-IP"); ip != "" {
return ip
}
if ip := r.Header.Get("X-Forwarded-For"); ip != "" {
return strings.Split(ip, ",")[0]
}
if ip, _, err := net.SplitHostPort(r.RemoteAddr); err == nil {
return ip
}
return r.RemoteAddr
}