api.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. package core
  2. import (
  3. "fmt"
  4. "github.com/SongZihuan/huan-proxy/src/config/rulescompile/actioncompile/rewritecompile"
  5. "github.com/SongZihuan/huan-proxy/src/server/context"
  6. "github.com/SongZihuan/huan-proxy/src/server/request/readonlyrequest"
  7. "github.com/SongZihuan/huan-proxy/src/utils"
  8. "net"
  9. "strings"
  10. )
  11. func (c *CoreServer) apiServer(ctx *context.Context) {
  12. proxy := ctx.Rule.Api.Server
  13. if proxy == nil {
  14. c.abortServerError(ctx)
  15. return
  16. }
  17. targetURL := ctx.Rule.Api.TargetURL
  18. ctx.ProxyRequest.URL.Scheme = targetURL.Scheme
  19. ctx.ProxyRequest.URL.Host = targetURL.Host
  20. c.processProxyHeader(ctx)
  21. ctx.ProxyRequest.URL.Path = c.apiRewrite(utils.ProcessURLPath(ctx.ProxyRequest.URL.Path), ctx.Rule.Api.AddPath, ctx.Rule.Api.SubPath, ctx.Rule.Api.Rewrite)
  22. for _, h := range ctx.Rule.Api.HeaderSet {
  23. ctx.ProxyRequest.Header.Set(h.Header, h.Value)
  24. }
  25. for _, h := range ctx.Rule.Api.HeaderAdd {
  26. ctx.ProxyRequest.Header.Add(h.Header, h.Value)
  27. }
  28. for _, h := range ctx.Rule.Api.HeaderDel {
  29. ctx.ProxyRequest.Header.Del(h.Header)
  30. }
  31. query := ctx.ProxyRequest.URL.Query()
  32. for _, q := range ctx.Rule.Api.QuerySet {
  33. query.Set(q.Query, q.Value)
  34. }
  35. for _, q := range ctx.Rule.Api.QueryAdd {
  36. query.Add(q.Query, q.Value)
  37. }
  38. for _, q := range ctx.Rule.Api.QueryDel {
  39. query.Del(q.Query)
  40. }
  41. ctx.ProxyRequest.URL.RawQuery = query.Encode()
  42. c.writeViaHeader(ctx)
  43. req, err := ctx.ProxyWriteToHttpRRequest()
  44. if err != nil {
  45. c.abortServerError(ctx)
  46. return
  47. }
  48. proxy.ServeHTTP(ctx.Writer, req) // 反向代理
  49. }
  50. func (c *CoreServer) apiRewrite(srcpath string, prefix string, suffix string, rewrite *rewritecompile.RewriteCompileConfig) string {
  51. srcpath = utils.ProcessURLPath(srcpath)
  52. prefix = utils.ProcessURLPath(prefix)
  53. suffix = utils.ProcessURLPath(suffix)
  54. if strings.HasPrefix(srcpath, suffix) {
  55. srcpath = srcpath[len(suffix):]
  56. }
  57. srcpath = prefix + srcpath
  58. if rewrite.Use && rewrite.Regex != nil {
  59. rewrite.Regex.ReplaceAllString(srcpath, rewrite.Target)
  60. }
  61. return srcpath
  62. }
  63. func (c *CoreServer) processProxyHeader(ctx *context.Context) {
  64. if ctx.Request.RemoteAddr() == "" {
  65. return
  66. }
  67. remoteIPStr, _, err := net.SplitHostPort(ctx.Request.RemoteAddr())
  68. if err != nil {
  69. return
  70. }
  71. remoteIP := net.ParseIP(remoteIPStr)
  72. var ProxyList, ForwardedList []string
  73. var host, proto string
  74. if ctx.Request.Header().Get("Forwarded") != "" {
  75. ProxyList, ForwardedList, host, proto = c.getProxyListForwarder(remoteIP, ctx.Request)
  76. } else if ctx.Request.Header().Get("X-Forwarded-For") != "" {
  77. ProxyList, ForwardedList, host, proto = c.getProxyListFromXForwardedFor(remoteIP, ctx.Request)
  78. } else {
  79. host = ctx.Request.Header().Get("X-Forwarded-Host")
  80. proto = ctx.Request.Header().Get("X-Forwarded-Proto")
  81. if host == "" {
  82. host = ctx.Request.Host()
  83. }
  84. host, _ = utils.SplitHostPort(host) // 去除host中的端口号
  85. if proto == "http" || proto == "https" {
  86. if ctx.Request.IsTLS() {
  87. proto = "https"
  88. } else {
  89. proto = "http"
  90. }
  91. }
  92. ProxyList = append(make([]string, 0, 1), remoteIP.String())
  93. ForwardedList = append(make([]string, 0, 1),
  94. fmt.Sprintf("for=%s", remoteIP.String()),
  95. fmt.Sprintf("host=%s", host),
  96. fmt.Sprintf("proto=%s", proto))
  97. }
  98. ctx.ProxyRequest.Header.Set("Forwarded", strings.Join(ForwardedList, ", "))
  99. ctx.ProxyRequest.Header.Set("X-Forwarded-For", strings.Join(ProxyList, ", "))
  100. ctx.ProxyRequest.Header.Set("X-Forwarded-Host", host)
  101. ctx.ProxyRequest.Header.Set("X-Forwarded-Proto", proto)
  102. }
  103. func (c *CoreServer) getProxyListForwarder(remoteIP net.IP, r *readonlyrequest.ReadOnlyRequest) ([]string, []string, string, string) {
  104. ForwardedList := strings.Split(r.Header().Get("Forwarded"), ",")
  105. ProxyList := make([]string, 0, len(ForwardedList)+1)
  106. NewForwardedList := make([]string, 0, len(ForwardedList)+1)
  107. host, _ := utils.SplitHostPort(r.Host()) // 去除host中的端口号
  108. proto := "http"
  109. if r.IsTLS() {
  110. proto = "https"
  111. }
  112. for _, keyStr := range ForwardedList {
  113. kv := strings.Split(strings.ReplaceAll(keyStr, " ", ""), "=")
  114. if len(kv) != 2 {
  115. continue
  116. }
  117. if kv[0] == "for" {
  118. forIP := net.ParseIP(strings.TrimSpace(kv[1]))
  119. if forIP != nil {
  120. NewForwardedList = append(NewForwardedList, keyStr)
  121. ProxyList = append(ProxyList, forIP.String())
  122. } else if kv[1] == "_hidden" || kv[1] == "_secret" || kv[1] == "unknown" {
  123. NewForwardedList = append(NewForwardedList, keyStr)
  124. }
  125. } else if kv[0] == "by" {
  126. byIP := net.ParseIP(strings.TrimSpace(kv[1]))
  127. if byIP != nil || kv[1] == "_hidden" || kv[1] == "_secret" || kv[1] == "unknown" {
  128. NewForwardedList = append(NewForwardedList, keyStr)
  129. }
  130. } else if kv[0] == "host" {
  131. host = kv[1]
  132. } else if kv[0] == "proto" {
  133. proto = kv[1]
  134. }
  135. }
  136. ProxyList = append(ProxyList, remoteIP.String())
  137. NewForwardedList = append(NewForwardedList, fmt.Sprintf("for=%s", remoteIP.String()))
  138. NewForwardedList = append(NewForwardedList, fmt.Sprintf("host=%s", host))
  139. NewForwardedList = append(NewForwardedList, fmt.Sprintf("proto=%s", proto))
  140. return ProxyList, NewForwardedList, host, proto
  141. }
  142. func (c *CoreServer) getProxyListFromXForwardedFor(remoteIP net.IP, r *readonlyrequest.ReadOnlyRequest) ([]string, []string, string, string) {
  143. XFroWardedForList := strings.Split(r.Header().Get("X-Forwarded-For"), ",")
  144. ProxyList := make([]string, 0, len(XFroWardedForList)+1)
  145. NewForwardedList := make([]string, 0, len(XFroWardedForList)+1)
  146. for _, forIPStr := range XFroWardedForList {
  147. forIP := net.ParseIP(strings.TrimSpace(forIPStr))
  148. if forIP != nil {
  149. ProxyList = append(ProxyList, forIP.String())
  150. }
  151. }
  152. host := r.Header().Get("X-Forwarded-Host")
  153. proto := r.Header().Get("X-Forwarded-Proto")
  154. if host == "" {
  155. host = r.Host()
  156. }
  157. host, _ = utils.SplitHostPort(host) // 去除host中的端口号
  158. if proto == "http" || proto == "https" {
  159. if r.IsTLS() {
  160. proto = "https"
  161. } else {
  162. proto = "http"
  163. }
  164. }
  165. ProxyList = append(ProxyList, remoteIP.String())
  166. for _, ip := range ProxyList {
  167. NewForwardedList = append(NewForwardedList, fmt.Sprintf("for=%s", ip))
  168. }
  169. NewForwardedList = append(NewForwardedList, fmt.Sprintf("host=%s", host))
  170. NewForwardedList = append(NewForwardedList, fmt.Sprintf("proto=%s", proto))
  171. return ProxyList, NewForwardedList, host, proto
  172. }