代码拉取完成,页面将自动刷新
package main
import (
"bytes"
"compress/gzip"
"context"
"encoding/base64"
"fmt"
"io"
"log"
"net/http"
"net/http/httputil"
"net/url"
"strings"
)
var ctx = context.Background()
var cache ICache
var keyBase = "proxyTrek"
var proxyHost = "localhost:7001" // gateway中trek监听的地址
var ignoreQuery = map[string]int{
"fetchId": 1,
}
type EnvName string
type IgnorePath string
var (
targetEnv = EnvName("test-tx-8")
)
var env map[EnvName]IEnvConfig
func makeEnv(envName string) {
var (
targetTrekHost = "trek.test-tx-8.e7link.com"
//targetIdentityHost = ""
targetLocalHost = "localhost:7000"
)
//targetTrekHost = strings.Join([]string{"trek", envName, "e7link.com"}, ".")
//targetIdentityHost = strings.Join([]string{"identity", envName, "e7link.com"}, ".")
env = map[EnvName]IEnvConfig{
"test-tx-8": {
DefaultHost: targetTrekHost,
IgnorePath: map[string]IgnorePathConfig{
"/appPassport/refreshToken": {
Host: targetTrekHost,
Switch: 1,
},
"/appPassport/getRefreshTokenByIpChange": {
Host: targetTrekHost,
Switch: 1,
},
"/web/asyncTask/status": {
Switch: 1,
},
"/web/entity/asyncBatchDo/BudgetPlan": {
Switch: 1,
},
},
},
"local": {
DefaultHost: targetLocalHost,
IgnorePath: map[string]IgnorePathConfig{
"/appPassport/refreshToken": {
Host: targetLocalHost,
Switch: 1,
},
"/appPassport/getRefreshTokenByIpChange": {
Host: targetLocalHost,
Switch: 1,
},
"/web/asyncTask/status": {
Switch: 1,
},
"/web/entity/asyncBatchDo/BudgetPlan": {
Switch: 1,
},
},
},
}
}
func main() {
cache = NewMemoryCache()
makeEnv(string(targetEnv))
envIgnoreProxy, envDefaultProxy := makeProxy()
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
var proxy = envIgnoreProxy[targetEnv][IgnorePath(r.URL.Path)]
if env[targetEnv].IgnorePath[r.URL.Path].Switch == 1 {
fmt.Println("DIRECT PROXY:", r.URL.String())
proxy.Director = func(req *http.Request) {
host := env[targetEnv].IgnorePath[r.URL.Path].Host
req.Header = r.Header
req.Host = host
req.URL.Scheme = "http"
req.URL.Host = host
req.URL.Path = r.URL.Path
req.URL.RawQuery = r.URL.RawQuery
}
proxy.ServeHTTP(w, r)
} else {
proxyHandler(w, r, envDefaultProxy[targetEnv], env[targetEnv].DefaultHost)
}
})
go func() {
// 代理后台
log.Fatal(http.ListenAndServe(proxyHost, nil))
}()
// 管理页面
view()
}
func makeProxy() (map[EnvName]map[IgnorePath]*httputil.ReverseProxy, map[EnvName]*httputil.ReverseProxy) {
envIgnoreProxy := make(map[EnvName]map[IgnorePath]*httputil.ReverseProxy)
envDefaultProxy := make(map[EnvName]*httputil.ReverseProxy)
for envName, envConfig := range env {
ignorePathProxy := make(map[IgnorePath]*httputil.ReverseProxy)
for path, pathConfig := range envConfig.IgnorePath {
if pathConfig.Host == "" {
pathConfig.Host = envConfig.DefaultHost
}
ignorePathProxy[IgnorePath(path)] = httputil.NewSingleHostReverseProxy(&url.URL{
Scheme: "http",
Host: pathConfig.Host,
})
}
envIgnoreProxy[envName] = ignorePathProxy
envDefaultProxy[envName] = httputil.NewSingleHostReverseProxy(&url.URL{
Scheme: "http",
Host: envConfig.DefaultHost,
})
}
return envIgnoreProxy, envDefaultProxy
}
func proxyHandler(w http.ResponseWriter, r *http.Request, proxy *httputil.ReverseProxy, targetHost string) {
buf4cache, reqBody := handleRequestBody(r)
defer r.Body.Close()
cacheKey := makeCacheKey(r, buf4cache)
cachedData, _ := cache.Get(cacheKey)
if cachedData != "" {
fmt.Println("find cache:", r.URL.String())
fmt.Fprint(w, cachedData)
return
}
fmt.Println("NO cache:", r.URL.String())
newRawURL := handleIgnoreQuery(r)
proxyReq, _ := http.NewRequest(r.Method, newRawURL, reqBody)
proxyReq.Header = r.Header
proxyReq.Host = targetHost
rww := ResponseWriterWrapper{w: w}
proxy.ServeHTTP(&rww, proxyReq)
body_ := handleGzip(rww)
resBody := string(body_)
resBody = strings.TrimSpace(resBody)
handleCache(rww, cacheKey, resBody, r)
}
func handleRequestBody(r *http.Request) (*bytes.Buffer, *bytes.Buffer) {
buf4cache := bytes.NewBuffer(nil)
reqBody := bytes.NewBuffer(nil)
body := io.TeeReader(r.Body, io.MultiWriter(buf4cache, reqBody)) // 将请求的Body同时写入buf和reqBody
_, _ = io.ReadAll(body) // 不知道在干嘛,但删了就不对了
return buf4cache, reqBody
}
// makeCacheKey 根据 header body url 生成 key
func makeCacheKey(r *http.Request, buf4cache *bytes.Buffer) string {
var (
tenantId = r.Header.Get("Tenant-Id")
body = buf4cache.String()
)
cacheKey := strings.Join([]string{r.URL.String(), tenantId, body}, "@")
cacheKey = base64.StdEncoding.EncodeToString([]byte(cacheKey))
cacheKey = strings.Join([]string{keyBase, cacheKey}, "@@")
return cacheKey
}
func handleCache(rww ResponseWriterWrapper, cacheKey string, resBody string, r *http.Request) {
if rww.statusCode == 200 {
if len(resBody) > 0 {
cache.Set(cacheKey, resBody)
fmt.Println("SET cache:", r.URL.String(), len(resBody))
} else {
fmt.Println("IGNORE cache:", r.URL.String(), len(resBody))
}
} else if rww.statusCode == 401 {
fmt.Println("REMOVE cache:", r.URL.String(), len(resBody))
cache.Del(cacheKey)
} else {
fmt.Println("request error 1.1:", rww.statusCode, r.URL.String())
fmt.Println("request error 1.2:", resBody)
}
}
func handleIgnoreQuery(r *http.Request) string {
q := r.URL.Query()
q1 := make(url.Values)
for k, v := range q {
if ignoreQuery[k] == 1 {
continue
}
q1.Add(k, v[0])
}
r.URL.RawQuery = q1.Encode()
newRawURL := r.URL.String()
return newRawURL
}
func handleGzip(rww ResponseWriterWrapper) (body_ []byte) {
ungzipbody, err := gzip.NewReader(&rww.body)
if err != nil {
fmt.Println(110.1, err)
body_ = rww.body.Bytes()
} else {
body_, err = io.ReadAll(ungzipbody)
}
if err != nil {
fmt.Println(110.2, err)
}
return
}
type IgnorePathConfig struct {
Host string
Switch int
}
type IEnvConfig struct {
IgnorePath map[string]IgnorePathConfig
DefaultHost string
DefaultProxy *httputil.ReverseProxy
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。