-
Notifications
You must be signed in to change notification settings - Fork 616
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement redirect capability #395
Changes from 1 commit
cf30c15
2f2ce08
1da6bff
d1259f8
1e83fa7
1d78ef8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,6 +47,12 @@ func TestParseTag(t *testing.T) { | |
route: "xx/Yy", | ||
ok: true, | ||
}, | ||
{ | ||
tag: "p-www.bar.com:80/foo https://www.bar.com/ redirect=302", | ||
route: "www.bar.com:80/foo", | ||
opts: "https://www.bar.com/ redirect=302", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, I forgot that we need to be able to specify the redirect target. How about this?
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure I can do that syntax for the consul service tags. |
||
ok: true, | ||
}, | ||
} | ||
|
||
for i, tt := range tests { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -119,6 +119,8 @@ func serviceConfig(client *api.Client, name string, passing map[string]bool, tag | |
dst := "http://" + addr + "/" | ||
for _, o := range strings.Fields(opts) { | ||
switch { | ||
case strings.Contains(o, "://"): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This would then also become more obvious by looking for |
||
dst = o | ||
case o == "proto=tcp": | ||
dst = "tcp://" + addr | ||
case o == "proto=https": | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ import ( | |
"net/url" | ||
"reflect" | ||
"sort" | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/fabiolb/fabio/metrics" | ||
|
@@ -68,6 +69,7 @@ func (r *Route) addTarget(service string, targetURL *url.URL, fixedWeight float6 | |
t.StripPath = opts["strip"] | ||
t.TLSSkipVerify = opts["tlsskipverify"] == "true" | ||
t.Host = opts["host"] | ||
t.RedirectCode, _ = strconv.Atoi(opts["redirect"]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we log the error or catch this somewhere sooner and log it there? |
||
} | ||
|
||
r.Targets = append(r.Targets, t) | ||
|
@@ -134,7 +136,12 @@ func contains(src, dst []string) bool { | |
} | ||
|
||
func (r *Route) TargetConfig(t *Target, addWeight bool) string { | ||
s := fmt.Sprintf("route add %s %s %s", t.Service, r.Host+r.Path, t.URL) | ||
s := fmt.Sprintf("route add %s %s", t.Service, r.Host+r.Path) | ||
if t.RedirectCode != 0 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is still using the old syntax |
||
s += fmt.Sprintf(" %d|%s", t.RedirectCode, t.URL) | ||
} else { | ||
s += fmt.Sprintf(" %s", t.URL) | ||
} | ||
if addWeight { | ||
s += fmt.Sprintf(" weight %2.4f", t.Weight) | ||
} else if t.FixedWeight > 0 { | ||
|
@@ -215,7 +222,7 @@ func (r *Route) weighTargets() { | |
} | ||
|
||
// compute the weight for the targets with dynamic weights | ||
dynamic := (1 - sumFixed) / float64(len(r.Targets)-nFixed) | ||
dynamic := float64(1-sumFixed) / float64(len(r.Targets)-nFixed) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. gofmt? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you divide something by a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, this makes sense. My bad. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No worries. You live and learn :) |
||
if dynamic < 0 { | ||
dynamic = 0 | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -273,8 +273,8 @@ func (t Table) route(host, path string) *Route { | |
|
||
// normalizeHost returns the hostname from the request | ||
// and removes the default port if present. | ||
func normalizeHost(req *http.Request) string { | ||
host := strings.ToLower(req.Host) | ||
func normalizeHost(host string, req *http.Request) string { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The reason I've passed in func normalizeHost(host string, tls bool) string {
host = strings.ToLower(host)
if !tls && strings.HasSuffix(host, ":80") {
return host[:len(host)-len(":80")]
}
if tls && strings.HasSuffix(host, ":443") {
return host[:len(host)-len(":443")]
}
return host
}
...
normalizeHost(req.Host, req.TLS != nil) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup, good call. |
||
host = strings.ToLower(host) | ||
if req.TLS == nil && strings.HasSuffix(host, ":80") { | ||
return host[:len(host)-len(":80")] | ||
} | ||
|
@@ -287,9 +287,10 @@ func normalizeHost(req *http.Request) string { | |
// matchingHosts returns all keys (host name patterns) from the | ||
// routing table which match the normalized request hostname. | ||
func (t Table) matchingHosts(req *http.Request) (hosts []string) { | ||
host := normalizeHost(req) | ||
host := normalizeHost(req.Host, req) | ||
for pattern := range t { | ||
if glob.Glob(pattern, host) { | ||
normpat := normalizeHost(pattern, req) | ||
if glob.Glob(normpat, host) { | ||
hosts = append(hosts, pattern) | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -416,6 +416,9 @@ func TestTableParse(t *testing.T) { | |
targetURLs := make([]string, len(r.wTargets)) | ||
for i, tg := range r.wTargets { | ||
targetURLs[i] = tg.URL.Scheme + "://" + tg.URL.Host + tg.URL.Path | ||
if tg.RedirectCode != 0 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. old syntax here as well |
||
targetURLs[i] = fmt.Sprintf("%d|%s", tg.RedirectCode, targetURLs[i]) | ||
} | ||
} | ||
|
||
// count how often the 'url' from 'route add svc <path> <url>' | ||
|
@@ -477,7 +480,7 @@ func TestNormalizeHost(t *testing.T) { | |
} | ||
|
||
for i, tt := range tests { | ||
if got, want := normalizeHost(tt.req), tt.host; got != want { | ||
if got, want := normalizeHost(tt.req.Host, tt.req), tt.host; got != want { | ||
t.Errorf("%d: got %v want %v", i, got, want) | ||
} | ||
} | ||
|
@@ -495,6 +498,7 @@ func TestTableLookup(t *testing.T) { | |
route add svc z.abc.com/foo/ http://foo.com:3100 | ||
route add svc *.abc.com/ http://foo.com:4000 | ||
route add svc *.abc.com/foo/ http://foo.com:5000 | ||
route add svc xyz.com:80/ https://xyz.com | ||
` | ||
|
||
tbl, err := NewTable(s) | ||
|
@@ -539,6 +543,9 @@ func TestTableLookup(t *testing.T) { | |
|
||
// exact match has precedence over glob match | ||
{&http.Request{Host: "z.abc.com", URL: mustParse("/foo/")}, "http://foo.com:3100"}, | ||
|
||
// explicit port on route | ||
{&http.Request{Host: "xyz.com", URL: mustParse("/")}, "https://xyz.com"}, | ||
} | ||
|
||
for i, tt := range tests { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,6 +33,9 @@ type Target struct { | |
// URL is the endpoint the service instance listens on | ||
URL *url.URL | ||
|
||
// RedirectCode is the HTTP status code used for redirects. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. // RedirectCode is the HTTP status code used for redirects.
// When set to a value > 0 the client is redirected to the target url. |
||
RedirectCode int | ||
|
||
// FixedWeight is the weight assigned to this target. | ||
// If the value is 0 the targets weight is dynamic. | ||
FixedWeight float64 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
old syntax