From a06dc1eafaa571949e6f3d5fca1a00f0fc8960df Mon Sep 17 00:00:00 2001 From: XueBing Date: Sun, 18 Dec 2016 00:02:21 +0800 Subject: [PATCH] support the "custom_location" configure --- cross_compiles_package.sh | 8 ++++ src/cmd/frps/main.go | 7 +++- src/models/server/config.go | 12 ++++++ src/models/server/server.go | 9 +++++ src/utils/vhost/http.go | 9 ++++- src/utils/vhost/router.go | 79 +++++++++++++++++++++++++++++++++++++ src/utils/vhost/vhost.go | 11 ++++++ 7 files changed, 133 insertions(+), 2 deletions(-) create mode 100644 src/utils/vhost/router.go diff --git a/cross_compiles_package.sh b/cross_compiles_package.sh index 5cbe6a67..3d1aa3d0 100755 --- a/cross_compiles_package.sh +++ b/cross_compiles_package.sh @@ -17,6 +17,14 @@ mkdir ./packages os_all='linux windows darwin' arch_all='386 amd64 arm' +if [ $1 ];then + os_all=$1 +fi + +if [ $2 ];then + arch_all=$2 +fi + for os in $os_all; do for arch in $arch_all; do frp_dir_name="frp_${frp_version}_${os}_${arch}" diff --git a/src/cmd/frps/main.go b/src/cmd/frps/main.go index 8e94d8d5..af6a7161 100644 --- a/src/cmd/frps/main.go +++ b/src/cmd/frps/main.go @@ -151,7 +151,12 @@ func main() { log.Error("Create vhost http listener error, %v", err) os.Exit(1) } - server.VhostHttpMuxer, err = vhost.NewHttpMuxer(vhostListener, 30*time.Second) + + if server.VhostHttpRouters == nil { + server.VhostHttpMuxer, err = vhost.NewHttpMuxer(vhostListener, 30*time.Second) + } else { + server.VhostHttpMuxer, err = vhost.NewHttpMuxerWithRouter(vhostListener, 30*time.Second, server.VhostHttpRouters) + } if err != nil { log.Error("Create vhost httpMuxer error, %v", err) } diff --git a/src/models/server/config.go b/src/models/server/config.go index e3296d05..7b0c8da1 100644 --- a/src/models/server/config.go +++ b/src/models/server/config.go @@ -54,6 +54,8 @@ var ( VhostHttpsMuxer *vhost.HttpsMuxer ProxyServers map[string]*ProxyServer = make(map[string]*ProxyServer) // all proxy servers info and resources ProxyServersMutex sync.RWMutex + + VhostHttpRouters *vhost.VhostRouters ) func LoadConf(confFile string) (err error) { @@ -272,6 +274,16 @@ func loadProxyConf(confFile string) (proxyServers map[string]*ProxyServer, err e } else { return proxyServers, fmt.Errorf("Parse conf error: proxy [%s] custom_domains must be set when type equals http", proxyServer.Name) } + + //location + locStr, loc_ok := section["custom_location"] + if loc_ok { + if VhostHttpRouters == nil { + VhostHttpRouters = vhost.NewVhostRouters() + } + proxyServer.Locations = strings.Split(locStr, ",") + VhostHttpRouters.Add(proxyServer.Name, proxyServer.CustomDomains, proxyServer.Locations) + } } else if proxyServer.Type == "https" { // for https proxyServer.ListenPort = VhostHttpsPort diff --git a/src/models/server/server.go b/src/models/server/server.go index d1502116..a5e3aa70 100644 --- a/src/models/server/server.go +++ b/src/models/server/server.go @@ -37,6 +37,7 @@ type ProxyServer struct { BindAddr string ListenPort int64 CustomDomains []string + Locations []string Status int64 CtlConn *conn.Conn // control connection with frpc @@ -99,6 +100,14 @@ func (p *ProxyServer) Compare(p2 *ProxyServer) bool { return false } } + if len(p.Locations) != len(p2.Locations) { + return false + } + for i, _ := range p.Locations { + if p.Locations[i] != p2.Locations[i] { + return false + } + } return true } diff --git a/src/utils/vhost/http.go b/src/utils/vhost/http.go index 0d1d8e07..2ac5da1a 100644 --- a/src/utils/vhost/http.go +++ b/src/utils/vhost/http.go @@ -41,7 +41,8 @@ func GetHttpHostname(c *conn.Conn) (_ net.Conn, routerName string, err error) { return sc, "", err } tmpArr := strings.Split(request.Host, ":") - routerName = tmpArr[0] + //routerName = tmpArr[0] + routerName = tmpArr[0] + ":" + request.URL.Path request.Body.Close() return sc, routerName, nil } @@ -51,6 +52,12 @@ func NewHttpMuxer(listener *conn.Listener, timeout time.Duration) (*HttpMuxer, e return &HttpMuxer{mux}, err } +func NewHttpMuxerWithRouter(listener *conn.Listener, timeout time.Duration, r *VhostRouters) (*HttpMuxer, error) { + mux, err := NewVhostMuxer(listener, GetHttpHostname, HttpHostNameRewrite, timeout) + mux.routers = r + return &HttpMuxer{mux}, err +} + func HttpHostNameRewrite(c *conn.Conn, rewriteHost string) (_ net.Conn, err error) { sc, rd := newShareConn(c.TcpConn) var buff []byte diff --git a/src/utils/vhost/router.go b/src/utils/vhost/router.go new file mode 100644 index 00000000..a81d6eb8 --- /dev/null +++ b/src/utils/vhost/router.go @@ -0,0 +1,79 @@ +package vhost + +import ( + "sort" + "strings" + "sync" +) + +type VhostRouters struct { + RouterByDomain map[string][]*VhostRouter + mutex sync.RWMutex +} + +type VhostRouter struct { + Name string + Domain string + Location string +} + +func NewVhostRouters() *VhostRouters { + return &VhostRouters{ + RouterByDomain: make(map[string][]*VhostRouter), + } +} + +//sort by location +type ByLocation []*VhostRouter + +func (a ByLocation) Len() int { + return len(a) +} +func (a ByLocation) Swap(i, j int) { + a[i], a[j] = a[j], a[i] +} +func (a ByLocation) Less(i, j int) bool { + return strings.Compare(a[i].Location, a[j].Location) < 0 +} + +func (r *VhostRouters) Add(name string, domains, locations []string) { + r.mutex.Lock() + defer r.mutex.Unlock() + + for _, domain := range domains { + vrs, found := r.RouterByDomain[name] + if !found { + vrs = make([]*VhostRouter, 0) + } + + for _, loc := range locations { + vr := &VhostRouter{ + Name: name, + Domain: domain, + Location: loc, + } + vrs = append(vrs, vr) + } + + sort_vrs := sort.Reverse(ByLocation(vrs)) + r.RouterByDomain[name] = sort_vrs.(ByLocation) + } +} + +func (r *VhostRouters) getName(domain, url string) (name string, exist bool) { + r.mutex.RLock() + defer r.mutex.RUnlock() + + vrs, exist := r.RouterByDomain[domain] + if !exist { + return + } + + for _, vr := range vrs { + if strings.HasPrefix(url, vr.Location+"/") { + return vr.Name, true + } + } + + return +} diff --git a/src/utils/vhost/vhost.go b/src/utils/vhost/vhost.go index 93279b3b..f7849ac1 100644 --- a/src/utils/vhost/vhost.go +++ b/src/utils/vhost/vhost.go @@ -35,6 +35,7 @@ type VhostMuxer struct { vhostFunc muxFunc rewriteFunc hostRewriteFunc registryMap map[string]*Listener + routers *VhostRouters mutex sync.RWMutex } @@ -71,6 +72,16 @@ func (v *VhostMuxer) Listen(name string, rewriteHost string) (l *Listener, err e func (v *VhostMuxer) getListener(name string) (l *Listener, exist bool) { v.mutex.RLock() defer v.mutex.RUnlock() + + if v.routers != nil { + tmparray := strings.SplitN(name, ":", 2) + if len(tmparray) == 2 { + newname, found := v.routers.getName(tmparray[0], tmparray[1]) + if found { + name = newname + } + } + } l, exist = v.registryMap[name] return l, exist }