Skip to content
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

Fix matching priority for host:port tuples #675

Merged
merged 1 commit into from
Jul 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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