mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-24 13:58:12 -05:00
move MultiHostReverseProxy logic away from the server command
This commit is contained in:
@@ -2,9 +2,6 @@ package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
gohttp "net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
@@ -21,18 +18,13 @@ import (
|
||||
"github.com/owncloud/ocis-proxy/pkg/config"
|
||||
"github.com/owncloud/ocis-proxy/pkg/flagset"
|
||||
"github.com/owncloud/ocis-proxy/pkg/metrics"
|
||||
"github.com/owncloud/ocis-proxy/pkg/proxy"
|
||||
"github.com/owncloud/ocis-proxy/pkg/server/debug"
|
||||
"github.com/owncloud/ocis-proxy/pkg/server/http"
|
||||
"go.opencensus.io/stats/view"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// ReverseProxy extends httputil to support multiple hosts with diffent policies
|
||||
type ReverseProxy struct {
|
||||
httputil.ReverseProxy
|
||||
Directors map[string]map[string]func(req *gohttp.Request)
|
||||
}
|
||||
|
||||
// Server is the entrypoint for the server command.
|
||||
func Server(cfg *config.Config) *cli.Command {
|
||||
return &cli.Command{
|
||||
@@ -142,7 +134,7 @@ func Server(cfg *config.Config) *cli.Command {
|
||||
|
||||
defer cancel()
|
||||
|
||||
rp := NewMultiHostReverseProxy(cfg)
|
||||
rp := proxy.NewMultiHostReverseProxy(cfg)
|
||||
|
||||
{
|
||||
server, err := http.Server(
|
||||
@@ -232,74 +224,3 @@ func Server(cfg *config.Config) *cli.Command {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// NewMultiHostReverseProxy undocummented
|
||||
func NewMultiHostReverseProxy(conf *config.Config) *ReverseProxy {
|
||||
reverseProxy := &ReverseProxy{Directors: make(map[string]map[string]func(req *gohttp.Request))}
|
||||
|
||||
for _, policy := range conf.Policies {
|
||||
for _, route := range policy.Routes {
|
||||
uri, err := url.Parse(route.Backend)
|
||||
if err != nil { /* do something with err */
|
||||
}
|
||||
reverseProxy.AddHost(policy.Name, uri, route.Endpoint)
|
||||
}
|
||||
}
|
||||
|
||||
return reverseProxy
|
||||
}
|
||||
|
||||
func singleJoiningSlash(a, b string) string {
|
||||
aslash := strings.HasSuffix(a, "/")
|
||||
bslash := strings.HasPrefix(b, "/")
|
||||
switch {
|
||||
case aslash && bslash:
|
||||
return a + b[1:]
|
||||
case !aslash && !bslash:
|
||||
return a + "/" + b
|
||||
}
|
||||
return a + b
|
||||
}
|
||||
|
||||
// AddHost undocumented
|
||||
func (p *ReverseProxy) AddHost(policy string, target *url.URL, endpoint string) {
|
||||
targetQuery := target.RawQuery
|
||||
if p.Directors[policy] == nil {
|
||||
p.Directors[policy] = make(map[string]func(req *gohttp.Request))
|
||||
}
|
||||
p.Directors[policy][endpoint] = func(req *gohttp.Request) {
|
||||
req.URL.Scheme = target.Scheme
|
||||
req.URL.Host = target.Host
|
||||
req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path)
|
||||
if targetQuery == "" || req.URL.RawQuery == "" {
|
||||
req.URL.RawQuery = targetQuery + req.URL.RawQuery
|
||||
} else {
|
||||
req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
|
||||
}
|
||||
if _, ok := req.Header["User-Agent"]; !ok {
|
||||
// explicitly disable User-Agent so it's not set to default value
|
||||
req.Header.Set("User-Agent", "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ReverseProxy) ServeHTTP(rw gohttp.ResponseWriter, req *gohttp.Request) {
|
||||
// TODO need to fetch from the accounts service
|
||||
policy := "reva"
|
||||
var hit bool
|
||||
|
||||
for k := range p.Directors[policy] {
|
||||
if strings.HasPrefix(req.URL.Path, k) && k != "/" {
|
||||
p.Director = p.Directors[policy][k]
|
||||
hit = true
|
||||
}
|
||||
}
|
||||
|
||||
// override default director with root. If any
|
||||
if !hit && p.Directors[policy]["/"] != nil {
|
||||
p.Director = p.Directors[policy]["/"]
|
||||
}
|
||||
|
||||
// Call upstream ServeHTTP
|
||||
p.ReverseProxy.ServeHTTP(rw, req)
|
||||
}
|
||||
|
||||
87
pkg/proxy/proxy.go
Normal file
87
pkg/proxy/proxy.go
Normal file
@@ -0,0 +1,87 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/owncloud/ocis-proxy/pkg/config"
|
||||
)
|
||||
|
||||
// MultiHostReverseProxy extends httputil to support multiple hosts with diffent policies
|
||||
type MultiHostReverseProxy struct {
|
||||
httputil.ReverseProxy
|
||||
Directors map[string]map[string]func(req *http.Request)
|
||||
}
|
||||
|
||||
// NewMultiHostReverseProxy undocummented
|
||||
func NewMultiHostReverseProxy(conf *config.Config) *MultiHostReverseProxy {
|
||||
reverseProxy := &MultiHostReverseProxy{Directors: make(map[string]map[string]func(req *http.Request))}
|
||||
|
||||
for _, policy := range conf.Policies {
|
||||
for _, route := range policy.Routes {
|
||||
uri, err := url.Parse(route.Backend)
|
||||
if err != nil { /* do something with err */
|
||||
}
|
||||
reverseProxy.AddHost(policy.Name, uri, route.Endpoint)
|
||||
}
|
||||
}
|
||||
|
||||
return reverseProxy
|
||||
}
|
||||
|
||||
func singleJoiningSlash(a, b string) string {
|
||||
aslash := strings.HasSuffix(a, "/")
|
||||
bslash := strings.HasPrefix(b, "/")
|
||||
switch {
|
||||
case aslash && bslash:
|
||||
return a + b[1:]
|
||||
case !aslash && !bslash:
|
||||
return a + "/" + b
|
||||
}
|
||||
return a + b
|
||||
}
|
||||
|
||||
// AddHost undocumented
|
||||
func (p *MultiHostReverseProxy) AddHost(policy string, target *url.URL, endpoint string) {
|
||||
targetQuery := target.RawQuery
|
||||
if p.Directors[policy] == nil {
|
||||
p.Directors[policy] = make(map[string]func(req *http.Request))
|
||||
}
|
||||
p.Directors[policy][endpoint] = func(req *http.Request) {
|
||||
req.URL.Scheme = target.Scheme
|
||||
req.URL.Host = target.Host
|
||||
req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path)
|
||||
if targetQuery == "" || req.URL.RawQuery == "" {
|
||||
req.URL.RawQuery = targetQuery + req.URL.RawQuery
|
||||
} else {
|
||||
req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
|
||||
}
|
||||
if _, ok := req.Header["User-Agent"]; !ok {
|
||||
// explicitly disable User-Agent so it's not set to default value
|
||||
req.Header.Set("User-Agent", "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *MultiHostReverseProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
// TODO need to fetch from the accounts service
|
||||
policy := "reva"
|
||||
var hit bool
|
||||
|
||||
for k := range p.Directors[policy] {
|
||||
if strings.HasPrefix(r.URL.Path, k) && k != "/" {
|
||||
p.Director = p.Directors[policy][k]
|
||||
hit = true
|
||||
}
|
||||
}
|
||||
|
||||
// override default director with root. If any
|
||||
if !hit && p.Directors[policy]["/"] != nil {
|
||||
p.Director = p.Directors[policy]["/"]
|
||||
}
|
||||
|
||||
// Call upstream ServeHTTP
|
||||
p.ReverseProxy.ServeHTTP(w, r)
|
||||
}
|
||||
Reference in New Issue
Block a user