123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- package core
- import (
- "fmt"
- "github.com/SongZihuan/huan-proxy/src/config/rulescompile/actioncompile/rewritecompile"
- "github.com/SongZihuan/huan-proxy/src/server/context"
- "github.com/SongZihuan/huan-proxy/src/server/request/readonlyrequest"
- "github.com/SongZihuan/huan-proxy/src/utils"
- "net"
- "strings"
- )
- func (c *CoreServer) apiServer(ctx *context.Context) {
- proxy := ctx.Rule.Api.Server
- if proxy == nil {
- c.abortServerError(ctx)
- return
- }
- targetURL := ctx.Rule.Api.TargetURL
- ctx.ProxyRequest.URL.Scheme = targetURL.Scheme
- ctx.ProxyRequest.URL.Host = targetURL.Host
- c.processProxyHeader(ctx)
- ctx.ProxyRequest.URL.Path = c.apiRewrite(utils.ProcessURLPath(ctx.ProxyRequest.URL.Path), ctx.Rule.Api.AddPath, ctx.Rule.Api.SubPath, ctx.Rule.Api.Rewrite)
- for _, h := range ctx.Rule.Api.HeaderSet {
- ctx.ProxyRequest.Header.Set(h.Header, h.Value)
- }
- for _, h := range ctx.Rule.Api.HeaderAdd {
- ctx.ProxyRequest.Header.Add(h.Header, h.Value)
- }
- for _, h := range ctx.Rule.Api.HeaderDel {
- ctx.ProxyRequest.Header.Del(h.Header)
- }
- query := ctx.ProxyRequest.URL.Query()
- for _, q := range ctx.Rule.Api.QuerySet {
- query.Set(q.Query, q.Value)
- }
- for _, q := range ctx.Rule.Api.QueryAdd {
- query.Add(q.Query, q.Value)
- }
- for _, q := range ctx.Rule.Api.QueryDel {
- query.Del(q.Query)
- }
- ctx.ProxyRequest.URL.RawQuery = query.Encode()
- c.writeViaHeader(ctx)
- req, err := ctx.ProxyWriteToHttpRRequest()
- if err != nil {
- c.abortServerError(ctx)
- return
- }
- proxy.ServeHTTP(ctx.Writer, req) // 反向代理
- }
- func (c *CoreServer) apiRewrite(srcpath string, prefix string, suffix string, rewrite *rewritecompile.RewriteCompileConfig) string {
- srcpath = utils.ProcessURLPath(srcpath)
- prefix = utils.ProcessURLPath(prefix)
- suffix = utils.ProcessURLPath(suffix)
- if strings.HasPrefix(srcpath, suffix) {
- srcpath = srcpath[len(suffix):]
- }
- srcpath = prefix + srcpath
- if rewrite.Use && rewrite.Regex != nil {
- rewrite.Regex.ReplaceAllString(srcpath, rewrite.Target)
- }
- return srcpath
- }
- func (c *CoreServer) processProxyHeader(ctx *context.Context) {
- if ctx.Request.RemoteAddr() == "" {
- return
- }
- remoteIPStr, _, err := net.SplitHostPort(ctx.Request.RemoteAddr())
- if err != nil {
- return
- }
- remoteIP := net.ParseIP(remoteIPStr)
- var ProxyList, ForwardedList []string
- var host, proto string
- if ctx.Request.Header().Get("Forwarded") != "" {
- ProxyList, ForwardedList, host, proto = c.getProxyListForwarder(remoteIP, ctx.Request)
- } else if ctx.Request.Header().Get("X-Forwarded-For") != "" {
- ProxyList, ForwardedList, host, proto = c.getProxyListFromXForwardedFor(remoteIP, ctx.Request)
- } else {
- host = ctx.Request.Header().Get("X-Forwarded-Host")
- proto = ctx.Request.Header().Get("X-Forwarded-Proto")
- if host == "" {
- host = ctx.Request.Host()
- }
- host, _ = utils.SplitHostPort(host) // 去除host中的端口号
- if proto == "http" || proto == "https" {
- if ctx.Request.IsTLS() {
- proto = "https"
- } else {
- proto = "http"
- }
- }
- ProxyList = append(make([]string, 0, 1), remoteIP.String())
- ForwardedList = append(make([]string, 0, 1),
- fmt.Sprintf("for=%s", remoteIP.String()),
- fmt.Sprintf("host=%s", host),
- fmt.Sprintf("proto=%s", proto))
- }
- ctx.ProxyRequest.Header.Set("Forwarded", strings.Join(ForwardedList, ", "))
- ctx.ProxyRequest.Header.Set("X-Forwarded-For", strings.Join(ProxyList, ", "))
- ctx.ProxyRequest.Header.Set("X-Forwarded-Host", host)
- ctx.ProxyRequest.Header.Set("X-Forwarded-Proto", proto)
- }
- func (c *CoreServer) getProxyListForwarder(remoteIP net.IP, r *readonlyrequest.ReadOnlyRequest) ([]string, []string, string, string) {
- ForwardedList := strings.Split(r.Header().Get("Forwarded"), ",")
- ProxyList := make([]string, 0, len(ForwardedList)+1)
- NewForwardedList := make([]string, 0, len(ForwardedList)+1)
- host, _ := utils.SplitHostPort(r.Host()) // 去除host中的端口号
- proto := "http"
- if r.IsTLS() {
- proto = "https"
- }
- for _, keyStr := range ForwardedList {
- kv := strings.Split(strings.ReplaceAll(keyStr, " ", ""), "=")
- if len(kv) != 2 {
- continue
- }
- if kv[0] == "for" {
- forIP := net.ParseIP(strings.TrimSpace(kv[1]))
- if forIP != nil {
- NewForwardedList = append(NewForwardedList, keyStr)
- ProxyList = append(ProxyList, forIP.String())
- } else if kv[1] == "_hidden" || kv[1] == "_secret" || kv[1] == "unknown" {
- NewForwardedList = append(NewForwardedList, keyStr)
- }
- } else if kv[0] == "by" {
- byIP := net.ParseIP(strings.TrimSpace(kv[1]))
- if byIP != nil || kv[1] == "_hidden" || kv[1] == "_secret" || kv[1] == "unknown" {
- NewForwardedList = append(NewForwardedList, keyStr)
- }
- } else if kv[0] == "host" {
- host = kv[1]
- } else if kv[0] == "proto" {
- proto = kv[1]
- }
- }
- ProxyList = append(ProxyList, remoteIP.String())
- NewForwardedList = append(NewForwardedList, fmt.Sprintf("for=%s", remoteIP.String()))
- NewForwardedList = append(NewForwardedList, fmt.Sprintf("host=%s", host))
- NewForwardedList = append(NewForwardedList, fmt.Sprintf("proto=%s", proto))
- return ProxyList, NewForwardedList, host, proto
- }
- func (c *CoreServer) getProxyListFromXForwardedFor(remoteIP net.IP, r *readonlyrequest.ReadOnlyRequest) ([]string, []string, string, string) {
- XFroWardedForList := strings.Split(r.Header().Get("X-Forwarded-For"), ",")
- ProxyList := make([]string, 0, len(XFroWardedForList)+1)
- NewForwardedList := make([]string, 0, len(XFroWardedForList)+1)
- for _, forIPStr := range XFroWardedForList {
- forIP := net.ParseIP(strings.TrimSpace(forIPStr))
- if forIP != nil {
- ProxyList = append(ProxyList, forIP.String())
- }
- }
- host := r.Header().Get("X-Forwarded-Host")
- proto := r.Header().Get("X-Forwarded-Proto")
- if host == "" {
- host = r.Host()
- }
- host, _ = utils.SplitHostPort(host) // 去除host中的端口号
- if proto == "http" || proto == "https" {
- if r.IsTLS() {
- proto = "https"
- } else {
- proto = "http"
- }
- }
- ProxyList = append(ProxyList, remoteIP.String())
- for _, ip := range ProxyList {
- NewForwardedList = append(NewForwardedList, fmt.Sprintf("for=%s", ip))
- }
- NewForwardedList = append(NewForwardedList, fmt.Sprintf("host=%s", host))
- NewForwardedList = append(NewForwardedList, fmt.Sprintf("proto=%s", proto))
- return ProxyList, NewForwardedList, host, proto
- }
|