转发地址:https://blog.csdn.net/dong945221578/article/details/110679480

  1. package main
  2. import (
  3. "encoding/json"
  4. "flag"
  5. "fmt"
  6. "github.com/gin-gonic/gin"
  7. "io"
  8. "io/ioutil"
  9. "log"
  10. "net/http"
  11. "net/http/httputil"
  12. "net/url"
  13. "os"
  14. "strings"
  15. )
  16. type Respond struct {
  17. Success bool
  18. Status string
  19. Data []Proxy
  20. }
  21. type Proxy struct {
  22. Remark string //描述
  23. Prefix string //转发的前缀判断
  24. Upstream string //后端 nginx 地址或者ip地址
  25. RewritePrefix string //重写
  26. }
  27. var (
  28. InfoLog *log.Logger
  29. ErrorLog *log.Logger
  30. proxyMap = make(map[string]Proxy)
  31. )
  32. var adminUrl = flag.String("adminUrl", "", "admin的地址")
  33. var profile = flag.String("profile", "", "环境")
  34. var proxyFile = flag.String("proxyFile", "", "测试环境的数据")
  35. //日志初始化
  36. func initLog() {
  37. errFile, err := os.OpenFile("errors.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
  38. infoFile, err := os.OpenFile("info.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
  39. if err != nil {
  40. log.Fatalln("打开日志文件失败:", err)
  41. }
  42. InfoLog = log.New(io.MultiWriter(os.Stderr, infoFile), "Info:", log.LstdFlags|log.Lmicroseconds|log.Lshortfile)
  43. ErrorLog = log.New(io.MultiWriter(os.Stderr, errFile), "Error:", log.LstdFlags|log.Lmicroseconds|log.Lshortfile)
  44. }
  45. func main() {
  46. router := gin.Default() //创建一个router
  47. flag.Parse()
  48. initLog()
  49. if *profile != "" {
  50. InfoLog.Printf("加载远端数据: %s ", *adminUrl)
  51. initProxyList()
  52. } else {
  53. InfoLog.Printf("加载本地配置数据: %s", *proxyFile)
  54. loadProxyListFromFile()
  55. }
  56. router.Any("/*action", Forward) //所有请求都会经过Forward函数转发
  57. router.Run(":8000")
  58. }
  59. func initProxyList() {
  60. resp, _ := http.Get(*adminUrl)
  61. if resp != nil && resp.StatusCode == 200 {
  62. bytes, err := ioutil.ReadAll(resp.Body)
  63. defer resp.Body.Close()
  64. if err != nil {
  65. fmt.Println("ioutil.ReadAll err=", err)
  66. return
  67. }
  68. var respond Respond
  69. err = json.Unmarshal(bytes, &respond)
  70. if err != nil {
  71. fmt.Println("json.Unmarshal err=", err)
  72. return
  73. }
  74. proxyList := respond.Data
  75. for _, proxy := range proxyList {
  76. //追加 反斜杠,为了动态匹配的时候 防止 /proxy/test /proxy/test1 无法正确转发
  77. proxyMap[proxy.Prefix+"/"] = proxy
  78. }
  79. }
  80. }
  81. func Forward(c *gin.Context) {
  82. HostReverseProxy(c.Writer, c.Request)
  83. }
  84. func HostReverseProxy(w http.ResponseWriter, r *http.Request) {
  85. if r.RequestURI == "/favicon.ico" {
  86. io.WriteString(w, "Request path Error")
  87. return
  88. }
  89. //从内存里面获取转发的url
  90. var upstream = ""
  91. if value, ok := proxyMap[r.RequestURI]; ok {
  92. //如果转发的地址是 / 开头的,需要去掉
  93. if strings.HasSuffix(value.Upstream, "/") {
  94. upstream += strings.TrimRight(value.Upstream, "/")
  95. } else {
  96. upstream += value.Upstream
  97. }
  98. //如果首位不是/开头,则需要追加
  99. if !strings.HasPrefix(value.RewritePrefix, "/") {
  100. upstream += "/" + value.RewritePrefix
  101. } else {
  102. upstream += value.RewritePrefix
  103. }
  104. //去掉开头
  105. r.URL.Path = strings.ReplaceAll(r.URL.Path, r.RequestURI, "")
  106. }
  107. // parse the url
  108. remote, err := url.Parse(upstream)
  109. InfoLog.Printf("RequestURI %s upstream %s remote %s", r.RequestURI, upstream, remote)
  110. if err != nil {
  111. panic(err)
  112. }
  113. r.URL.Host = remote.Host
  114. r.URL.Scheme = remote.Scheme
  115. r.Header.Set("X-Forwarded-Host", r.Header.Get("Host"))
  116. r.Host = remote.Host
  117. httputil.NewSingleHostReverseProxy(remote).ServeHTTP(w, r)
  118. }
  119. func loadProxyListFromFile() {
  120. file, err := os.Open(*proxyFile)
  121. if err != nil {
  122. ErrorLog.Println("err:", err)
  123. }
  124. var respond Respond
  125. // 创建json解码器
  126. decoder := json.NewDecoder(file)
  127. err = decoder.Decode(&respond)
  128. if err != nil {
  129. fmt.Println("LoadProxyListFromFile failed", err.Error())
  130. }
  131. proxyList := respond.Data
  132. for _, proxy := range proxyList {
  133. proxyMap[proxy.Prefix+"/"] = proxy
  134. }
  135. }