Skip to content

Commit

Permalink
Fix matching priority for host:port tuples (#675)
Browse files Browse the repository at this point in the history
e566aaa reversed DNS names since they have
their most significant part at the front. Unfortunately it didn't
consider cases where the name is followed by a :port, making names
without port always take precedence over names with a port.

This patch changes the reverse function to ignores such port suffixes.

Signed-off-by: Peter Schultz <peter.schultz@classmarkets.com>
  • Loading branch information
pschultz authored and Aaron Hurt committed Jul 16, 2019
1 parent 91baae6 commit 8494d3f
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 8 deletions.
27 changes: 19 additions & 8 deletions route/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"log"
"net"
"net/http"
"net/url"
"sort"
Expand Down Expand Up @@ -341,11 +342,11 @@ func (t Table) matchingHosts(req *http.Request) (hosts []string) {
// the correct result we need to reverse the strings, sort them and then
// reverse them again.
for i, h := range hosts {
hosts[i] = Reverse(h)
hosts[i] = ReverseHostPort(h)
}
sort.Sort(sort.Reverse(sort.StringSlice(hosts)))
for i, h := range hosts {
hosts[i] = Reverse(h)
hosts[i] = ReverseHostPort(h)
}
return
}
Expand All @@ -368,15 +369,25 @@ func (t Table) matchingHostNoGlob(req *http.Request) (hosts []string) {
return
}

// Reverse returns its argument string reversed rune-wise left to right.
//
// taken from https://github.com/golang/example/blob/master/stringutil/reverse.go
func Reverse(s string) string {
r := []rune(s)
// ReverseHostPort returns its argument string reversed rune-wise left to
// right. If s includes a port, only the host part is reversed.
func ReverseHostPort(s string) string {
h, p, _ := net.SplitHostPort(s)
if h == "" {
h = s
}

// Taken from https://github.com/golang/example/blob/master/stringutil/reverse.go
r := []rune(h)
for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
r[i], r[j] = r[j], r[i]
}
return string(r)

if p == "" {
return string(r)
} else {
return net.JoinHostPort(string(r), p)
}
}

// Lookup finds a target url based on the current matcher and picker
Expand Down
27 changes: 27 additions & 0 deletions route/table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"math"
"net/http"
"net/http/httptest"
"reflect"
"strconv"
"strings"
Expand Down Expand Up @@ -641,6 +642,32 @@ func TestTableLookup(t *testing.T) {
}
}

func TestTableLookup_656(t *testing.T) {
// A typical HTTPS redirect
s := `
route add my-service example.com:80/ https://example.com$path opts "redirect=301"
route add my-service example.com/ http://127.0.0.1:3000/
`

tbl, err := NewTable(bytes.NewBufferString(s))
if err != nil {
t.Fatal(err)
}

req := httptest.NewRequest("GET", "http://example.com/foo", nil)
target := tbl.Lookup(req, "redirect", rrPicker, prefixMatcher, false)

if target == nil {
t.Fatal("No route match")
}
if got, want := target.RedirectCode, 301; got != want {
t.Errorf("target.RedirectCode = %d, want %d", got, want)
}
if got, want := fmt.Sprint(target.RedirectURL), "https://example.com/foo"; got != want {
t.Errorf("target.RedirectURL = %s, want %s", got, want)
}
}

func TestNewTableCustom(t *testing.T) {

var routes []RouteDef
Expand Down

0 comments on commit 8494d3f

Please sign in to comment.