-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathheaderproxy.go
More file actions
88 lines (77 loc) · 2.2 KB
/
Copy pathheaderproxy.go
File metadata and controls
88 lines (77 loc) · 2.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package headerproxy
import (
"context"
"net/http"
"net/http/httputil"
"net/url"
)
// Service struct
type Service struct {
Destination string `yaml:"Destination"`
}
// Tenant struct
type Tenant struct {
Services map[string]Service `yaml:"Services"`
}
type Header struct {
TenantHeader string `yaml:"TenantHeader"`
ServiceHeader string `yaml:"ServiceHeader"`
}
// Config struct holds configuration to be passed to the plugin
type Config struct {
Tenants map[string]Tenant // `yaml:"Tenants"`
Headers []Header
}
// CreateConfig creates the default plugin configuration.
func CreateConfig() *Config {
return &Config{
// Tenants: []Tenant{},
Tenants: map[string]Tenant{},
Headers: []Header{},
}
}
// HostReplacement holds the necessary components of a Traefik plugin
type HostReplacement struct {
tenants map[string]Tenant
headers []Header
next http.Handler
name string
}
// New instantiates and returns the required components used to handle a HTTP request
func New(ctx context.Context, next http.Handler, config *Config, name string) (http.Handler, error) {
return &HostReplacement{
tenants: config.Tenants,
headers: config.Headers,
next: next,
name: name,
}, nil
}
// Iterate over headers (if provided in the configuration) to match the ones that come in the request &
// match the headers & send a request to a specified tenant and service configuration
func (u *HostReplacement) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
for _, header := range u.headers {
tenant, TenantHeaderExist := u.tenants[req.Header.Get(header.TenantHeader)]
if TenantHeaderExist {
service, ServiceHeaderExist := tenant.Services[req.Header.Get(header.ServiceHeader)]
if ServiceHeaderExist {
ProxyReq(rw, req, service)
} else {
u.next.ServeHTTP(rw, req)
}
} else {
u.next.ServeHTTP(rw, req)
}
}
}
// Send the request
func ProxyReq(rw http.ResponseWriter, req *http.Request, service Service) {
director := func(req *http.Request) {
address := service.Destination
dest, _ := url.Parse(address)
req.Header.Add("X-Origin-Host", dest.Host)
req.URL.Scheme = dest.Scheme
req.URL.Host = dest.Host
}
proxy := &httputil.ReverseProxy{Director: director}
proxy.ServeHTTP(rw, req)
}