proxy-go/internal/handler/mirror_proxy.go

102 lines
2.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// handler/mirror_proxy.go
package handler
import (
"io"
"log"
"net/http"
"proxy-go/internal/utils"
"strings"
"time"
)
type MirrorProxyHandler struct{}
func NewMirrorProxyHandler() *MirrorProxyHandler {
return &MirrorProxyHandler{}
}
func (h *MirrorProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
startTime := time.Now()
// 设置 CORS 头
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD, PATCH")
w.Header().Set("Access-Control-Allow-Headers", "*")
// 如果需要允许发送凭证cookies等可以设置
// w.Header().Set("Access-Control-Allow-Credentials", "true")
// 处理 OPTIONS 请求(预检请求)
if r.Method == "OPTIONS" {
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)
return
}
// 从路径中提取实际URL
// 例如:/mirror/https://example.com/path 变成 https://example.com/path
actualURL := strings.TrimPrefix(r.URL.Path, "/mirror/")
if actualURL == "" || actualURL == r.URL.Path {
http.Error(w, "Invalid URL", http.StatusBadRequest)
return
}
// 添加原始请求中的查询参数和片段
if r.URL.RawQuery != "" {
actualURL += "?" + r.URL.RawQuery
}
// 创建新的请求
proxyReq, err := http.NewRequest(r.Method, actualURL, r.Body)
if err != nil {
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)
return
}
// 复制原始请求的header
copyHeader(proxyReq.Header, r.Header)
// 发送请求
client := &http.Client{
Transport: &http.Transport{
DisableCompression: true,
},
}
resp, err := client.Do(proxyReq)
if err != nil {
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)
return
}
defer resp.Body.Close()
// 设置CORS头
w.Header().Set("Access-Control-Allow-Origin", "*")
// 复制响应头
copyHeader(w.Header(), resp.Header)
// 设置状态码
w.WriteHeader(resp.StatusCode)
// 复制响应体
bytesCopied, err := io.Copy(w, resp.Body)
if err != nil {
log.Printf("Error copying response: %v", err)
return
}
// 记录访问日志
log.Printf("| %-6s | %3d | %12s | %15s | %10s | %-30s | %s",
r.Method, resp.StatusCode, time.Since(startTime),
utils.GetClientIP(r), utils.FormatBytes(bytesCopied),
utils.GetRequestSource(r), actualURL)
}